OLD | NEW |
1 ; This tests the optimization where producers and consumers of i1 (bool) | 1 ; This tests the optimization where producers and consumers of i1 (bool) |
2 ; variables are combined to implicitly use flags instead of explicitly using | 2 ; variables are combined to implicitly use flags instead of explicitly using |
3 ; stack or register variables. | 3 ; stack or register variables. |
4 | 4 |
5 ; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 \ | 5 ; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 \ |
6 ; RUN: -allow-externally-defined-symbols | FileCheck %s | 6 ; RUN: -allow-externally-defined-symbols | FileCheck %s |
7 | 7 |
8 ; RUN: %if --need=allow_dump --need=target_ARM32 --command %p2i --filetype=asm \ | 8 ; RUN: %if --need=target_ARM32 --command %p2i --filetype=obj \ |
9 ; RUN: --target arm32 -i %s --args -O2 --skip-unimplemented \ | 9 ; RUN: --target arm32 -i %s --disassemble --args -O2 \ |
10 ; RUN: -allow-externally-defined-symbols \ | 10 ; RUN: -allow-externally-defined-symbols \ |
11 ; RUN: | %if --need=allow_dump --need=target_ARM32 --command FileCheck %s \ | 11 ; RUN: | %if --need=target_ARM32 --command FileCheck %s \ |
12 ; RUN: --check-prefix=ARM32 | 12 ; RUN: --check-prefix=ARM32 |
13 | 13 |
14 declare void @use_value(i32) | 14 declare void @use_value(i32) |
15 | 15 |
16 ; Basic cmp/branch folding. | 16 ; Basic cmp/branch folding. |
17 define internal i32 @fold_cmp_br(i32 %arg1, i32 %arg2) { | 17 define internal i32 @fold_cmp_br(i32 %arg1, i32 %arg2) { |
18 entry: | 18 entry: |
19 %cmp1 = icmp slt i32 %arg1, %arg2 | 19 %cmp1 = icmp slt i32 %arg1, %arg2 |
20 br i1 %cmp1, label %branch1, label %branch2 | 20 br i1 %cmp1, label %branch1, label %branch2 |
21 branch1: | 21 branch1: |
(...skipping 26 matching lines...) Expand all Loading... |
48 ret i32 2 | 48 ret i32 2 |
49 } | 49 } |
50 | 50 |
51 ; CHECK-LABEL: fold_cmp_br_intervening_insts | 51 ; CHECK-LABEL: fold_cmp_br_intervening_insts |
52 ; CHECK-NOT: cmp | 52 ; CHECK-NOT: cmp |
53 ; CHECK: call | 53 ; CHECK: call |
54 ; CHECK: cmp | 54 ; CHECK: cmp |
55 ; CHECK: jge | 55 ; CHECK: jge |
56 ; ARM32-LABEL: fold_cmp_br_intervening_insts | 56 ; ARM32-LABEL: fold_cmp_br_intervening_insts |
57 ; ARM32: push {{[{].*[}]}} | 57 ; ARM32: push {{[{].*[}]}} |
58 ; ARM32: bl use_value | 58 ; ARM32: bl{{.*}}use_value |
59 ; ARM32: cmp {{r[0-9]+}}, {{r[0-9]+}} | 59 ; ARM32: cmp {{r[0-9]+}}, {{r[0-9]+}} |
60 ; ARM32: bge | 60 ; ARM32: bge |
61 ; ARM32: mov r0, #1 | 61 ; ARM32: mov r0, #1 |
62 ; ARM32: bx lr | 62 ; ARM32: bx lr |
63 ; ARM32: mov r0, #2 | 63 ; ARM32: mov r0, #2 |
64 ; ARM32: bx lr | 64 ; ARM32: bx lr |
65 | 65 |
66 | 66 |
67 ; Cmp/branch non-folding because of live-out. | 67 ; Cmp/branch non-folding because of live-out. |
68 define internal i32 @no_fold_cmp_br_liveout(i32 %arg1, i32 %arg2) { | 68 define internal i32 @no_fold_cmp_br_liveout(i32 %arg1, i32 %arg2) { |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 %result = select i1 %cmp1, i32 %arg1, i32 %arg2 | 183 %result = select i1 %cmp1, i32 %arg1, i32 %arg2 |
184 ret i32 %result | 184 ret i32 %result |
185 } | 185 } |
186 | 186 |
187 ; CHECK-LABEL: fold_cmp_select_intervening_insts | 187 ; CHECK-LABEL: fold_cmp_select_intervening_insts |
188 ; CHECK-NOT: cmp | 188 ; CHECK-NOT: cmp |
189 ; CHECK: call | 189 ; CHECK: call |
190 ; CHECK: cmp | 190 ; CHECK: cmp |
191 ; CHECK: cmovl | 191 ; CHECK: cmovl |
192 ; ARM32-LABEL: fold_cmp_select_intervening_insts | 192 ; ARM32-LABEL: fold_cmp_select_intervening_insts |
193 ; ARM32: bl use_value | 193 ; ARM32: bl{{.*}}use_value |
194 ; ARM32: cmp r{{[0-9]+}}, r{{[0-9]+}} | 194 ; ARM32: cmp r{{[0-9]+}}, r{{[0-9]+}} |
195 ; ARM32: movlt | 195 ; ARM32: movlt |
196 ; ARM32: bx lr | 196 ; ARM32: bx lr |
197 | 197 |
198 ; Cmp/multi-select folding. | 198 ; Cmp/multi-select folding. |
199 define internal i32 @fold_cmp_select_multi(i32 %arg1, i32 %arg2) { | 199 define internal i32 @fold_cmp_select_multi(i32 %arg1, i32 %arg2) { |
200 entry: | 200 entry: |
201 %cmp1 = icmp slt i32 %arg1, %arg2 | 201 %cmp1 = icmp slt i32 %arg1, %arg2 |
202 %a = select i1 %cmp1, i32 %arg1, i32 %arg2 | 202 %a = select i1 %cmp1, i32 %arg1, i32 %arg2 |
203 %b = select i1 %cmp1, i32 %arg2, i32 %arg1 | 203 %b = select i1 %cmp1, i32 %arg2, i32 %arg1 |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 br i1 %t2, label %target_true, label %target_false | 370 br i1 %t2, label %target_true, label %target_false |
371 | 371 |
372 target_true: | 372 target_true: |
373 ret i32 1 | 373 ret i32 1 |
374 | 374 |
375 target_false: | 375 target_false: |
376 ret i32 0 | 376 ret i32 0 |
377 } | 377 } |
378 ; ARM32-LABEL: br_i1_folding2_and | 378 ; ARM32-LABEL: br_i1_folding2_and |
379 ; ARM32: tst r0, #1 | 379 ; ARM32: tst r0, #1 |
380 ; ARM32: beq {{.*}}target_false | 380 ; ARM32: beq |
381 ; ARM32: tst r1, #1 | 381 ; ARM32: tst r1, #1 |
382 ; ARM32: beq {{.*}}target_false | 382 ; ARM32: beq |
383 | 383 |
384 define internal i32 @br_i1_folding2_or(i32 %arg1, i32 %arg2) { | 384 define internal i32 @br_i1_folding2_or(i32 %arg1, i32 %arg2) { |
385 %t0 = trunc i32 %arg1 to i1 | 385 %t0 = trunc i32 %arg1 to i1 |
386 %t1 = trunc i32 %arg2 to i1 | 386 %t1 = trunc i32 %arg2 to i1 |
387 | 387 |
388 %t2 = or i1 %t0, %t1 | 388 %t2 = or i1 %t0, %t1 |
389 br i1 %t2, label %target_true, label %target_false | 389 br i1 %t2, label %target_true, label %target_false |
390 | 390 |
391 target_true: | 391 target_true: |
392 ret i32 1 | 392 ret i32 1 |
393 | 393 |
394 target_false: | 394 target_false: |
395 ret i32 0 | 395 ret i32 0 |
396 } | 396 } |
397 ; ARM32-LABEL: br_i1_folding2_or | 397 ; ARM32-LABEL: br_i1_folding2_or |
398 ; ARM32: tst r0, #1 | 398 ; ARM32: tst r0, #1 |
399 ; ARM32: bne {{.*}}target_true | 399 ; ARM32: bne |
400 ; ARM32: tst r1, #1 | 400 ; ARM32: tst r1, #1 |
401 ; ARM32: beq {{.*}}target_false | 401 ; ARM32: beq |
402 | 402 |
403 define internal i32 @br_i1_folding3_and_or(i32 %arg1, i32 %arg2, i32 %arg3) { | 403 define internal i32 @br_i1_folding3_and_or(i32 %arg1, i32 %arg2, i32 %arg3) { |
404 %t0 = trunc i32 %arg1 to i1 | 404 %t0 = trunc i32 %arg1 to i1 |
405 %t1 = trunc i32 %arg2 to i1 | 405 %t1 = trunc i32 %arg2 to i1 |
406 %t2 = trunc i32 %arg3 to i1 | 406 %t2 = trunc i32 %arg3 to i1 |
407 | 407 |
408 %t3 = and i1 %t0, %t1 | 408 %t3 = and i1 %t0, %t1 |
409 %t4 = or i1 %t3, %t2 | 409 %t4 = or i1 %t3, %t2 |
410 | 410 |
411 br i1 %t4, label %target_true, label %target_false | 411 br i1 %t4, label %target_true, label %target_false |
412 | 412 |
413 target_true: | 413 target_true: |
414 ret i32 1 | 414 ret i32 1 |
415 | 415 |
416 target_false: | 416 target_false: |
417 ret i32 0 | 417 ret i32 0 |
418 } | 418 } |
419 ; ARM32-LABEL: br_i1_folding3_and_or | 419 ; ARM32-LABEL: br_i1_folding3_and_or |
420 ; ARM32: tst r0, #1 | 420 ; ARM32: tst r0, #1 |
421 ; ARM32: beq | 421 ; ARM32: beq |
422 ; ARM32: tst r1, #1 | 422 ; ARM32: tst r1, #1 |
423 ; ARM32: bne {{.*}}target_true | 423 ; ARM32: bne |
424 ; ARM32: tst r2, #1 | 424 ; ARM32: tst r2, #1 |
425 ; ARM32: beq {{.*}}target_false | 425 ; ARM32: beq |
426 | 426 |
427 define internal i32 @br_i1_folding3_or_and(i32 %arg1, i32 %arg2, i32 %arg3) { | 427 define internal i32 @br_i1_folding3_or_and(i32 %arg1, i32 %arg2, i32 %arg3) { |
428 %t0 = trunc i32 %arg1 to i1 | 428 %t0 = trunc i32 %arg1 to i1 |
429 %t1 = trunc i32 %arg2 to i1 | 429 %t1 = trunc i32 %arg2 to i1 |
430 %t2 = trunc i32 %arg3 to i1 | 430 %t2 = trunc i32 %arg3 to i1 |
431 | 431 |
432 %t3 = or i1 %t0, %t1 | 432 %t3 = or i1 %t0, %t1 |
433 %t4 = and i1 %t3, %t2 | 433 %t4 = and i1 %t3, %t2 |
434 | 434 |
435 br i1 %t4, label %target_true, label %target_false | 435 br i1 %t4, label %target_true, label %target_false |
436 | 436 |
437 target_true: | 437 target_true: |
438 ret i32 1 | 438 ret i32 1 |
439 | 439 |
440 target_false: | 440 target_false: |
441 ret i32 0 | 441 ret i32 0 |
442 } | 442 } |
443 ; ARM32-LABEL: br_i1_folding3_or_and | 443 ; ARM32-LABEL: br_i1_folding3_or_and |
444 ; ARM32: tst r0, #1 | 444 ; ARM32: tst r0, #1 |
445 ; ARM32: bne | 445 ; ARM32: bne |
446 ; ARM32: tst r1, #1 | 446 ; ARM32: tst r1, #1 |
447 ; ARM32: beq {{.*}}target_false | 447 ; ARM32: beq |
448 ; ARM32: tst r2, #1 | 448 ; ARM32: tst r2, #1 |
449 ; ARM32: beq {{.*}}target_false | 449 ; ARM32: beq |
450 | 450 |
451 define internal i32 @br_i1_folding4(i32 %arg1, i32 %arg2, i32 %arg3, i32 %arg4, | 451 define internal i32 @br_i1_folding4(i32 %arg1, i32 %arg2, i32 %arg3, i32 %arg4, |
452 i32 %arg5) { | 452 i32 %arg5) { |
453 %t0 = trunc i32 %arg1 to i1 | 453 %t0 = trunc i32 %arg1 to i1 |
454 %t1 = trunc i32 %arg2 to i1 | 454 %t1 = trunc i32 %arg2 to i1 |
455 %t2 = trunc i32 %arg3 to i1 | 455 %t2 = trunc i32 %arg3 to i1 |
456 %t3 = trunc i32 %arg4 to i1 | 456 %t3 = trunc i32 %arg4 to i1 |
457 %t4 = trunc i32 %arg5 to i1 | 457 %t4 = trunc i32 %arg5 to i1 |
458 | 458 |
459 %t5 = or i1 %t0, %t1 | 459 %t5 = or i1 %t0, %t1 |
460 %t6 = and i1 %t5, %t2 | 460 %t6 = and i1 %t5, %t2 |
461 %t7 = and i1 %t3, %t4 | 461 %t7 = and i1 %t3, %t4 |
462 %t8 = or i1 %t6, %t7 | 462 %t8 = or i1 %t6, %t7 |
463 br i1 %t8, label %target_true, label %target_false | 463 br i1 %t8, label %target_true, label %target_false |
464 | 464 |
465 target_true: | 465 target_true: |
466 ret i32 1 | 466 ret i32 1 |
467 | 467 |
468 target_false: | 468 target_false: |
469 ret i32 0 | 469 ret i32 0 |
470 } | 470 } |
471 ; ARM32-LABEL: br_i1_folding4 | 471 ; ARM32-LABEL: br_i1_folding4 |
472 ; ARM32: tst r0, #1 | 472 ; ARM32: tst r0, #1 |
473 ; ARM32: bne | 473 ; ARM32: bne |
474 ; ARM32: tst r1, #1 | 474 ; ARM32: tst r1, #1 |
475 ; ARM32: beq | 475 ; ARM32: beq |
476 ; ARM32: tst r2, #1 | 476 ; ARM32: tst r2, #1 |
477 ; ARM32: bne {{.*}}target_true | 477 ; ARM32: bne |
478 ; ARM32: tst r3, #1 | 478 ; ARM32: tst r3, #1 |
479 ; ARM32: beq {{.*}}target_false | 479 ; ARM32: beq [[TARGET:.*]] |
480 ; ARM32: tst r4, #1 | 480 ; ARM32: tst r4, #1 |
481 ; ARM32: beq {{.*}}target_false | 481 ; ARM32: beq [[TARGET]] |
OLD | NEW |