1; RUN: llc -mtriple arm-unknown -mattr=+vfp2,+v6 -global-isel %s -o - | FileCheck %s 2 3define void @test_void_return() { 4; CHECK-LABEL: test_void_return: 5; CHECK: bx lr 6entry: 7 ret void 8} 9 10define i32 @test_constant_return_i32() { 11; CHECK-LABEL: test_constant_return_i32: 12; CHECK: mov r0, #42 13; CHECK: bx lr 14entry: 15 ret i32 42 16} 17 18define zeroext i1 @test_zext_i1(i1 %x) { 19; CHECK-LABEL: test_zext_i1 20; CHECK: and r0, r0, #1 21; CHECK: bx lr 22entry: 23 ret i1 %x 24} 25 26define 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 32entry: 33 ret i1 %x 34} 35 36define zeroext i8 @test_ext_i8(i8 %x) { 37; CHECK-LABEL: test_ext_i8: 38; CHECK: uxtb r0, r0 39; CHECK: bx lr 40 41entry: 42 ret i8 %x 43} 44 45define 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 51entry: 52 ret i16 %x 53} 54 55define 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 61entry: 62 %v16 = trunc i32 %v to i16 63 store i16 %v16, i16 *%p 64 ret void 65} 66 67define 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 73entry: 74 %v8 = trunc i32 %v to i8 75 store i8 %v8, i8 *%p 76 ret void 77} 78 79define i8 @test_add_i8(i8 %x, i8 %y) { 80; CHECK-LABEL: test_add_i8: 81; CHECK: add r0, r0, r1 82; CHECK: bx lr 83entry: 84 %sum = add i8 %x, %y 85 ret i8 %sum 86} 87 88define i16 @test_add_i16(i16 %x, i16 %y) { 89; CHECK-LABEL: test_add_i16: 90; CHECK: add r0, r0, r1 91; CHECK: bx lr 92entry: 93 %sum = add i16 %x, %y 94 ret i16 %sum 95} 96 97define i32 @test_add_i32(i32 %x, i32 %y) { 98; CHECK-LABEL: test_add_i32: 99; CHECK: add r0, r0, r1 100; CHECK: bx lr 101entry: 102 %sum = add i32 %x, %y 103 ret i32 %sum 104} 105 106define i8 @test_sub_i8(i8 %x, i8 %y) { 107; CHECK-LABEL: test_sub_i8: 108; CHECK: sub r0, r0, r1 109; CHECK: bx lr 110entry: 111 %sum = sub i8 %x, %y 112 ret i8 %sum 113} 114 115define i16 @test_sub_i16(i16 %x, i16 %y) { 116; CHECK-LABEL: test_sub_i16: 117; CHECK: sub r0, r0, r1 118; CHECK: bx lr 119entry: 120 %sum = sub i16 %x, %y 121 ret i16 %sum 122} 123 124define i32 @test_sub_i32(i32 %x, i32 %y) { 125; CHECK-LABEL: test_sub_i32: 126; CHECK: sub r0, r0, r1 127; CHECK: bx lr 128entry: 129 %sum = sub i32 %x, %y 130 ret i32 %sum 131} 132 133define i8 @test_mul_i8(i8 %x, i8 %y) { 134; CHECK-LABEL: test_mul_i8: 135; CHECK: mul r0, r0, r1 136; CHECK: bx lr 137entry: 138 %sum = mul i8 %x, %y 139 ret i8 %sum 140} 141 142define i16 @test_mul_i16(i16 %x, i16 %y) { 143; CHECK-LABEL: test_mul_i16: 144; CHECK: mul r0, r0, r1 145; CHECK: bx lr 146entry: 147 %sum = mul i16 %x, %y 148 ret i16 %sum 149} 150 151define i32 @test_mul_i32(i32 %x, i32 %y) { 152; CHECK-LABEL: test_mul_i32: 153; CHECK: mul r0, r0, r1 154; CHECK: bx lr 155entry: 156 %sum = mul i32 %x, %y 157 ret i32 %sum 158} 159 160define i8 @test_and_i8(i8 %x, i8 %y) { 161; CHECK-LABEL: test_and_i8: 162; CHECK: and r0, r0, r1 163; CHECK: bx lr 164entry: 165 %sum = and i8 %x, %y 166 ret i8 %sum 167} 168 169define i16 @test_and_i16(i16 %x, i16 %y) { 170; CHECK-LABEL: test_and_i16: 171; CHECK: and r0, r0, r1 172; CHECK: bx lr 173entry: 174 %sum = and i16 %x, %y 175 ret i16 %sum 176} 177 178define i32 @test_and_i32(i32 %x, i32 %y) { 179; CHECK-LABEL: test_and_i32: 180; CHECK: and r0, r0, r1 181; CHECK: bx lr 182entry: 183 %sum = and i32 %x, %y 184 ret i32 %sum 185} 186 187define i8 @test_or_i8(i8 %x, i8 %y) { 188; CHECK-LABEL: test_or_i8: 189; CHECK: orr r0, r0, r1 190; CHECK: bx lr 191entry: 192 %sum = or i8 %x, %y 193 ret i8 %sum 194} 195 196define i16 @test_or_i16(i16 %x, i16 %y) { 197; CHECK-LABEL: test_or_i16: 198; CHECK: orr r0, r0, r1 199; CHECK: bx lr 200entry: 201 %sum = or i16 %x, %y 202 ret i16 %sum 203} 204 205define i32 @test_or_i32(i32 %x, i32 %y) { 206; CHECK-LABEL: test_or_i32: 207; CHECK: orr r0, r0, r1 208; CHECK: bx lr 209entry: 210 %sum = or i32 %x, %y 211 ret i32 %sum 212} 213 214define i8 @test_xor_i8(i8 %x, i8 %y) { 215; CHECK-LABEL: test_xor_i8: 216; CHECK: eor r0, r0, r1 217; CHECK: bx lr 218entry: 219 %sum = xor i8 %x, %y 220 ret i8 %sum 221} 222 223define i16 @test_xor_i16(i16 %x, i16 %y) { 224; CHECK-LABEL: test_xor_i16: 225; CHECK: eor r0, r0, r1 226; CHECK: bx lr 227entry: 228 %sum = xor i16 %x, %y 229 ret i16 %sum 230} 231 232define i32 @test_xor_i32(i32 %x, i32 %y) { 233; CHECK-LABEL: test_xor_i32: 234; CHECK: eor r0, r0, r1 235; CHECK: bx lr 236entry: 237 %sum = xor i32 %x, %y 238 ret i32 %sum 239} 240 241define 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 247entry: 248 %sum = add i32 %p2, %p5 249 ret i32 %sum 250} 251 252define 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 258entry: 259 %sum = add i16 %p1, %p5 260 ret i16 %sum 261} 262 263define 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 269entry: 270 %sum = add i16 %p1, %p4 271 ret i16 %sum 272} 273 274define 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 280entry: 281 %sum = add i8 %p2, %p4 282 ret i8 %sum 283} 284 285define 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 291entry: 292 %sum = add i8 %p2, %p4 293 ret i8 %sum 294} 295 296define 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 300entry: 301 %v = load i32, i32* %p 302 ret i32 %v 303} 304 305define 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 311entry: 312 %v = load i32, i32* %p 313 ret i32 %v 314} 315 316define i8* @test_ptr_ret(i8** %p) { 317; CHECK-LABEL: test_ptr_ret: 318; CHECK: ldr r0, [r0] 319; CHECK: bx lr 320entry: 321 %v = load i8*, i8** %p 322 ret i8* %v 323} 324 325define 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 329entry: 330 %v = fadd float %f0, %f1 331 ret float %v 332} 333 334define 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 341entry: 342 %v = fadd float %f0, %f1 343 ret float %v 344} 345 346define 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 350entry: 351 %v = fadd double %f0, %f1 352 ret double %v 353} 354 355define 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 362entry: 363 %v = fadd double %f0, %f1 364 ret double %v 365} 366 367define 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 374entry: 375 %v = icmp eq i32 %a, %b 376 %r = zext i1 %v to i32 377 ret i32 %r 378} 379 380define 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 387entry: 388 %v = icmp ne double * %a, %b 389 %r = zext i1 %v to i32 390 ret i32 %r 391} 392 393define 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 400entry: 401 %v = icmp slt i16 %a, %b 402 %r = zext i1 %v to i32 403 ret i32 %r 404} 405 406define 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 411entry: 412 %r = select i1 %cond, i32 %a, i32 %b 413 ret i32 %r 414} 415 416define 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 421entry: 422 %r = select i1 %cond, i32* %a, i32* %b 423 ret i32* %r 424} 425 426define arm_aapcscc void @test_br() { 427; CHECK-LABEL: test_br 428; CHECK: [[LABEL:.L[[:alnum:]_]+]]: 429; CHECK: b [[LABEL]] 430entry: 431 br label %infinite 432 433infinite: 434 br label %infinite 435} 436 437declare arm_aapcscc void @brcond1() 438declare arm_aapcscc void @brcond2() 439 440define 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 449entry: 450 %cmp = icmp sgt i32 %n, 0 451 br i1 %cmp, label %if.true, label %if.false 452 453if.true: 454 call arm_aapcscc void @brcond1() 455 br label %if.end 456 457if.false: 458 call arm_aapcscc void @brcond2() 459 br label %if.end 460 461if.end: 462 ret void 463} 464