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