1; RUN: llc < %s -mtriple=arm64-apple-ios -asm-verbose=false | FileCheck %s 2 3define float @load0(i16* nocapture readonly %a) nounwind { 4; CHECK-LABEL: load0: 5; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0] 6; CHECK-NEXT: fcvt s0, [[HREG]] 7; CHECK-NEXT: ret 8 9 %tmp = load i16* %a, align 2 10 %tmp1 = tail call float @llvm.convert.from.fp16(i16 %tmp) 11 ret float %tmp1 12} 13 14define double @load1(i16* nocapture readonly %a) nounwind { 15; CHECK-LABEL: load1: 16; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0] 17; CHECK-NEXT: fcvt d0, [[HREG]] 18; CHECK-NEXT: ret 19 20 %tmp = load i16* %a, align 2 21 %tmp1 = tail call float @llvm.convert.from.fp16(i16 %tmp) 22 %conv = fpext float %tmp1 to double 23 ret double %conv 24} 25 26define float @load2(i16* nocapture readonly %a, i32 %i) nounwind { 27; CHECK-LABEL: load2: 28; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, w1, sxtw #1] 29; CHECK-NEXT: fcvt s0, [[HREG]] 30; CHECK-NEXT: ret 31 32 %idxprom = sext i32 %i to i64 33 %arrayidx = getelementptr inbounds i16* %a, i64 %idxprom 34 %tmp = load i16* %arrayidx, align 2 35 %tmp1 = tail call float @llvm.convert.from.fp16(i16 %tmp) 36 ret float %tmp1 37} 38 39define double @load3(i16* nocapture readonly %a, i32 %i) nounwind { 40; CHECK-LABEL: load3: 41; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, w1, sxtw #1] 42; CHECK-NEXT: fcvt d0, [[HREG]] 43; CHECK-NEXT: ret 44 45 %idxprom = sext i32 %i to i64 46 %arrayidx = getelementptr inbounds i16* %a, i64 %idxprom 47 %tmp = load i16* %arrayidx, align 2 48 %tmp1 = tail call float @llvm.convert.from.fp16(i16 %tmp) 49 %conv = fpext float %tmp1 to double 50 ret double %conv 51} 52 53define float @load4(i16* nocapture readonly %a, i64 %i) nounwind { 54; CHECK-LABEL: load4: 55; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, x1, lsl #1] 56; CHECK-NEXT: fcvt s0, [[HREG]] 57; CHECK-NEXT: ret 58 59 %arrayidx = getelementptr inbounds i16* %a, i64 %i 60 %tmp = load i16* %arrayidx, align 2 61 %tmp1 = tail call float @llvm.convert.from.fp16(i16 %tmp) 62 ret float %tmp1 63} 64 65define double @load5(i16* nocapture readonly %a, i64 %i) nounwind { 66; CHECK-LABEL: load5: 67; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, x1, lsl #1] 68; CHECK-NEXT: fcvt d0, [[HREG]] 69; CHECK-NEXT: ret 70 71 %arrayidx = getelementptr inbounds i16* %a, i64 %i 72 %tmp = load i16* %arrayidx, align 2 73 %tmp1 = tail call float @llvm.convert.from.fp16(i16 %tmp) 74 %conv = fpext float %tmp1 to double 75 ret double %conv 76} 77 78define float @load6(i16* nocapture readonly %a) nounwind { 79; CHECK-LABEL: load6: 80; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, #20] 81; CHECK-NEXT: fcvt s0, [[HREG]] 82; CHECK-NEXT: ret 83 84 %arrayidx = getelementptr inbounds i16* %a, i64 10 85 %tmp = load i16* %arrayidx, align 2 86 %tmp1 = tail call float @llvm.convert.from.fp16(i16 %tmp) 87 ret float %tmp1 88} 89 90define double @load7(i16* nocapture readonly %a) nounwind { 91; CHECK-LABEL: load7: 92; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, #20] 93; CHECK-NEXT: fcvt d0, [[HREG]] 94; CHECK-NEXT: ret 95 96 %arrayidx = getelementptr inbounds i16* %a, i64 10 97 %tmp = load i16* %arrayidx, align 2 98 %tmp1 = tail call float @llvm.convert.from.fp16(i16 %tmp) 99 %conv = fpext float %tmp1 to double 100 ret double %conv 101} 102 103define float @load8(i16* nocapture readonly %a) nounwind { 104; CHECK-LABEL: load8: 105; CHECK-NEXT: ldur [[HREG:h[0-9]+]], [x0, #-20] 106; CHECK-NEXT: fcvt s0, [[HREG]] 107; CHECK-NEXT: ret 108 109 %arrayidx = getelementptr inbounds i16* %a, i64 -10 110 %tmp = load i16* %arrayidx, align 2 111 %tmp1 = tail call float @llvm.convert.from.fp16(i16 %tmp) 112 ret float %tmp1 113} 114 115define double @load9(i16* nocapture readonly %a) nounwind { 116; CHECK-LABEL: load9: 117; CHECK-NEXT: ldur [[HREG:h[0-9]+]], [x0, #-20] 118; CHECK-NEXT: fcvt d0, [[HREG]] 119; CHECK-NEXT: ret 120 121 %arrayidx = getelementptr inbounds i16* %a, i64 -10 122 %tmp = load i16* %arrayidx, align 2 123 %tmp1 = tail call float @llvm.convert.from.fp16(i16 %tmp) 124 %conv = fpext float %tmp1 to double 125 ret double %conv 126} 127 128define void @store0(i16* nocapture %a, float %val) nounwind { 129; CHECK-LABEL: store0: 130; CHECK-NEXT: fcvt h0, s0 131; CHECK-NEXT: str h0, [x0] 132; CHECK-NEXT: ret 133 134 %tmp = tail call i16 @llvm.convert.to.fp16(float %val) 135 store i16 %tmp, i16* %a, align 2 136 ret void 137} 138 139define void @store1(i16* nocapture %a, double %val) nounwind { 140; CHECK-LABEL: store1: 141; CHECK-NEXT: fcvt h0, d0 142; CHECK-NEXT: str h0, [x0] 143; CHECK-NEXT: ret 144 145 %conv = fptrunc double %val to float 146 %tmp = tail call i16 @llvm.convert.to.fp16(float %conv) 147 store i16 %tmp, i16* %a, align 2 148 ret void 149} 150 151define void @store2(i16* nocapture %a, i32 %i, float %val) nounwind { 152; CHECK-LABEL: store2: 153; CHECK-NEXT: fcvt h0, s0 154; CHECK-NEXT: str h0, [x0, w1, sxtw #1] 155; CHECK-NEXT: ret 156 157 %tmp = tail call i16 @llvm.convert.to.fp16(float %val) 158 %idxprom = sext i32 %i to i64 159 %arrayidx = getelementptr inbounds i16* %a, i64 %idxprom 160 store i16 %tmp, i16* %arrayidx, align 2 161 ret void 162} 163 164define void @store3(i16* nocapture %a, i32 %i, double %val) nounwind { 165; CHECK-LABEL: store3: 166; CHECK-NEXT: fcvt h0, d0 167; CHECK-NEXT: str h0, [x0, w1, sxtw #1] 168; CHECK-NEXT: ret 169 170 %conv = fptrunc double %val to float 171 %tmp = tail call i16 @llvm.convert.to.fp16(float %conv) 172 %idxprom = sext i32 %i to i64 173 %arrayidx = getelementptr inbounds i16* %a, i64 %idxprom 174 store i16 %tmp, i16* %arrayidx, align 2 175 ret void 176} 177 178define void @store4(i16* nocapture %a, i64 %i, float %val) nounwind { 179; CHECK-LABEL: store4: 180; CHECK-NEXT: fcvt h0, s0 181; CHECK-NEXT: str h0, [x0, x1, lsl #1] 182; CHECK-NEXT: ret 183 184 %tmp = tail call i16 @llvm.convert.to.fp16(float %val) 185 %arrayidx = getelementptr inbounds i16* %a, i64 %i 186 store i16 %tmp, i16* %arrayidx, align 2 187 ret void 188} 189 190define void @store5(i16* nocapture %a, i64 %i, double %val) nounwind { 191; CHECK-LABEL: store5: 192; CHECK-NEXT: fcvt h0, d0 193; CHECK-NEXT: str h0, [x0, x1, lsl #1] 194; CHECK-NEXT: ret 195 196 %conv = fptrunc double %val to float 197 %tmp = tail call i16 @llvm.convert.to.fp16(float %conv) 198 %arrayidx = getelementptr inbounds i16* %a, i64 %i 199 store i16 %tmp, i16* %arrayidx, align 2 200 ret void 201} 202 203define void @store6(i16* nocapture %a, float %val) nounwind { 204; CHECK-LABEL: store6: 205; CHECK-NEXT: fcvt h0, s0 206; CHECK-NEXT: str h0, [x0, #20] 207; CHECK-NEXT: ret 208 209 %tmp = tail call i16 @llvm.convert.to.fp16(float %val) 210 %arrayidx = getelementptr inbounds i16* %a, i64 10 211 store i16 %tmp, i16* %arrayidx, align 2 212 ret void 213} 214 215define void @store7(i16* nocapture %a, double %val) nounwind { 216; CHECK-LABEL: store7: 217; CHECK-NEXT: fcvt h0, d0 218; CHECK-NEXT: str h0, [x0, #20] 219; CHECK-NEXT: ret 220 221 %conv = fptrunc double %val to float 222 %tmp = tail call i16 @llvm.convert.to.fp16(float %conv) 223 %arrayidx = getelementptr inbounds i16* %a, i64 10 224 store i16 %tmp, i16* %arrayidx, align 2 225 ret void 226} 227 228define void @store8(i16* nocapture %a, float %val) nounwind { 229; CHECK-LABEL: store8: 230; CHECK-NEXT: fcvt h0, s0 231; CHECK-NEXT: stur h0, [x0, #-20] 232; CHECK-NEXT: ret 233 234 %tmp = tail call i16 @llvm.convert.to.fp16(float %val) 235 %arrayidx = getelementptr inbounds i16* %a, i64 -10 236 store i16 %tmp, i16* %arrayidx, align 2 237 ret void 238} 239 240define void @store9(i16* nocapture %a, double %val) nounwind { 241; CHECK-LABEL: store9: 242; CHECK-NEXT: fcvt h0, d0 243; CHECK-NEXT: stur h0, [x0, #-20] 244; CHECK-NEXT: ret 245 246 %conv = fptrunc double %val to float 247 %tmp = tail call i16 @llvm.convert.to.fp16(float %conv) 248 %arrayidx = getelementptr inbounds i16* %a, i64 -10 249 store i16 %tmp, i16* %arrayidx, align 2 250 ret void 251} 252 253declare i16 @llvm.convert.to.fp16(float) nounwind readnone 254declare float @llvm.convert.from.fp16(i16) nounwind readnone 255