| 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 |