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