forked from OSchip/llvm-project
[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
This commit is contained in:
parent
2bbdeacf31
commit
e656642295
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue