summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
diff options
context:
space:
mode:
authorJames Molloy <james.molloy@arm.com>2016-09-01 07:45:25 +0000
committerJames Molloy <james.molloy@arm.com>2016-09-01 07:45:25 +0000
commite656642295cb7730e9b7d511ffc0b2402add3df7 (patch)
treea84460eeeb1ab88fff20a3b5c002a196b5089592 /llvm/lib/Transforms/Utils/SimplifyCFG.cpp
parent2bbdeacf318bd24280d4943ce2311961febe17e3 (diff)
downloadbcm5719-llvm-e656642295cb7730e9b7d511ffc0b2402add3df7.tar.gz
bcm5719-llvm-e656642295cb7730e9b7d511ffc0b2402add3df7.zip
[SimplifyCFG] Improve FoldValueComparisonIntoPredecessors to handle more cases
A very important case is not handled here: multiple arcs to a single block with a PHI. Consider: a: %1 = icmp %b, 1 br %1, label %c, label %e c: %2 = icmp %b, 2 br %2, label %d, label %e d: br %e e: phi [0, %a], [1, %c], [2, %d] FoldValueComparisonIntoPredecessors will refuse to fold this, as it doesn't know how to deal with two arcs to a common destination with different PHI values. The answer is obvious - just split all conflicting arcs. llvm-svn: 280338
Diffstat (limited to 'llvm/lib/Transforms/Utils/SimplifyCFG.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/SimplifyCFG.cpp27
1 files changed, 21 insertions, 6 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index dc36a6e1f0b..d8f8851c72d 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -174,7 +174,9 @@ public:
/// Return true if it is safe to merge these two
/// terminator instructions together.
-static bool SafeToMergeTerminators(TerminatorInst *SI1, TerminatorInst *SI2) {
+static bool
+SafeToMergeTerminators(TerminatorInst *SI1, TerminatorInst *SI2,
+ SmallPtrSetImpl<BasicBlock *> *FailBlocks = nullptr) {
if (SI1 == SI2)
return false; // Can't merge with self!
@@ -183,18 +185,22 @@ static bool SafeToMergeTerminators(TerminatorInst *SI1, TerminatorInst *SI2) {
// conflicting incoming values from the two switch blocks.
BasicBlock *SI1BB = SI1->getParent();
BasicBlock *SI2BB = SI2->getParent();
- SmallPtrSet<BasicBlock *, 16> SI1Succs(succ_begin(SI1BB), succ_end(SI1BB));
+ SmallPtrSet<BasicBlock *, 16> SI1Succs(succ_begin(SI1BB), succ_end(SI1BB));
+ bool Fail = false;
for (BasicBlock *Succ : successors(SI2BB))
if (SI1Succs.count(Succ))
for (BasicBlock::iterator BBI = Succ->begin(); isa<PHINode>(BBI); ++BBI) {
PHINode *PN = cast<PHINode>(BBI);
if (PN->getIncomingValueForBlock(SI1BB) !=
- PN->getIncomingValueForBlock(SI2BB))
- return false;
+ PN->getIncomingValueForBlock(SI2BB)) {
+ if (FailBlocks)
+ FailBlocks->insert(Succ);
+ Fail = true;
+ }
}
- return true;
+ return !Fail;
}
/// Return true if it is safe and profitable to merge these two terminator
@@ -954,7 +960,16 @@ bool SimplifyCFGOpt::FoldValueComparisonIntoPredecessors(TerminatorInst *TI,
TerminatorInst *PTI = Pred->getTerminator();
Value *PCV = isValueEqualityComparison(PTI); // PredCondVal
- if (PCV == CV && SafeToMergeTerminators(TI, PTI)) {
+ if (PCV == CV && TI != PTI) {
+ SmallPtrSet<BasicBlock*, 4> FailBlocks;
+ if (!SafeToMergeTerminators(TI, PTI, &FailBlocks)) {
+ for (auto *Succ : FailBlocks) {
+ std::vector<BasicBlock*> Blocks = { TI->getParent() };
+ if (!SplitBlockPredecessors(Succ, Blocks, ".fold.split"))
+ return false;
+ }
+ }
+
// Figure out which 'cases' to copy from SI to PSI.
std::vector<ValueEqualityComparisonCase> BBCases;
BasicBlock *BBDefault = GetValueEqualityComparisonCases(TI, BBCases);
OpenPOWER on IntegriCloud