diff options
| author | Sanjay Patel <spatel@rotateright.com> | 2017-10-22 16:51:03 +0000 |
|---|---|---|
| committer | Sanjay Patel <spatel@rotateright.com> | 2017-10-22 16:51:03 +0000 |
| commit | 24226504a7d18cb626e41f27c8154c95aa2bf08a (patch) | |
| tree | 4e5ac85153f6eedef4f33c50b7eab21bf08d240e /llvm/lib/Transforms | |
| parent | 81b756e6a3e491d43ac18ed39a9ffb13f45b9ea4 (diff) | |
| download | bcm5719-llvm-24226504a7d18cb626e41f27c8154c95aa2bf08a.tar.gz bcm5719-llvm-24226504a7d18cb626e41f27c8154c95aa2bf08a.zip | |
[SimplifyCFG] try harder to forward switch condition to phi (PR34471)
The missed canonicalization/optimization in the motivating test from PR34471 leads to very different codegen:
int switcher(int x) {
switch(x) {
case 17: return 17;
case 19: return 19;
case 42: return 42;
default: break;
}
return 0;
}
int comparator(int x) {
if (x == 17) return 17;
if (x == 19) return 19;
if (x == 42) return 42;
return 0;
}
For the first example, we use a bit-test optimization to avoid a series of compare-and-branch:
https://godbolt.org/g/BivDsw
Differential Revision: https://reviews.llvm.org/D39011
llvm-svn: 316293
Diffstat (limited to 'llvm/lib/Transforms')
| -rw-r--r-- | llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index e7388f63864..42f2bf267f5 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -4450,16 +4450,46 @@ static PHINode *FindPHIForConditionForwarding(ConstantInt *CaseValue, static bool ForwardSwitchConditionToPHI(SwitchInst *SI) { typedef DenseMap<PHINode *, SmallVector<int, 4>> ForwardingNodesMap; ForwardingNodesMap ForwardingNodes; - + BasicBlock *SwitchBlock = SI->getParent(); + bool Changed = false; for (auto &Case : SI->cases()) { ConstantInt *CaseValue = Case.getCaseValue(); BasicBlock *CaseDest = Case.getCaseSuccessor(); + + // Replace phi operands in successor blocks that are using the constant case + // value rather than the switch condition variable: + // switchbb: + // switch i32 %x, label %default [ + // i32 17, label %succ + // ... + // succ: + // %r = phi i32 ... [ 17, %switchbb ] ... + // --> + // %r = phi i32 ... [ %x, %switchbb ] ... + + for (Instruction &InstInCaseDest : *CaseDest) { + auto *Phi = dyn_cast<PHINode>(&InstInCaseDest); + if (!Phi) break; + + // This only works if there is exactly 1 incoming edge from the switch to + // a phi. If there is >1, that means multiple cases of the switch map to 1 + // value in the phi, and that phi value is not the switch condition. Thus, + // this transform would not make sense (the phi would be invalid because + // a phi can't have different incoming values from the same block). + int SwitchBBIdx = Phi->getBasicBlockIndex(SwitchBlock); + if (Phi->getIncomingValue(SwitchBBIdx) == CaseValue && + count(Phi->blocks(), SwitchBlock) == 1) { + Phi->setIncomingValue(SwitchBBIdx, SI->getCondition()); + Changed = true; + } + } + + // Collect phi nodes that are indirectly using this switch's case constants. int PhiIdx; if (auto *Phi = FindPHIForConditionForwarding(CaseValue, CaseDest, &PhiIdx)) ForwardingNodes[Phi].push_back(PhiIdx); } - bool Changed = false; for (auto &ForwardingNode : ForwardingNodes) { PHINode *Phi = ForwardingNode.first; SmallVectorImpl<int> &Indexes = ForwardingNode.second; |

