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