Skip to content

Commit c435cd1

Browse files
[SimplifyCFG] Cache unique predecessors in simplifyDuplicateSwitchArms
Avoid repeatedly querying `getUniquePredecessor` for already-visited switch successors so as not to incur quadratic runtime. Fixes: #147239.
1 parent 1614c3b commit c435cd1

File tree

3 files changed

+59
-14
lines changed

3 files changed

+59
-14
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7493,7 +7493,7 @@ bool SimplifyCFGOpt::simplifyDuplicateSwitchArms(SwitchInst *SI,
74937493
SmallPtrSet<PHINode *, 8> Phis;
74947494
SmallPtrSet<BasicBlock *, 8> Seen;
74957495
DenseMap<PHINode *, SmallDenseMap<BasicBlock *, Value *, 8>> PhiPredIVs;
7496-
DenseMap<BasicBlock *, SmallVector<unsigned, 4>> BBToSuccessorIndexes;
7496+
DenseMap<BasicBlock *, SmallVector<unsigned, 32>> BBToSuccessorIndexes;
74977497
SmallVector<SwitchSuccWrapper> Cases;
74987498
Cases.reserve(SI->getNumSuccessors());
74997499

@@ -7505,27 +7505,31 @@ bool SimplifyCFGOpt::simplifyDuplicateSwitchArms(SwitchInst *SI,
75057505
if (BB->size() != 1)
75067506
continue;
75077507

7508-
// FIXME: This case needs some extra care because the terminators other than
7509-
// SI need to be updated. For now, consider only backedges to the SI.
7510-
if (BB->hasNPredecessorsOrMore(4) ||
7511-
BB->getUniquePredecessor() != SI->getParent())
7512-
continue;
7513-
75147508
// FIXME: Relax that the terminator is a BranchInst by checking for equality
75157509
// on other kinds of terminators. We decide to only support unconditional
75167510
// branches for now for compile time reasons.
75177511
auto *BI = dyn_cast<BranchInst>(BB->getTerminator());
75187512
if (!BI || BI->isConditional())
75197513
continue;
75207514

7521-
if (Seen.insert(BB).second) {
7522-
// Keep track of which PHIs we need as keys in PhiPredIVs below.
7523-
for (BasicBlock *Succ : BI->successors())
7524-
Phis.insert_range(llvm::make_pointer_range(Succ->phis()));
7525-
// Add the successor only if not previously visited.
7526-
Cases.emplace_back(SwitchSuccWrapper{BB, &PhiPredIVs});
7515+
if (!Seen.insert(BB).second) {
7516+
auto It = BBToSuccessorIndexes.find(BB);
7517+
if (It != BBToSuccessorIndexes.end())
7518+
It->second.emplace_back(I);
7519+
continue;
75277520
}
75287521

7522+
// FIXME: This case needs some extra care because the terminators other than
7523+
// SI need to be updated. For now, consider only backedges to the SI.
7524+
if (BB->getUniquePredecessor() != SI->getParent())
7525+
continue;
7526+
7527+
// Keep track of which PHIs we need as keys in PhiPredIVs below.
7528+
for (BasicBlock *Succ : BI->successors())
7529+
Phis.insert_range(llvm::make_pointer_range(Succ->phis()));
7530+
7531+
// Add the successor only if not previously visited.
7532+
Cases.emplace_back(SwitchSuccWrapper{BB, &PhiPredIVs});
75297533
BBToSuccessorIndexes[BB].emplace_back(I);
75307534
}
75317535

llvm/test/Transforms/SimplifyCFG/switch-dup-bbs.ll

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,3 +199,44 @@ exit:
199199
%ret = phi i64 [ 0, %default ], [ 0, %bb1 ], [ 1, %entry ], [ 1, %bb2 ]
200200
ret i64 %ret
201201
}
202+
203+
define i32 @switch_dup_unbounded_predecessors(i32 %val) {
204+
; SIMPLIFY-CFG-LABEL: define i32 @switch_dup_unbounded_predecessors(
205+
; SIMPLIFY-CFG-SAME: i32 [[VAL:%.*]]) {
206+
; SIMPLIFY-CFG-NEXT: [[ENTRY:.*]]:
207+
; SIMPLIFY-CFG-NEXT: switch i32 [[VAL]], label %[[EXIT:.*]] [
208+
; SIMPLIFY-CFG-NEXT: i32 99, label %[[BB1:.*]]
209+
; SIMPLIFY-CFG-NEXT: i32 115, label %[[BB1]]
210+
; SIMPLIFY-CFG-NEXT: i32 102, label %[[BB1]]
211+
; SIMPLIFY-CFG-NEXT: i32 70, label %[[BB1]]
212+
; SIMPLIFY-CFG-NEXT: i32 101, label %[[BB1]]
213+
; SIMPLIFY-CFG-NEXT: i32 69, label %[[BB1]]
214+
; SIMPLIFY-CFG-NEXT: i32 103, label %[[BB1]]
215+
; SIMPLIFY-CFG-NEXT: ]
216+
; SIMPLIFY-CFG: [[BB1]]:
217+
; SIMPLIFY-CFG-NEXT: br label %[[EXIT]]
218+
; SIMPLIFY-CFG: [[EXIT]]:
219+
; SIMPLIFY-CFG-NEXT: [[PHI:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ 1, %[[BB1]] ]
220+
; SIMPLIFY-CFG-NEXT: ret i32 [[PHI]]
221+
;
222+
entry:
223+
switch i32 %val, label %exit [
224+
i32 99, label %bb1
225+
i32 115, label %bb1
226+
i32 102, label %bb2
227+
i32 70, label %bb2
228+
i32 101, label %bb2
229+
i32 69, label %bb2
230+
i32 103, label %bb2
231+
]
232+
233+
bb1:
234+
br label %exit
235+
236+
bb2:
237+
br label %exit
238+
239+
exit:
240+
%phi = phi i32 [ 0, %entry ], [ 1, %bb1 ], [ 1, %bb2 ]
241+
ret i32 %phi
242+
}

llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ unreach2:
149149

150150
define void @pr53208_single_reachable_dest(i8 %sw, ptr %p0) {
151151
; CHECK-LABEL: @pr53208_single_reachable_dest(
152-
; CHECK-NEXT: group2:
152+
; CHECK-NEXT: exit:
153153
; CHECK-NEXT: call void @bar(ptr [[P0:%.*]])
154154
; CHECK-NEXT: ret void
155155
;

0 commit comments

Comments
 (0)