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* %a, align 2 10 %tmp1 = tail call float @llvm.convert.from.fp16(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* %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 26 define 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 39 define 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 53 define 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 65 define 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 78 define 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 90 define 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 103 define 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 115 define 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 128 define 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 139 define 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 151 define 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 164 define 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 178 define 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 190 define 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 203 define 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 215 define 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 228 define 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 240 define 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 253 declare i16 @llvm.convert.to.fp16(float) nounwind readnone 254 declare float @llvm.convert.from.fp16(i16) nounwind readnone 255