| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt %s -S -o - -passes=simplifycfg | FileCheck %s |
| |
| %struct.S = type { [4 x i32] } |
| |
| ; Check the second, third, and fourth basic blocks are folded into |
| ; the first basic block since each has one bonus intruction, which |
| ; does not exceed the default bouns instruction threshold of 1. |
| |
| define i1 @test1(i32 %0, i32 %1, i32 %2, i32 %3) { |
| ; CHECK-LABEL: @test1( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[MUL0:%.*]] = mul i32 [[TMP0:%.*]], [[TMP0]] |
| ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[MUL0]], 0 |
| ; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[TMP1:%.*]], [[TMP1]] |
| ; CHECK-NEXT: [[CMP2_1:%.*]] = icmp sgt i32 [[MUL1]], 0 |
| ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP2]], i1 true, i1 [[CMP2_1]] |
| ; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[TMP2:%.*]], [[TMP2]] |
| ; CHECK-NEXT: [[CMP2_2:%.*]] = icmp sgt i32 [[MUL2]], 0 |
| ; CHECK-NEXT: [[OR_COND1:%.*]] = select i1 [[OR_COND]], i1 true, i1 [[CMP2_2]] |
| ; CHECK-NEXT: [[MUL3:%.*]] = mul i32 [[TMP3:%.*]], [[TMP3]] |
| ; CHECK-NEXT: [[CMP2_3:%.*]] = icmp sgt i32 [[MUL3]], 0 |
| ; CHECK-NEXT: [[OR_COND2:%.*]] = select i1 [[OR_COND1]], i1 true, i1 [[CMP2_3]] |
| ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[OR_COND2]], i1 false, i1 true |
| ; CHECK-NEXT: ret i1 [[SPEC_SELECT]] |
| ; |
| entry: |
| %mul0 = mul i32 %0, %0 |
| %cmp2 = icmp sgt i32 %mul0, 0 |
| br i1 %cmp2, label %cleanup, label %for.cond |
| |
| for.cond: |
| %mul1 = mul i32 %1, %1 |
| %cmp2.1 = icmp sgt i32 %mul1, 0 |
| br i1 %cmp2.1, label %cleanup, label %for.cond.1 |
| |
| for.cond.1: |
| %mul2 = mul i32 %2, %2 |
| %cmp2.2 = icmp sgt i32 %mul2, 0 |
| br i1 %cmp2.2, label %cleanup, label %for.cond.2 |
| |
| for.cond.2: |
| %mul3 = mul i32 %3, %3 |
| %cmp2.3 = icmp sgt i32 %mul3, 0 |
| br i1 %cmp2.3, label %cleanup, label %for.cond.3 |
| |
| for.cond.3: |
| br label %cleanup |
| |
| cleanup: |
| %cmp = phi i1 [ false, %entry ], [ false, %for.cond ], [ false, %for.cond.1 ], [ false, %for.cond.2 ], [ true, %for.cond.3 ] |
| ret i1 %cmp |
| } |
| |
| ; Check the second, third, and forth basic blocks are folded into the first |
| ; basic block since each has no bonus instruction. |
| |
| define i1 @test2(i32 %0, i32 %1, i32 %2, i32 %3) { |
| ; CHECK-LABEL: @test2( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[TMP0:%.*]], 0 |
| ; CHECK-NEXT: [[CMP2_1:%.*]] = icmp sgt i32 [[TMP1:%.*]], 0 |
| ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP2]], i1 true, i1 [[CMP2_1]] |
| ; CHECK-NEXT: [[CMP2_2:%.*]] = icmp sgt i32 [[TMP2:%.*]], 0 |
| ; CHECK-NEXT: [[OR_COND1:%.*]] = select i1 [[OR_COND]], i1 true, i1 [[CMP2_2]] |
| ; CHECK-NEXT: [[CMP2_3:%.*]] = icmp sgt i32 [[TMP3:%.*]], 0 |
| ; CHECK-NEXT: [[OR_COND2:%.*]] = select i1 [[OR_COND1]], i1 true, i1 [[CMP2_3]] |
| ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[OR_COND2]], i1 false, i1 true |
| ; CHECK-NEXT: ret i1 [[SPEC_SELECT]] |
| ; |
| entry: |
| %cmp2 = icmp sgt i32 %0, 0 |
| br i1 %cmp2, label %cleanup, label %for.cond |
| |
| for.cond: |
| %cmp2.1 = icmp sgt i32 %1, 0 |
| br i1 %cmp2.1, label %cleanup, label %for.cond.1 |
| |
| for.cond.1: |
| %cmp2.2 = icmp sgt i32 %2, 0 |
| br i1 %cmp2.2, label %cleanup, label %for.cond.2 |
| |
| for.cond.2: |
| %cmp2.3 = icmp sgt i32 %3, 0 |
| br i1 %cmp2.3, label %cleanup, label %for.cond.3 |
| |
| for.cond.3: |
| br label %cleanup |
| |
| cleanup: |
| %cmp = phi i1 [ false, %entry ], [ false, %for.cond ], [ false, %for.cond.1 ], [ false, %for.cond.2 ], [ true, %for.cond.3 ] |
| ret i1 %cmp |
| } |
| |
| ; Check the second basic block is not folded into the first basic block |
| ; since it has three bonus instructions, which exceeds the default bonus |
| ; instruction threshold of 1. The third and fourth basic blocks are folded |
| ; into the second basic block since they do not have bonus instruction. |
| |
| define i1 @test3(i32 %0, i32 %1, i32 %2, i32 %3) { |
| ; CHECK-LABEL: @test3( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[TMP0:%.*]], 0 |
| ; CHECK-NEXT: br i1 [[CMP2]], label [[CLEANUP:%.*]], label [[FOR_COND:%.*]] |
| ; CHECK: for.cond: |
| ; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[TMP0]], [[TMP1:%.*]] |
| ; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL1]], [[TMP2:%.*]] |
| ; CHECK-NEXT: [[MUL3:%.*]] = mul i32 [[MUL2]], [[TMP3:%.*]] |
| ; CHECK-NEXT: [[MUL4:%.*]] = mul i32 [[MUL3]], [[TMP3]] |
| ; CHECK-NEXT: [[MUL5:%.*]] = mul i32 [[MUL4]], [[TMP3]] |
| ; CHECK-NEXT: [[MUL6:%.*]] = mul i32 [[MUL5]], [[TMP3]] |
| ; CHECK-NEXT: [[CMP2_1:%.*]] = icmp sgt i32 [[MUL5]], 0 |
| ; CHECK-NEXT: [[CMP2_2:%.*]] = icmp sgt i32 [[TMP2]], 0 |
| ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP2_1]], i1 true, i1 [[CMP2_2]] |
| ; CHECK-NEXT: [[CMP2_3:%.*]] = icmp sgt i32 [[TMP3]], 0 |
| ; CHECK-NEXT: [[OR_COND1:%.*]] = select i1 [[OR_COND]], i1 true, i1 [[CMP2_3]] |
| ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[OR_COND1]], i1 false, i1 true |
| ; CHECK-NEXT: br label [[CLEANUP]] |
| ; CHECK: cleanup: |
| ; CHECK-NEXT: [[CMP:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[FOR_COND]] ] |
| ; CHECK-NEXT: ret i1 [[CMP]] |
| ; |
| entry: |
| %cmp2 = icmp sgt i32 %0, 0 |
| br i1 %cmp2, label %cleanup, label %for.cond |
| |
| for.cond: |
| %mul1 = mul i32 %0, %1 |
| %mul2 = mul i32 %mul1, %2 |
| %mul3 = mul i32 %mul2, %3 |
| %mul4 = mul i32 %mul3, %3 |
| %mul5 = mul i32 %mul4, %3 |
| %mul6 = mul i32 %mul5, %3 |
| %cmp2.1 = icmp sgt i32 %mul5, 0 |
| br i1 %cmp2.1, label %cleanup, label %for.cond.1 |
| |
| for.cond.1: |
| %cmp2.2 = icmp sgt i32 %2, 0 |
| br i1 %cmp2.2, label %cleanup, label %for.cond.2 |
| |
| for.cond.2: |
| %cmp2.3 = icmp sgt i32 %3, 0 |
| br i1 %cmp2.3, label %cleanup, label %for.cond.3 |
| |
| for.cond.3: |
| br label %cleanup |
| |
| cleanup: |
| %cmp = phi i1 [ false, %entry ], [ false, %for.cond ], [ false, %for.cond.1 ], [ false, %for.cond.2 ], [ true, %for.cond.3 ] |
| ret i1 %cmp |
| } |