Home | History | Annotate | Download | only in GlobalISel
      1 ; RUN: llc -mtriple arm-unknown -mattr=+vfp2,+v6 -global-isel %s -o - | FileCheck %s
      2 
      3 define void @test_void_return() {
      4 ; CHECK-LABEL: test_void_return:
      5 ; CHECK: bx lr
      6 entry:
      7   ret void
      8 }
      9 
     10 define i32 @test_constant_return_i32() {
     11 ; CHECK-LABEL: test_constant_return_i32:
     12 ; CHECK: mov r0, #42
     13 ; CHECK: bx lr
     14 entry:
     15   ret i32 42
     16 }
     17 
     18 define zeroext i1 @test_zext_i1(i1 %x) {
     19 ; CHECK-LABEL: test_zext_i1
     20 ; CHECK: and r0, r0, #1
     21 ; CHECK: bx lr
     22 entry:
     23   ret i1 %x
     24 }
     25 
     26 define signext i1 @test_sext_i1(i1 %x) {
     27 ; CHECK-LABEL: test_sext_i1
     28 ; CHECK: mov	r1, #31
     29 ; CHECK: lsl	r0, r0, r1
     30 ; CHECK: asr	r0, r0, r1
     31 ; CHECK: bx lr
     32 entry:
     33   ret i1 %x
     34 }
     35 
     36 define zeroext i8 @test_ext_i8(i8 %x) {
     37 ; CHECK-LABEL: test_ext_i8:
     38 ; CHECK: uxtb r0, r0
     39 ; CHECK: bx lr
     40 
     41 entry:
     42   ret i8 %x
     43 }
     44 
     45 define signext i16 @test_ext_i16(i16 %x) {
     46 ; CHECK-LABEL: test_ext_i16:
     47 ; CHECK: mov	r1, #16
     48 ; CHECK: lsl	r0, r0, r1
     49 ; CHECK: asr	r0, r0, r1
     50 ; CHECK: bx lr
     51 entry:
     52   ret i16 %x
     53 }
     54 
     55 define void @test_trunc_i32_i16(i32 %v, i16 *%p) {
     56 ; CHECK-LABEL: test_trunc_i32_i16:
     57 ; The trunc doesn't result in any instructions, but we
     58 ; expect the store to be explicitly 16-bit.
     59 ; CHECK: strh r0, [r1]
     60 ; CHECK: bx lr
     61 entry:
     62   %v16 = trunc i32 %v to i16
     63   store i16 %v16, i16 *%p
     64   ret void
     65 }
     66 
     67 define void @test_trunc_i32_i8(i32 %v, i8 *%p) {
     68 ; CHECK-LABEL: test_trunc_i32_i8:
     69 ; The trunc doesn't result in any instructions, but we
     70 ; expect the store to be explicitly 8-bit.
     71 ; CHECK: strb r0, [r1]
     72 ; CHECK: bx lr
     73 entry:
     74   %v8 = trunc i32 %v to i8
     75   store i8 %v8, i8 *%p
     76   ret void
     77 }
     78 
     79 define i8 @test_add_i8(i8 %x, i8 %y) {
     80 ; CHECK-LABEL: test_add_i8:
     81 ; CHECK: add r0, r0, r1
     82 ; CHECK: bx lr
     83 entry:
     84   %sum = add i8 %x, %y
     85   ret i8 %sum
     86 }
     87 
     88 define i16 @test_add_i16(i16 %x, i16 %y) {
     89 ; CHECK-LABEL: test_add_i16:
     90 ; CHECK: add r0, r0, r1
     91 ; CHECK: bx lr
     92 entry:
     93   %sum = add i16 %x, %y
     94   ret i16 %sum
     95 }
     96 
     97 define i32 @test_add_i32(i32 %x, i32 %y) {
     98 ; CHECK-LABEL: test_add_i32:
     99 ; CHECK: add r0, r0, r1
    100 ; CHECK: bx lr
    101 entry:
    102   %sum = add i32 %x, %y
    103   ret i32 %sum
    104 }
    105 
    106 define i8 @test_sub_i8(i8 %x, i8 %y) {
    107 ; CHECK-LABEL: test_sub_i8:
    108 ; CHECK: sub r0, r0, r1
    109 ; CHECK: bx lr
    110 entry:
    111   %sum = sub i8 %x, %y
    112   ret i8 %sum
    113 }
    114 
    115 define i16 @test_sub_i16(i16 %x, i16 %y) {
    116 ; CHECK-LABEL: test_sub_i16:
    117 ; CHECK: sub r0, r0, r1
    118 ; CHECK: bx lr
    119 entry:
    120   %sum = sub i16 %x, %y
    121   ret i16 %sum
    122 }
    123 
    124 define i32 @test_sub_i32(i32 %x, i32 %y) {
    125 ; CHECK-LABEL: test_sub_i32:
    126 ; CHECK: sub r0, r0, r1
    127 ; CHECK: bx lr
    128 entry:
    129   %sum = sub i32 %x, %y
    130   ret i32 %sum
    131 }
    132 
    133 define i8 @test_mul_i8(i8 %x, i8 %y) {
    134 ; CHECK-LABEL: test_mul_i8:
    135 ; CHECK: mul r0, r0, r1
    136 ; CHECK: bx lr
    137 entry:
    138   %sum = mul i8 %x, %y
    139   ret i8 %sum
    140 }
    141 
    142 define i16 @test_mul_i16(i16 %x, i16 %y) {
    143 ; CHECK-LABEL: test_mul_i16:
    144 ; CHECK: mul r0, r0, r1
    145 ; CHECK: bx lr
    146 entry:
    147   %sum = mul i16 %x, %y
    148   ret i16 %sum
    149 }
    150 
    151 define i32 @test_mul_i32(i32 %x, i32 %y) {
    152 ; CHECK-LABEL: test_mul_i32:
    153 ; CHECK: mul r0, r0, r1
    154 ; CHECK: bx lr
    155 entry:
    156   %sum = mul i32 %x, %y
    157   ret i32 %sum
    158 }
    159 
    160 define i8 @test_and_i8(i8 %x, i8 %y) {
    161 ; CHECK-LABEL: test_and_i8:
    162 ; CHECK: and r0, r0, r1
    163 ; CHECK: bx lr
    164 entry:
    165   %sum = and i8 %x, %y
    166   ret i8 %sum
    167 }
    168 
    169 define i16 @test_and_i16(i16 %x, i16 %y) {
    170 ; CHECK-LABEL: test_and_i16:
    171 ; CHECK: and r0, r0, r1
    172 ; CHECK: bx lr
    173 entry:
    174   %sum = and i16 %x, %y
    175   ret i16 %sum
    176 }
    177 
    178 define i32 @test_and_i32(i32 %x, i32 %y) {
    179 ; CHECK-LABEL: test_and_i32:
    180 ; CHECK: and r0, r0, r1
    181 ; CHECK: bx lr
    182 entry:
    183   %sum = and i32 %x, %y
    184   ret i32 %sum
    185 }
    186 
    187 define i8 @test_or_i8(i8 %x, i8 %y) {
    188 ; CHECK-LABEL: test_or_i8:
    189 ; CHECK: orr r0, r0, r1
    190 ; CHECK: bx lr
    191 entry:
    192   %sum = or i8 %x, %y
    193   ret i8 %sum
    194 }
    195 
    196 define i16 @test_or_i16(i16 %x, i16 %y) {
    197 ; CHECK-LABEL: test_or_i16:
    198 ; CHECK: orr r0, r0, r1
    199 ; CHECK: bx lr
    200 entry:
    201   %sum = or i16 %x, %y
    202   ret i16 %sum
    203 }
    204 
    205 define i32 @test_or_i32(i32 %x, i32 %y) {
    206 ; CHECK-LABEL: test_or_i32:
    207 ; CHECK: orr r0, r0, r1
    208 ; CHECK: bx lr
    209 entry:
    210   %sum = or i32 %x, %y
    211   ret i32 %sum
    212 }
    213 
    214 define i8 @test_xor_i8(i8 %x, i8 %y) {
    215 ; CHECK-LABEL: test_xor_i8:
    216 ; CHECK: eor r0, r0, r1
    217 ; CHECK: bx lr
    218 entry:
    219   %sum = xor i8 %x, %y
    220   ret i8 %sum
    221 }
    222 
    223 define i16 @test_xor_i16(i16 %x, i16 %y) {
    224 ; CHECK-LABEL: test_xor_i16:
    225 ; CHECK: eor r0, r0, r1
    226 ; CHECK: bx lr
    227 entry:
    228   %sum = xor i16 %x, %y
    229   ret i16 %sum
    230 }
    231 
    232 define i32 @test_xor_i32(i32 %x, i32 %y) {
    233 ; CHECK-LABEL: test_xor_i32:
    234 ; CHECK: eor r0, r0, r1
    235 ; CHECK: bx lr
    236 entry:
    237   %sum = xor i32 %x, %y
    238   ret i32 %sum
    239 }
    240 
    241 define i32 @test_stack_args_i32(i32 %p0, i32 %p1, i32 %p2, i32 %p3, i32 %p4, i32 %p5) {
    242 ; CHECK-LABEL: test_stack_args_i32:
    243 ; CHECK: add [[P5ADDR:r[0-9]+]], sp, #4
    244 ; CHECK: ldr [[P5:r[0-9]+]], {{.*}}[[P5ADDR]]
    245 ; CHECK: add r0, r2, [[P5]]
    246 ; CHECK: bx lr
    247 entry:
    248   %sum = add i32 %p2, %p5
    249   ret i32 %sum
    250 }
    251 
    252 define i16 @test_stack_args_mixed(i32 %p0, i16 %p1, i8 %p2, i1 %p3, i8 %p4, i16 %p5) {
    253 ; CHECK-LABEL: test_stack_args_mixed:
    254 ; CHECK: add [[P5ADDR:r[0-9]+]], sp, #4
    255 ; CHECK: ldrh [[P5:r[0-9]+]], {{.*}}[[P5ADDR]]
    256 ; CHECK: add r0, r1, [[P5]]
    257 ; CHECK: bx lr
    258 entry:
    259   %sum = add i16 %p1, %p5
    260   ret i16 %sum
    261 }
    262 
    263 define i16 @test_stack_args_zeroext(i32 %p0, i16 %p1, i8 %p2, i1 %p3, i16 zeroext %p4) {
    264 ; CHECK-LABEL: test_stack_args_zeroext:
    265 ; CHECK: mov [[P4ADDR:r[0-9]+]], sp
    266 ; CHECK: ldr [[P4:r[0-9]+]], {{.*}}[[P4ADDR]]
    267 ; CHECK: add r0, r1, [[P4]]
    268 ; CHECK: bx lr
    269 entry:
    270   %sum = add i16 %p1, %p4
    271   ret i16 %sum
    272 }
    273 
    274 define i8 @test_stack_args_signext(i32 %p0, i16 %p1, i8 %p2, i1 %p3, i8 signext %p4) {
    275 ; CHECK-LABEL: test_stack_args_signext:
    276 ; CHECK: mov [[P4ADDR:r[0-9]+]], sp
    277 ; CHECK: ldr [[P4:r[0-9]+]], {{.*}}[[P4ADDR]]
    278 ; CHECK: add r0, r2, [[P4]]
    279 ; CHECK: bx lr
    280 entry:
    281   %sum = add i8 %p2, %p4
    282   ret i8 %sum
    283 }
    284 
    285 define i8 @test_stack_args_noext(i32 %p0, i16 %p1, i8 %p2, i1 %p3, i8 %p4) {
    286 ; CHECK-LABEL: test_stack_args_noext:
    287 ; CHECK: mov [[P4ADDR:r[0-9]+]], sp
    288 ; CHECK: ldrb [[P4:r[0-9]+]], {{.*}}[[P4ADDR]]
    289 ; CHECK: add r0, r2, [[P4]]
    290 ; CHECK: bx lr
    291 entry:
    292   %sum = add i8 %p2, %p4
    293   ret i8 %sum
    294 }
    295 
    296 define i32 @test_ptr_arg_in_reg(i32* %p) {
    297 ; CHECK-LABEL: test_ptr_arg_in_reg:
    298 ; CHECK: ldr r0, [r0]
    299 ; CHECK: bx lr
    300 entry:
    301   %v = load i32, i32* %p
    302   ret i32 %v
    303 }
    304 
    305 define i32 @test_ptr_arg_on_stack(i32 %f0, i32 %f1, i32 %f2, i32 %f3, i32* %p) {
    306 ; CHECK-LABEL: test_ptr_arg_on_stack:
    307 ; CHECK: mov r0, sp
    308 ; CHECK: ldr r0, [r0]
    309 ; CHECK: ldr r0, [r0]
    310 ; CHECK: bx lr
    311 entry:
    312   %v = load i32, i32* %p
    313   ret i32 %v
    314 }
    315 
    316 define i8* @test_ptr_ret(i8** %p) {
    317 ; CHECK-LABEL: test_ptr_ret:
    318 ; CHECK: ldr r0, [r0]
    319 ; CHECK: bx lr
    320 entry:
    321   %v = load i8*, i8** %p
    322   ret i8* %v
    323 }
    324 
    325 define arm_aapcs_vfpcc float @test_float_hard(float %f0, float %f1) {
    326 ; CHECK-LABEL: test_float_hard:
    327 ; CHECK: vadd.f32 s0, s0, s1
    328 ; CHECK: bx lr
    329 entry:
    330   %v = fadd float %f0, %f1
    331   ret float %v
    332 }
    333 
    334 define arm_aapcscc float @test_float_softfp(float %f0, float %f1) {
    335 ; CHECK-LABEL: test_float_softfp:
    336 ; CHECK-DAG: vmov [[F0:s[0-9]+]], r0
    337 ; CHECK-DAG: vmov [[F1:s[0-9]+]], r1
    338 ; CHECK: vadd.f32 [[FV:s[0-9]+]], [[F0]], [[F1]]
    339 ; CHECK: vmov r0, [[FV]]
    340 ; CHECK: bx lr
    341 entry:
    342   %v = fadd float %f0, %f1
    343   ret float %v
    344 }
    345 
    346 define arm_aapcs_vfpcc double @test_double_hard(double %f0, double %f1) {
    347 ; CHECK-LABEL: test_double_hard:
    348 ; CHECK: vadd.f64 d0, d0, d1
    349 ; CHECK: bx lr
    350 entry:
    351   %v = fadd double %f0, %f1
    352   ret double %v
    353 }
    354 
    355 define arm_aapcscc double @test_double_softfp(double %f0, double %f1) {
    356 ; CHECK-LABEL: test_double_softfp:
    357 ; CHECK-DAG: vmov [[F0:d[0-9]+]], r0, r1
    358 ; CHECK-DAG: vmov [[F1:d[0-9]+]], r2, r3
    359 ; CHECK: vadd.f64 [[FV:d[0-9]+]], [[F0]], [[F1]]
    360 ; CHECK: vmov r0, r1, [[FV]]
    361 ; CHECK: bx lr
    362 entry:
    363   %v = fadd double %f0, %f1
    364   ret double %v
    365 }
    366 
    367 define arm_aapcscc i32 @test_cmp_i32_eq(i32 %a, i32 %b) {
    368 ; CHECK-LABEL: test_cmp_i32_eq:
    369 ; CHECK: mov [[V:r[0-9]+]], #0
    370 ; CHECK: cmp r0, r1
    371 ; CHECK: moveq [[V]], #1
    372 ; CHECK: and r0, [[V]], #1
    373 ; CHECK: bx lr
    374 entry:
    375   %v = icmp eq i32 %a, %b
    376   %r = zext i1 %v to i32
    377   ret i32 %r
    378 }
    379 
    380 define arm_aapcscc i32 @test_cmp_ptr_neq(double *%a, double *%b) {
    381 ; CHECK-LABEL: test_cmp_ptr_neq:
    382 ; CHECK: mov [[V:r[0-9]+]], #0
    383 ; CHECK: cmp r0, r1
    384 ; CHECK: movne [[V]], #1
    385 ; CHECK: and r0, [[V]], #1
    386 ; CHECK: bx lr
    387 entry:
    388   %v = icmp ne double * %a, %b
    389   %r = zext i1 %v to i32
    390   ret i32 %r
    391 }
    392 
    393 define arm_aapcscc i32 @test_cmp_i16_slt(i16 %a, i16 %b) {
    394 ; CHECK-LABEL: test_cmp_i16_slt:
    395 ; CHECK-DAG: mov [[V:r[0-9]+]], #0
    396 ; CHECK: cmp r0, r1
    397 ; CHECK: movlt [[V]], #1
    398 ; CHECK: and r0, [[V]], #1
    399 ; CHECK: bx lr
    400 entry:
    401   %v = icmp slt i16 %a, %b
    402   %r = zext i1 %v to i32
    403   ret i32 %r
    404 }
    405 
    406 define arm_aapcscc i32 @test_select_i32(i32 %a, i32 %b, i1 %cond) {
    407 ; CHECK-LABEL: test_select_i32
    408 ; CHECK: cmp r2, #0
    409 ; CHECK: moveq r0, r1
    410 ; CHECK: bx lr
    411 entry:
    412   %r = select i1 %cond, i32 %a, i32 %b
    413   ret i32 %r
    414 }
    415 
    416 define arm_aapcscc i32* @test_select_ptr(i32* %a, i32* %b, i1 %cond) {
    417 ; CHECK-LABEL: test_select_ptr
    418 ; CHECK: cmp r2, #0
    419 ; CHECK: moveq r0, r1
    420 ; CHECK: bx lr
    421 entry:
    422   %r = select i1 %cond, i32* %a, i32* %b
    423   ret i32* %r
    424 }
    425 
    426 define arm_aapcscc void @test_br() {
    427 ; CHECK-LABEL: test_br
    428 ; CHECK: [[LABEL:.L[[:alnum:]_]+]]:
    429 ; CHECK: b [[LABEL]]
    430 entry:
    431   br label %infinite
    432 
    433 infinite:
    434   br label %infinite
    435 }
    436 
    437 declare arm_aapcscc void @brcond1()
    438 declare arm_aapcscc void @brcond2()
    439 
    440 define arm_aapcscc void @test_brcond(i32 %n) {
    441 ; CHECK-LABEL: test_brcond
    442 ; CHECK: cmp r0
    443 ; CHECK-NEXT: movgt [[RCMP:r[0-9]+]], #1
    444 ; CHECK: tst [[RCMP]], #1
    445 ; CHECK-NEXT: beq [[FALSE:.L[[:alnum:]_]+]]
    446 ; CHECK: bl brcond1
    447 ; CHECK: [[FALSE]]:
    448 ; CHECK: bl brcond2
    449 entry:
    450   %cmp = icmp sgt i32 %n, 0
    451   br i1 %cmp, label %if.true, label %if.false
    452 
    453 if.true:
    454   call arm_aapcscc void @brcond1()
    455   br label %if.end
    456 
    457 if.false:
    458   call arm_aapcscc void @brcond2()
    459   br label %if.end
    460 
    461 if.end:
    462   ret void
    463 }
    464