Skip to content

Commit 4ab4a8e

Browse files
committed
Fix PR10103: Less code for enum type translation.
In cases such as the attached test, where the case value for a switch destination is used in a phi node that follows the destination, it might be better to replace that value with the condition value of the switch, so that more blocks can be folded away with TryToSimplifyUncondBranchFromEmptyBlock because there are less conflicts in the phi node. llvm-svn: 133344
1 parent 54a2c06 commit 4ab4a8e

File tree

3 files changed

+111
-1
lines changed

3 files changed

+111
-1
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2450,6 +2450,77 @@ static bool EliminateDeadSwitchCases(SwitchInst *SI) {
24502450
return !DeadCases.empty();
24512451
}
24522452

2453+
/// FindPHIForConditionForwarding - If BB would be eligible for simplification
2454+
/// by TryToSimplifyUncondBranchFromEmptyBlock (i.e. it is empty and terminated
2455+
/// by an unconditional branch), look at the phi node for BB in the successor
2456+
/// block and see if the incoming value is equal to CaseValue. If so, return
2457+
/// the phi node, and set PhiIndex to BB's index in the phi node.
2458+
static PHINode *FindPHIForConditionForwarding(ConstantInt *CaseValue,
2459+
BasicBlock *BB,
2460+
int *PhiIndex) {
2461+
if (BB->getFirstNonPHIOrDbg() != BB->getTerminator())
2462+
return NULL; // BB must be empty to be a candidate for simplification.
2463+
if (!BB->getSinglePredecessor())
2464+
return NULL; // BB must be dominated by the switch.
2465+
2466+
BranchInst *Branch = dyn_cast<BranchInst>(BB->getTerminator());
2467+
if (!Branch || !Branch->isUnconditional())
2468+
return NULL; // Terminator must be unconditional branch.
2469+
2470+
BasicBlock *Succ = Branch->getSuccessor(0);
2471+
2472+
BasicBlock::iterator I = Succ->begin();
2473+
while (PHINode *PHI = dyn_cast<PHINode>(I++)) {
2474+
int Idx = PHI->getBasicBlockIndex(BB);
2475+
assert(Idx >= 0 && "PHI has no entry for predecessor?");
2476+
2477+
Value *InValue = PHI->getIncomingValue(Idx);
2478+
if (InValue != CaseValue) continue;
2479+
2480+
*PhiIndex = Idx;
2481+
return PHI;
2482+
}
2483+
2484+
return NULL;
2485+
}
2486+
2487+
/// ForwardSwitchConditionToPHI - Try to forward the condition of a switch
2488+
/// instruction to a phi node dominated by the switch, if that would mean that
2489+
/// some of the destination blocks of the switch can be folded away.
2490+
/// Returns true if a change is made.
2491+
static bool ForwardSwitchConditionToPHI(SwitchInst *SI) {
2492+
typedef DenseMap<PHINode*, SmallVector<int,4> > ForwardingNodesMap;
2493+
ForwardingNodesMap ForwardingNodes;
2494+
2495+
for (unsigned I = 1; I < SI->getNumCases(); ++I) { // 0 is the default case.
2496+
ConstantInt *CaseValue = SI->getCaseValue(I);
2497+
BasicBlock *CaseDest = SI->getSuccessor(I);
2498+
2499+
int PhiIndex;
2500+
PHINode *PHI = FindPHIForConditionForwarding(CaseValue, CaseDest,
2501+
&PhiIndex);
2502+
if (!PHI) continue;
2503+
2504+
ForwardingNodes[PHI].push_back(PhiIndex);
2505+
}
2506+
2507+
bool Changed = false;
2508+
2509+
for (ForwardingNodesMap::iterator I = ForwardingNodes.begin(),
2510+
E = ForwardingNodes.end(); I != E; ++I) {
2511+
PHINode *Phi = I->first;
2512+
SmallVector<int,4> &Indexes = I->second;
2513+
2514+
if (Indexes.size() < 2) continue;
2515+
2516+
for (size_t I = 0, E = Indexes.size(); I != E; ++I)
2517+
Phi->setIncomingValue(Indexes[I], SI->getCondition());
2518+
Changed = true;
2519+
}
2520+
2521+
return Changed;
2522+
}
2523+
24532524
bool SimplifyCFGOpt::SimplifySwitch(SwitchInst *SI, IRBuilder<> &Builder) {
24542525
// If this switch is too complex to want to look at, ignore it.
24552526
if (!isValueEqualityComparison(SI))
@@ -2486,6 +2557,9 @@ bool SimplifyCFGOpt::SimplifySwitch(SwitchInst *SI, IRBuilder<> &Builder) {
24862557
if (EliminateDeadSwitchCases(SI))
24872558
return SimplifyCFG(BB) | true;
24882559

2560+
if (ForwardSwitchConditionToPHI(SI))
2561+
return SimplifyCFG(BB) | true;
2562+
24892563
return false;
24902564
}
24912565

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
; RUN: opt < %s -simplifycfg -S | \
2+
; RUN: not grep " switch"
3+
; PR10131
4+
5+
; ModuleID = '<stdin>'
6+
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
7+
target triple = "i386-pc-linux-gnu"
8+
9+
define i32 @t(i32 %m) nounwind readnone {
10+
entry:
11+
switch i32 %m, label %sw.bb4 [
12+
i32 0, label %sw.bb0
13+
i32 1, label %sw.bb1
14+
i32 2, label %sw.bb2
15+
i32 3, label %sw.bb3
16+
]
17+
18+
sw.bb0: ; preds = %entry
19+
br label %return
20+
21+
sw.bb1: ; preds = %entry
22+
br label %return
23+
24+
sw.bb2: ; preds = %entry
25+
br label %return
26+
27+
sw.bb3: ; preds = %entry
28+
br label %return
29+
30+
sw.bb4: ; preds = %entry
31+
br label %return
32+
33+
return: ; preds = %entry, %sw.bb4, %sw.bb3, %sw.bb2, %sw.bb1
34+
%retval.0 = phi i32 [ 4, %sw.bb4 ], [ 3, %sw.bb3 ], [ 2, %sw.bb2 ], [ 1, %sw.bb1 ], [ 0, %sw.bb0 ]
35+
ret i32 %retval.0
36+
}

llvm/test/Transforms/SimplifyCFG/switch_switch_fold_dbginfo.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; RUN: opt < %s -simplifycfg -S | \
2-
; RUN: grep switch | count 1
2+
; RUN: not grep " switch"
33

44
; ModuleID = '<stdin>'
55
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32"

0 commit comments

Comments
 (0)