Skip to content

Commit 4e545bd

Browse files
committed
[SimplifyCFG] Thread branches on same condition in more cases (PR54980)
SimplifyCFG implements basic jump threading, if a branch is performed on a phi node with constant operands. However, InstCombine canonicalizes such phis to the condition value of a previous branch, if possible. SimplifyCFG does support this as well, but only in the very limited case where the same condition is used in a direct predecessor -- notably, this does not include the common diamond pattern (i.e. two consecutive if/elses on the same condition). This patch extends the code to look back a limited number of blocks to find a branch on the same value, rather than only looking at the direct predecessor. Fixes llvm/llvm-project#54980. Differential Revision: https://reviews.llvm.org/D124159
1 parent db1cec3 commit 4e545bd

File tree

8 files changed

+53
-50
lines changed

8 files changed

+53
-50
lines changed

clang/test/CodeGenObjC/exceptions.m

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@ void f1(void) {
2525
// CHECK-NEXT: icmp
2626
// CHECK-NEXT: br i1
2727
@try {
28-
// CHECK: call void asm sideeffect "", "=*m"
2928
// CHECK: call void asm sideeffect "", "*m"
3029
// CHECK-NEXT: call void @foo()
3130
foo();
3231
// CHECK: call void @objc_exception_try_exit
32+
// CHECK: try.handler:
33+
// CHECK: call void asm sideeffect "", "=*m"
3334

3435
} @finally {
3536
break;
@@ -53,12 +54,6 @@ int f2(void) {
5354
// CHECK-NEXT: [[CAUGHT:%.*]] = icmp eq i32 [[SETJMP]], 0
5455
// CHECK-NEXT: br i1 [[CAUGHT]]
5556
@try {
56-
// Landing pad. Note that we elide the re-enter.
57-
// CHECK: call void asm sideeffect "", "=*m,=*m"(i32* nonnull elementtype(i32) [[X]]
58-
// CHECK-NEXT: call i8* @objc_exception_extract
59-
// CHECK-NEXT: [[T1:%.*]] = load i32, i32* [[X]]
60-
// CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], -1
61-
6257
// CHECK: store i32 6, i32* [[X]]
6358
x++;
6459
// CHECK-NEXT: call void asm sideeffect "", "*m,*m"(i32* nonnull elementtype(i32) [[X]]
@@ -67,6 +62,12 @@ int f2(void) {
6762
// CHECK-NEXT: [[T:%.*]] = load i32, i32* [[X]]
6863
foo();
6964
} @catch (id) {
65+
// Landing pad. Note that we elide the re-enter.
66+
// CHECK: call void asm sideeffect "", "=*m,=*m"(i32* nonnull elementtype(i32) [[X]]
67+
// CHECK-NEXT: call i8* @objc_exception_extract
68+
// CHECK-NEXT: [[T1:%.*]] = load i32, i32* [[X]]
69+
// CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], -1
70+
7071
x--;
7172
}
7273

clang/test/CodeGenObjCXX/exceptions-legacy.mm

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,19 @@ void test1(id obj, bool *failed) {
6363
// Body.
6464
// CHECK: invoke void @_Z3foov()
6565

66-
// Catch handler. Reload of 'failed' address is unnecessary.
67-
// CHECK: [[T0:%.*]] = load i8*, i8**
68-
// CHECK-NEXT: store i8 1, i8* [[T0]],
69-
// CHECK-NEXT: br label
70-
7166
// Leave the @try.
7267
// CHECK: call void @objc_exception_try_exit([[BUF_T]]* nonnull [[BUF]])
7368
// CHECK-NEXT: br label
7469
// CHECK: ret void
7570

76-
7771
// Real EH cleanup.
7872
// CHECK: [[T0:%.*]] = landingpad
7973
// CHECK-NEXT: cleanup
8074
// CHECK-NEXT: call void @objc_exception_try_exit([[BUF_T]]* nonnull [[BUF]])
8175
// CHECK-NEXT: resume
8276

77+
// Catch handler. Reload of 'failed' address is unnecessary.
78+
// CHECK: [[T0:%.*]] = load i8*, i8**
79+
// CHECK-NEXT: store i8 1, i8* [[T0]],
80+
// CHECK-NEXT: br label
81+

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2975,8 +2975,10 @@ static bool BlockIsSimpleEnoughToThreadThrough(BasicBlock *BB) {
29752975
return true;
29762976
}
29772977

2978-
static ConstantInt *getKnownValueOnEdge(Value *V, BasicBlock *From,
2979-
BasicBlock *To) {
2978+
static ConstantInt *
2979+
getKnownValueOnEdge(Value *V, BasicBlock *From, BasicBlock *To,
2980+
SmallDenseMap<std::pair<BasicBlock *, BasicBlock *>,
2981+
ConstantInt *> &Visited) {
29802982
// Don't look past the block defining the value, we might get the value from
29812983
// a previous loop iteration.
29822984
auto *I = dyn_cast<Instruction>(V);
@@ -2990,7 +2992,23 @@ static ConstantInt *getKnownValueOnEdge(Value *V, BasicBlock *From,
29902992
return BI->getSuccessor(0) == To ? ConstantInt::getTrue(BI->getContext())
29912993
: ConstantInt::getFalse(BI->getContext());
29922994

2993-
return nullptr;
2995+
// Limit the amount of blocks we inspect.
2996+
if (Visited.size() >= 8)
2997+
return nullptr;
2998+
2999+
auto Pair = Visited.try_emplace({From, To}, nullptr);
3000+
if (!Pair.second)
3001+
return Pair.first->second;
3002+
3003+
// Check whether the known value is the same for all predecessors.
3004+
ConstantInt *Common = nullptr;
3005+
for (BasicBlock *Pred : predecessors(From)) {
3006+
ConstantInt *C = getKnownValueOnEdge(V, Pred, From, Visited);
3007+
if (!C || (Common && Common != C))
3008+
return nullptr;
3009+
Common = C;
3010+
}
3011+
return Visited[{From, To}] = Common;
29943012
}
29953013

29963014
/// If we have a conditional branch on something for which we know the constant
@@ -3015,8 +3033,9 @@ FoldCondBranchOnValueKnownInPredecessorImpl(BranchInst *BI, DomTreeUpdater *DTU,
30153033
if (auto *CB = dyn_cast<ConstantInt>(U))
30163034
KnownValues.insert({PN->getIncomingBlock(U), CB});
30173035
} else {
3036+
SmallDenseMap<std::pair<BasicBlock *, BasicBlock *>, ConstantInt *> Visited;
30183037
for (BasicBlock *Pred : predecessors(BB)) {
3019-
if (ConstantInt *CB = getKnownValueOnEdge(Cond, Pred, BB))
3038+
if (ConstantInt *CB = getKnownValueOnEdge(Cond, Pred, BB, Visited))
30203039
KnownValues.insert({Pred, CB});
30213040
}
30223041
}

llvm/test/CodeGen/AArch64/arm64-andCmpBrToTBZ.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ if.then3: ; preds = %_ZNK7WebCore4Node10
3636
if.end5: ; preds = %_ZNK7WebCore4Node10hasTagNameERKNS_13QualifiedNameE.exit, %lor.rhs.i.i.i
3737
; CHECK: %if.end5
3838
; CHECK: tbz
39-
br i1 %tobool.i.i.i, label %if.end12, label %land.rhs.i19, !prof !1
39+
br i1 %IsEditable, label %if.end12, label %land.rhs.i19, !prof !1
4040

4141
land.rhs.i19: ; preds = %if.end5
4242
%cmp.i.i.i18 = icmp eq i8* %str6, %str7

llvm/test/Transforms/GVNSink/sink-common-code.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ succ:
604604
declare void @g()
605605

606606
; CHECK-LABEL: test_pr30292
607-
; CHECK: phi i32 [ 0, %entry ], [ %add1, %succ ], [ %add2, %two ]
607+
; CHECK: phi i32 [ 0, %entry ], [ %add1, %succ ]
608608

609609
define zeroext i1 @test_pr30244(i1 zeroext %flag, i1 zeroext %flag2, i32 %blksA, i32 %blksB, i32 %nblks) {
610610

llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -885,9 +885,9 @@ define void @test_pr30292(i1 %cond, i1 %cond2, i32 %a, i32 %b) {
885885
; CHECK: two:
886886
; CHECK-NEXT: call void @g()
887887
; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[A]], 1
888-
; CHECK-NEXT: br label [[SUCC]]
888+
; CHECK-NEXT: br label [[TWO:%.*]]
889889
; CHECK: succ:
890-
; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD1]], [[SUCC]] ], [ [[ADD2]], [[TWO:%.*]] ]
890+
; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD1]], [[SUCC]] ]
891891
; CHECK-NEXT: br i1 [[COND:%.*]], label [[TWO]], label [[SUCC]]
892892
;
893893
entry:

llvm/test/Transforms/SimplifyCFG/jump-threading.ll

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -144,16 +144,10 @@ define void @test_same_cond_simple(i1 %c) {
144144
; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
145145
; CHECK: if:
146146
; CHECK-NEXT: call void @foo()
147-
; CHECK-NEXT: br label [[JOIN:%.*]]
148-
; CHECK: else:
149-
; CHECK-NEXT: call void @bar()
150-
; CHECK-NEXT: br label [[JOIN]]
151-
; CHECK: join:
152-
; CHECK-NEXT: br i1 [[C]], label [[IF2:%.*]], label [[ELSE2:%.*]]
153-
; CHECK: if2:
154147
; CHECK-NEXT: call void @foo()
155148
; CHECK-NEXT: br label [[JOIN2:%.*]]
156-
; CHECK: else2:
149+
; CHECK: else:
150+
; CHECK-NEXT: call void @bar()
157151
; CHECK-NEXT: call void @bar()
158152
; CHECK-NEXT: br label [[JOIN2]]
159153
; CHECK: join2:
@@ -189,17 +183,12 @@ define void @test_same_cond_extra_use(i1 %c) {
189183
; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
190184
; CHECK: if:
191185
; CHECK-NEXT: call void @foo()
192-
; CHECK-NEXT: br label [[JOIN:%.*]]
193-
; CHECK: else:
194-
; CHECK-NEXT: call void @bar()
195-
; CHECK-NEXT: br label [[JOIN]]
196-
; CHECK: join:
197186
; CHECK-NEXT: call void @use.i1(i1 [[C]])
198-
; CHECK-NEXT: br i1 [[C]], label [[IF2:%.*]], label [[ELSE2:%.*]]
199-
; CHECK: if2:
200187
; CHECK-NEXT: call void @foo()
201188
; CHECK-NEXT: br label [[JOIN2:%.*]]
202-
; CHECK: else2:
189+
; CHECK: else:
190+
; CHECK-NEXT: call void @bar()
191+
; CHECK-NEXT: call void @use.i1(i1 [[C]])
203192
; CHECK-NEXT: call void @bar()
204193
; CHECK-NEXT: br label [[JOIN2]]
205194
; CHECK: join2:
@@ -236,17 +225,11 @@ define void @test_same_cond_extra_use_different_block(i1 %c) {
236225
; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
237226
; CHECK: if:
238227
; CHECK-NEXT: call void @foo()
239-
; CHECK-NEXT: br label [[JOIN:%.*]]
240-
; CHECK: else:
241-
; CHECK-NEXT: call void @bar()
242-
; CHECK-NEXT: br label [[JOIN]]
243-
; CHECK: join:
244-
; CHECK-NEXT: br i1 [[C]], label [[IF2:%.*]], label [[ELSE2:%.*]]
245-
; CHECK: if2:
246228
; CHECK-NEXT: call void @use.i1(i1 [[C]])
247229
; CHECK-NEXT: call void @foo()
248230
; CHECK-NEXT: br label [[JOIN2:%.*]]
249-
; CHECK: else2:
231+
; CHECK: else:
232+
; CHECK-NEXT: call void @bar()
250233
; CHECK-NEXT: call void @use.i1(i1 [[C]])
251234
; CHECK-NEXT: call void @bar()
252235
; CHECK-NEXT: br label [[JOIN2]]

llvm/test/Transforms/SimplifyCFG/wc-widen-block.ll

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -269,17 +269,18 @@ return:
269269
define i32 @neg_loop(i1 %cond_0, i1 %cond_1) {
270270
; CHECK-LABEL: @neg_loop(
271271
; CHECK-NEXT: entry:
272-
; CHECK-NEXT: br label [[GUARDED:%.*]]
272+
; CHECK-NEXT: call void @unknown()
273+
; CHECK-NEXT: br i1 [[COND_1:%.*]], label [[LOOP:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
274+
; CHECK: loop.critedge:
275+
; CHECK-NEXT: call void @unknown()
276+
; CHECK-NEXT: br label [[LOOP]]
273277
; CHECK: loop:
274278
; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
275279
; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]]
276-
; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
280+
; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[LOOP_CRITEDGE:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
277281
; CHECK: deopt:
278282
; CHECK-NEXT: [[DEOPTRET:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
279283
; CHECK-NEXT: ret i32 [[DEOPTRET]]
280-
; CHECK: guarded:
281-
; CHECK-NEXT: call void @unknown()
282-
; CHECK-NEXT: br i1 [[COND_1:%.*]], label [[LOOP:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
283284
; CHECK: deopt2:
284285
; CHECK-NEXT: [[DEOPTRET2:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
285286
; CHECK-NEXT: ret i32 [[DEOPTRET2]]

0 commit comments

Comments
 (0)