1 ; RUN: llc -O0 -fast-isel-abort=1 -verify-machineinstrs -mtriple=arm64-apple-darwin -mcpu=cyclone < %s | FileCheck %s 2 3 ;; Test various conversions. 4 define zeroext i32 @trunc_(i8 zeroext %a, i16 zeroext %b, i32 %c, i64 %d) nounwind ssp { 5 entry: 6 ; CHECK-LABEL: trunc_ 7 ; CHECK: sub sp, sp, #16 8 ; CHECK: strb w0, [sp, #15] 9 ; CHECK: strh w1, [sp, #12] 10 ; CHECK: str w2, [sp, #8] 11 ; CHECK: str x3, [sp] 12 ; CHECK: ldr x3, [sp] 13 ; CHECK: mov x0, x3 14 ; CHECK: str w0, [sp, #8] 15 ; CHECK: ldr w0, [sp, #8] 16 ; CHECK: strh w0, [sp, #12] 17 ; CHECK: ldrh w0, [sp, #12] 18 ; CHECK: strb w0, [sp, #15] 19 ; CHECK: ldrb w0, [sp, #15] 20 ; CHECK: add sp, sp, #16 21 ; CHECK: ret 22 %a.addr = alloca i8, align 1 23 %b.addr = alloca i16, align 2 24 %c.addr = alloca i32, align 4 25 %d.addr = alloca i64, align 8 26 store i8 %a, i8* %a.addr, align 1 27 store i16 %b, i16* %b.addr, align 2 28 store i32 %c, i32* %c.addr, align 4 29 store i64 %d, i64* %d.addr, align 8 30 %tmp = load i64, i64* %d.addr, align 8 31 %conv = trunc i64 %tmp to i32 32 store i32 %conv, i32* %c.addr, align 4 33 %tmp1 = load i32, i32* %c.addr, align 4 34 %conv2 = trunc i32 %tmp1 to i16 35 store i16 %conv2, i16* %b.addr, align 2 36 %tmp3 = load i16, i16* %b.addr, align 2 37 %conv4 = trunc i16 %tmp3 to i8 38 store i8 %conv4, i8* %a.addr, align 1 39 %tmp5 = load i8, i8* %a.addr, align 1 40 %conv6 = zext i8 %tmp5 to i32 41 ret i32 %conv6 42 } 43 44 define i64 @zext_(i8 zeroext %a, i16 zeroext %b, i32 %c, i64 %d) nounwind ssp { 45 entry: 46 ; CHECK-LABEL: zext_ 47 ; CHECK: sub sp, sp, #16 48 ; CHECK: strb w0, [sp, #15] 49 ; CHECK: strh w1, [sp, #12] 50 ; CHECK: str w2, [sp, #8] 51 ; CHECK: str x3, [sp] 52 ; CHECK: ldrb w0, [sp, #15] 53 ; CHECK: strh w0, [sp, #12] 54 ; CHECK: ldrh w0, [sp, #12] 55 ; CHECK: str w0, [sp, #8] 56 ; CHECK: ldr w0, [sp, #8] 57 ; CHECK: mov x3, x0 58 ; CHECK: str x3, [sp] 59 ; CHECK: ldr x0, [sp] 60 ; CHECK: ret 61 %a.addr = alloca i8, align 1 62 %b.addr = alloca i16, align 2 63 %c.addr = alloca i32, align 4 64 %d.addr = alloca i64, align 8 65 store i8 %a, i8* %a.addr, align 1 66 store i16 %b, i16* %b.addr, align 2 67 store i32 %c, i32* %c.addr, align 4 68 store i64 %d, i64* %d.addr, align 8 69 %tmp = load i8, i8* %a.addr, align 1 70 %conv = zext i8 %tmp to i16 71 store i16 %conv, i16* %b.addr, align 2 72 %tmp1 = load i16, i16* %b.addr, align 2 73 %conv2 = zext i16 %tmp1 to i32 74 store i32 %conv2, i32* %c.addr, align 4 75 %tmp3 = load i32, i32* %c.addr, align 4 76 %conv4 = zext i32 %tmp3 to i64 77 store i64 %conv4, i64* %d.addr, align 8 78 %tmp5 = load i64, i64* %d.addr, align 8 79 ret i64 %tmp5 80 } 81 82 define i32 @zext_i1_i32(i1 zeroext %a) nounwind ssp { 83 entry: 84 ; CHECK-LABEL: zext_i1_i32 85 ; CHECK-NOT: and w0, w0, #0x1 86 ; CHECK: ret 87 %conv = zext i1 %a to i32 88 ret i32 %conv; 89 } 90 91 define i64 @zext_i1_i64(i1 zeroext %a) nounwind ssp { 92 entry: 93 ; CHECK-LABEL: zext_i1_i64 94 ; CHECK-NOT: and w0, w0, #0x1 95 ; CHECK: ret 96 %conv = zext i1 %a to i64 97 ret i64 %conv; 98 } 99 100 define i64 @sext_(i8 signext %a, i16 signext %b, i32 %c, i64 %d) nounwind ssp { 101 entry: 102 ; CHECK-LABEL: sext_ 103 ; CHECK: sub sp, sp, #16 104 ; CHECK: strb w0, [sp, #15] 105 ; CHECK: strh w1, [sp, #12] 106 ; CHECK: str w2, [sp, #8] 107 ; CHECK: str x3, [sp] 108 ; CHECK: ldrsb w0, [sp, #15] 109 ; CHECK: strh w0, [sp, #12] 110 ; CHECK: ldrsh w0, [sp, #12] 111 ; CHECK: str w0, [sp, #8] 112 ; CHECK: ldrsw x3, [sp, #8] 113 ; CHECK: str x3, [sp] 114 ; CHECK: ldr x0, [sp] 115 ; CHECK: ret 116 %a.addr = alloca i8, align 1 117 %b.addr = alloca i16, align 2 118 %c.addr = alloca i32, align 4 119 %d.addr = alloca i64, align 8 120 store i8 %a, i8* %a.addr, align 1 121 store i16 %b, i16* %b.addr, align 2 122 store i32 %c, i32* %c.addr, align 4 123 store i64 %d, i64* %d.addr, align 8 124 %tmp = load i8, i8* %a.addr, align 1 125 %conv = sext i8 %tmp to i16 126 store i16 %conv, i16* %b.addr, align 2 127 %tmp1 = load i16, i16* %b.addr, align 2 128 %conv2 = sext i16 %tmp1 to i32 129 store i32 %conv2, i32* %c.addr, align 4 130 %tmp3 = load i32, i32* %c.addr, align 4 131 %conv4 = sext i32 %tmp3 to i64 132 store i64 %conv4, i64* %d.addr, align 8 133 %tmp5 = load i64, i64* %d.addr, align 8 134 ret i64 %tmp5 135 } 136 137 ; Test sext i8 to i64 138 139 define zeroext i64 @sext_i8_i64(i8 zeroext %in) { 140 ; CHECK-LABEL: sext_i8_i64: 141 ; CHECK: mov x[[TMP:[0-9]+]], x0 142 ; CHECK: sxtb x0, w[[TMP]] 143 %big = sext i8 %in to i64 144 ret i64 %big 145 } 146 147 define zeroext i64 @sext_i16_i64(i16 zeroext %in) { 148 ; CHECK-LABEL: sext_i16_i64: 149 ; CHECK: mov x[[TMP:[0-9]+]], x0 150 ; CHECK: sxth x0, w[[TMP]] 151 %big = sext i16 %in to i64 152 ret i64 %big 153 } 154 155 ; Test sext i1 to i32 156 define i32 @sext_i1_i32(i1 signext %a) nounwind ssp { 157 entry: 158 ; CHECK-LABEL: sext_i1_i32 159 ; CHECK-NOT: sbfx w0, w0, #0, #1 160 ; CHECK: ret 161 %conv = sext i1 %a to i32 162 ret i32 %conv 163 } 164 165 ; Test sext i1 to i16 166 define signext i16 @sext_i1_i16(i1 %a) nounwind ssp { 167 entry: 168 ; CHECK-LABEL: sext_i1_i16 169 ; CHECK: sbfx w0, w0, #0, #1 170 %conv = sext i1 %a to i16 171 ret i16 %conv 172 } 173 174 ; Test sext i1 to i8 175 define signext i8 @sext_i1_i8(i1 %a) nounwind ssp { 176 entry: 177 ; CHECK-LABEL: sext_i1_i8 178 ; CHECK: sbfx w0, w0, #0, #1 179 %conv = sext i1 %a to i8 180 ret i8 %conv 181 } 182 183 ; Test fpext 184 define double @fpext_(float %a) nounwind ssp { 185 entry: 186 ; CHECK-LABEL: fpext_ 187 ; CHECK: fcvt d0, s0 188 %conv = fpext float %a to double 189 ret double %conv 190 } 191 192 ; Test fptrunc 193 define float @fptrunc_(double %a) nounwind ssp { 194 entry: 195 ; CHECK-LABEL: fptrunc_ 196 ; CHECK: fcvt s0, d0 197 %conv = fptrunc double %a to float 198 ret float %conv 199 } 200 201 ; Test fptosi 202 define i32 @fptosi_ws(float %a) nounwind ssp { 203 entry: 204 ; CHECK-LABEL: fptosi_ws 205 ; CHECK: fcvtzs w0, s0 206 %conv = fptosi float %a to i32 207 ret i32 %conv 208 } 209 210 ; Test fptosi 211 define i32 @fptosi_wd(double %a) nounwind ssp { 212 entry: 213 ; CHECK-LABEL: fptosi_wd 214 ; CHECK: fcvtzs w0, d0 215 %conv = fptosi double %a to i32 216 ret i32 %conv 217 } 218 219 ; Test fptoui 220 define i32 @fptoui_ws(float %a) nounwind ssp { 221 entry: 222 ; CHECK-LABEL: fptoui_ws 223 ; CHECK: fcvtzu w0, s0 224 %conv = fptoui float %a to i32 225 ret i32 %conv 226 } 227 228 ; Test fptoui 229 define i32 @fptoui_wd(double %a) nounwind ssp { 230 entry: 231 ; CHECK-LABEL: fptoui_wd 232 ; CHECK: fcvtzu w0, d0 233 %conv = fptoui double %a to i32 234 ret i32 %conv 235 } 236 237 ; Test sitofp 238 define float @sitofp_sw_i1(i1 %a) nounwind ssp { 239 entry: 240 ; CHECK-LABEL: sitofp_sw_i1 241 ; CHECK: sbfx w0, w0, #0, #1 242 ; CHECK: scvtf s0, w0 243 %conv = sitofp i1 %a to float 244 ret float %conv 245 } 246 247 ; Test sitofp 248 define float @sitofp_sw_i8(i8 %a) nounwind ssp { 249 entry: 250 ; CHECK-LABEL: sitofp_sw_i8 251 ; CHECK: sxtb w0, w0 252 ; CHECK: scvtf s0, w0 253 %conv = sitofp i8 %a to float 254 ret float %conv 255 } 256 257 ; Test sitofp 258 define float @sitofp_sw_i16(i16 %a) nounwind ssp { 259 entry: 260 ; CHECK-LABEL: sitofp_sw_i16 261 %conv = sitofp i16 %a to float 262 ret float %conv 263 } 264 265 ; Test sitofp 266 define float @sitofp_sw(i32 %a) nounwind ssp { 267 entry: 268 ; CHECK-LABEL: sitofp_sw 269 ; CHECK: scvtf s0, w0 270 %conv = sitofp i32 %a to float 271 ret float %conv 272 } 273 274 ; Test sitofp 275 define float @sitofp_sx(i64 %a) nounwind ssp { 276 entry: 277 ; CHECK-LABEL: sitofp_sx 278 ; CHECK: scvtf s0, x0 279 %conv = sitofp i64 %a to float 280 ret float %conv 281 } 282 283 ; Test sitofp 284 define double @sitofp_dw(i32 %a) nounwind ssp { 285 entry: 286 ; CHECK-LABEL: sitofp_dw 287 ; CHECK: scvtf d0, w0 288 %conv = sitofp i32 %a to double 289 ret double %conv 290 } 291 292 ; Test sitofp 293 define double @sitofp_dx(i64 %a) nounwind ssp { 294 entry: 295 ; CHECK-LABEL: sitofp_dx 296 ; CHECK: scvtf d0, x0 297 %conv = sitofp i64 %a to double 298 ret double %conv 299 } 300 301 ; Test uitofp 302 define float @uitofp_sw_i1(i1 %a) nounwind ssp { 303 entry: 304 ; CHECK-LABEL: uitofp_sw_i1 305 ; CHECK: and w0, w0, #0x1 306 ; CHECK: ucvtf s0, w0 307 %conv = uitofp i1 %a to float 308 ret float %conv 309 } 310 311 ; Test uitofp 312 define float @uitofp_sw_i8(i8 %a) nounwind ssp { 313 entry: 314 ; CHECK-LABEL: uitofp_sw_i8 315 %conv = uitofp i8 %a to float 316 ret float %conv 317 } 318 319 ; Test uitofp 320 define float @uitofp_sw_i16(i16 %a) nounwind ssp { 321 entry: 322 ; CHECK-LABEL: uitofp_sw_i16 323 %conv = uitofp i16 %a to float 324 ret float %conv 325 } 326 327 ; Test uitofp 328 define float @uitofp_sw(i32 %a) nounwind ssp { 329 entry: 330 ; CHECK-LABEL: uitofp_sw 331 ; CHECK: ucvtf s0, w0 332 %conv = uitofp i32 %a to float 333 ret float %conv 334 } 335 336 ; Test uitofp 337 define float @uitofp_sx(i64 %a) nounwind ssp { 338 entry: 339 ; CHECK-LABEL: uitofp_sx 340 ; CHECK: ucvtf s0, x0 341 %conv = uitofp i64 %a to float 342 ret float %conv 343 } 344 345 ; Test uitofp 346 define double @uitofp_dw(i32 %a) nounwind ssp { 347 entry: 348 ; CHECK-LABEL: uitofp_dw 349 ; CHECK: ucvtf d0, w0 350 %conv = uitofp i32 %a to double 351 ret double %conv 352 } 353 354 ; Test uitofp 355 define double @uitofp_dx(i64 %a) nounwind ssp { 356 entry: 357 ; CHECK-LABEL: uitofp_dx 358 ; CHECK: ucvtf d0, x0 359 %conv = uitofp i64 %a to double 360 ret double %conv 361 } 362 363 define i32 @i64_trunc_i32(i64 %a) nounwind ssp { 364 entry: 365 ; CHECK-LABEL: i64_trunc_i32 366 ; CHECK: mov x1, x0 367 %conv = trunc i64 %a to i32 368 ret i32 %conv 369 } 370 371 define zeroext i16 @i64_trunc_i16(i64 %a) nounwind ssp { 372 entry: 373 ; CHECK-LABEL: i64_trunc_i16 374 ; CHECK: mov x[[REG:[0-9]+]], x0 375 ; CHECK: and [[REG2:w[0-9]+]], w[[REG]], #0xffff 376 ; CHECK: uxth w0, [[REG2]] 377 %conv = trunc i64 %a to i16 378 ret i16 %conv 379 } 380 381 define zeroext i8 @i64_trunc_i8(i64 %a) nounwind ssp { 382 entry: 383 ; CHECK-LABEL: i64_trunc_i8 384 ; CHECK: mov x[[REG:[0-9]+]], x0 385 ; CHECK: and [[REG2:w[0-9]+]], w[[REG]], #0xff 386 ; CHECK: uxtb w0, [[REG2]] 387 %conv = trunc i64 %a to i8 388 ret i8 %conv 389 } 390 391 define zeroext i1 @i64_trunc_i1(i64 %a) nounwind ssp { 392 entry: 393 ; CHECK-LABEL: i64_trunc_i1 394 ; CHECK: mov x[[REG:[0-9]+]], x0 395 ; CHECK: and [[REG2:w[0-9]+]], w[[REG]], #0x1 396 ; CHECK: and w0, [[REG2]], #0x1 397 %conv = trunc i64 %a to i1 398 ret i1 %conv 399 } 400 401 ; rdar://15101939 402 define void @stack_trunc() nounwind { 403 ; CHECK-LABEL: stack_trunc 404 ; CHECK: sub sp, sp, #16 405 ; CHECK: ldr [[REG:x[0-9]+]], [sp] 406 ; CHECK: mov x[[REG2:[0-9]+]], [[REG]] 407 ; CHECK: and [[REG3:w[0-9]+]], w[[REG2]], #0xff 408 ; CHECK: strb [[REG3]], [sp, #15] 409 ; CHECK: add sp, sp, #16 410 %a = alloca i8, align 1 411 %b = alloca i64, align 8 412 %c = load i64, i64* %b, align 8 413 %d = trunc i64 %c to i8 414 store i8 %d, i8* %a, align 1 415 ret void 416 } 417 418 define zeroext i64 @zext_i8_i64(i8 zeroext %in) { 419 ; CHECK-LABEL: zext_i8_i64: 420 ; CHECK-NOT: ubfx x0, {{x[0-9]+}}, #0, #8 421 ; CHECK: ret 422 %big = zext i8 %in to i64 423 ret i64 %big 424 } 425 define zeroext i64 @zext_i16_i64(i16 zeroext %in) { 426 ; CHECK-LABEL: zext_i16_i64: 427 ; CHECK-NOT: ubfx x0, {{x[0-9]+}}, #0, #16 428 ; CHECK: ret 429 %big = zext i16 %in to i64 430 ret i64 %big 431 } 432 433 define float @bitcast_i32_to_float(i32 %a) { 434 %1 = bitcast i32 %a to float 435 ret float %1 436 } 437 438 define double @bitcast_i64_to_double(i64 %a) { 439 %1 = bitcast i64 %a to double 440 ret double %1 441 } 442 443 define i32 @bitcast_float_to_i32(float %a) { 444 %1 = bitcast float %a to i32 445 ret i32 %1 446 } 447 448 define i64 @bitcast_double_to_i64(double %a) { 449 %1 = bitcast double %a to i64 450 ret i64 %1 451 } 452 453