Skip to content

Commit c52af46

Browse files
Teach GVN to also propagate switch cases. For example, in this code
switch (n) { case 27: do_something(x); ... } the call do_something(x) will be replaced with do_something(27). In gcc-as-one-big-file this results in the removal of about 500 lines of bitcode (about 0.02%), so has about 1/10 of the effect of propagating branch conditions. llvm-svn: 141360
1 parent 04e6cbc commit c52af46

File tree

2 files changed

+92
-31
lines changed

2 files changed

+92
-31
lines changed

llvm/lib/Transforms/Scalar/GVN.cpp

Lines changed: 59 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1980,6 +1980,42 @@ bool GVN::propagateEquality(Value *LHS, Value *RHS, BasicBlock *Root) {
19801980
return Changed;
19811981
}
19821982

1983+
/// isOnlyReachableViaThisEdge - There is an edge from 'Src' to 'Dst'. Return
1984+
/// true if every path from the entry block to 'Dst' passes via this edge. In
1985+
/// particular 'Dst' must not be reachable via another edge from 'Src'.
1986+
static bool isOnlyReachableViaThisEdge(BasicBlock *Src, BasicBlock *Dst,
1987+
DominatorTree *DT) {
1988+
// First off, there must not be more than one edge from Src to Dst, there
1989+
// should be exactly one. So keep track of the number of times Src occurs
1990+
// as a predecessor of Dst and fail if it's more than once. Secondly, any
1991+
// other predecessors of Dst should be dominated by Dst (see logic below).
1992+
bool SawEdgeFromSrc = false;
1993+
for (pred_iterator PI = pred_begin(Dst), PE = pred_end(Dst); PI != PE; ++PI) {
1994+
BasicBlock *Pred = *PI;
1995+
if (Pred == Src) {
1996+
// An edge from Src to Dst.
1997+
if (SawEdgeFromSrc)
1998+
// There are multiple edges from Src to Dst - fail.
1999+
return false;
2000+
SawEdgeFromSrc = true;
2001+
continue;
2002+
}
2003+
// If the predecessor is not dominated by Dst, then it must be possible to
2004+
// reach it either without passing through Src (and thus not via the edge)
2005+
// or by passing through Src but taking a different edge out of Src. Either
2006+
// way it is possible to reach Dst without passing via the edge, so fail.
2007+
if (!DT->dominates(Dst, *PI))
2008+
return false;
2009+
}
2010+
assert(SawEdgeFromSrc && "No edge between these basic blocks!");
2011+
2012+
// Every path from the entry block to Dst must at some point pass to Dst from
2013+
// a predecessor that is not dominated by Dst. This predecessor can only be
2014+
// Src, since all others are dominated by Dst. As there is only one edge from
2015+
// Src to Dst, the path passes by this edge.
2016+
return true;
2017+
}
2018+
19832019
/// processInstruction - When calculating availability, handle an instruction
19842020
/// by inserting it into the appropriate sets
19852021
bool GVN::processInstruction(Instruction *I) {
@@ -2011,7 +2047,6 @@ bool GVN::processInstruction(Instruction *I) {
20112047

20122048
// For conditional branches, we can perform simple conditional propagation on
20132049
// the condition value itself.
2014-
// TODO: Add conditional propagation of switch cases.
20152050
if (BranchInst *BI = dyn_cast<BranchInst>(I)) {
20162051
if (!BI->isConditional() || isa<Constant>(BI->getCondition()))
20172052
return false;
@@ -2021,41 +2056,34 @@ bool GVN::processInstruction(Instruction *I) {
20212056
BasicBlock *TrueSucc = BI->getSuccessor(0);
20222057
BasicBlock *FalseSucc = BI->getSuccessor(1);
20232058
BasicBlock *Parent = BI->getParent();
2059+
bool Changed = false;
20242060

2025-
// If the true and false branches are to the same basic block then the
2026-
// branch gives no information about the condition. Eliminating this
2027-
// here simplifies the rest of the logic.
2028-
if (TrueSucc == FalseSucc)
2029-
return false;
2061+
if (isOnlyReachableViaThisEdge(Parent, TrueSucc, DT))
2062+
Changed |= propagateEquality(BranchCond,
2063+
ConstantInt::getTrue(TrueSucc->getContext()),
2064+
TrueSucc);
20302065

2031-
// If the true block can be reached without executing the true edge then we
2032-
// can't say anything about the value of the condition there.
2033-
for (pred_iterator PI = pred_begin(TrueSucc), PE = pred_end(TrueSucc);
2034-
PI != PE; ++PI)
2035-
if (*PI != Parent && !DT->dominates(TrueSucc, *PI)) {
2036-
TrueSucc = 0;
2037-
break;
2038-
}
2066+
if (isOnlyReachableViaThisEdge(Parent, FalseSucc, DT))
2067+
Changed |= propagateEquality(BranchCond,
2068+
ConstantInt::getFalse(FalseSucc->getContext()),
2069+
FalseSucc);
20392070

2040-
// If the false block can be reached without executing the false edge then
2041-
// we can't say anything about the value of the condition there.
2042-
for (pred_iterator PI = pred_begin(FalseSucc), PE = pred_end(FalseSucc);
2043-
PI != PE; ++PI)
2044-
if (*PI != Parent && !DT->dominates(FalseSucc, *PI)) {
2045-
FalseSucc = 0;
2046-
break;
2047-
}
2071+
return Changed;
2072+
}
20482073

2049-
// Replace the condition with true/false in basic blocks that can only be
2050-
// reached via the true/false arm of the branch.
2051-
return (TrueSucc && propagateEquality(BranchCond,
2052-
ConstantInt::getTrue(TrueSucc->getContext()),
2053-
TrueSucc))
2054-
|| (FalseSucc && propagateEquality(BranchCond,
2055-
ConstantInt::getFalse(FalseSucc->getContext()),
2056-
FalseSucc));
2074+
// For switches, propagate the case values into the case destinations.
2075+
if (SwitchInst *SI = dyn_cast<SwitchInst>(I)) {
2076+
Value *SwitchCond = SI->getCondition();
2077+
BasicBlock *Parent = SI->getParent();
2078+
bool Changed = false;
2079+
for (unsigned i = 1, e = SI->getNumCases(); i != e; ++i) {
2080+
BasicBlock *Dst = SI->getSuccessor(i);
2081+
if (isOnlyReachableViaThisEdge(Parent, Dst, DT))
2082+
Changed |= propagateEquality(SwitchCond, SI->getCaseValue(i), Dst);
2083+
}
2084+
return Changed;
20572085
}
2058-
2086+
20592087
// Instructions with void type don't return a value, so there's
20602088
// no point in trying to find redudancies in them.
20612089
if (I->getType()->isVoidTy()) return false;

llvm/test/Transforms/GVN/condprop.ll

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,36 @@ nope:
9797
; CHECK: call void @foo(i1 false)
9898
ret void
9999
}
100+
101+
; CHECK: @test4
102+
define void @test4(i1 %b, i32 %x) {
103+
br i1 %b, label %sw, label %case3
104+
sw:
105+
switch i32 %x, label %default [
106+
i32 0, label %case0
107+
i32 1, label %case1
108+
i32 2, label %case0
109+
i32 3, label %case3
110+
i32 4, label %default
111+
]
112+
default:
113+
; CHECK: default:
114+
call void @bar(i32 %x)
115+
; CHECK: call void @bar(i32 %x)
116+
ret void
117+
case0:
118+
; CHECK: case0:
119+
call void @bar(i32 %x)
120+
; CHECK: call void @bar(i32 %x)
121+
ret void
122+
case1:
123+
; CHECK: case1:
124+
call void @bar(i32 %x)
125+
; CHECK: call void @bar(i32 1)
126+
ret void
127+
case3:
128+
; CHECK: case3:
129+
call void @bar(i32 %x)
130+
; CHECK: call void @bar(i32 %x)
131+
ret void
132+
}

0 commit comments

Comments
 (0)