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