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