Home | History | Annotate | Download | only in AArch64
      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