diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp index 1cd28944350..c5d0a18c387 100644 --- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp +++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp @@ -1929,7 +1929,7 @@ class LSRInstance { SmallSetVector<Type *, 4> Types; /// The list of interesting uses. - SmallVector<LSRUse, 16> Uses; + mutable SmallVector<LSRUse, 16> Uses; /// Track which uses use which register candidates. RegUseTracker RegUses; @@ -5290,6 +5290,7 @@ void LSRInstance::RewriteForPHI( DenseMap<BasicBlock *, Value *> Inserted; for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) if (PN->getIncomingValue(i) == LF.OperandValToReplace) { + bool needUpdateFixups = false; BasicBlock *BB = PN->getIncomingBlock(i); // If this is a critical edge, split the edge so that we do not insert @@ -5328,6 +5329,8 @@ void LSRInstance::RewriteForPHI( e = PN->getNumIncomingValues(); BB = NewBB; i = PN->getBasicBlockIndex(BB); + + needUpdateFixups = true; } } } @@ -5352,6 +5355,44 @@ void LSRInstance::RewriteForPHI( PN->setIncomingValue(i, FullV); Pair.first->second = FullV; } + + // If LSR split critical edge and phi node has other pending + // fixup operands, we need to update those pending fixups. Otherwise + // formulae will not be implemented completely and some instructions + // will not be eliminated. + if (needUpdateFixups) { + for (size_t LUIdx = 0, NumUses = Uses.size(); LUIdx != NumUses; ++LUIdx) + for (LSRFixup &Fixup : Uses[LUIdx].Fixups) + // If fixup is supposed to rewrite some operand in the phi + // that was just updated, it may be already moved to + // another phi node. Such fixup requires update. + if (Fixup.UserInst == PN) { + // Check if the operand we try to replace still exists in the + // original phi. + bool foundInOriginalPHI = false; + for (const auto &val : PN->incoming_values()) + if (val == Fixup.OperandValToReplace) { + foundInOriginalPHI = true; + break; + } + + // If fixup operand found in original PHI - nothing to do. + if (foundInOriginalPHI) + continue; + + // Otherwise it might be moved to another PHI and requires update. + // If fixup operand not found in any of the incoming blocks that + // means we have already rewritten it - nothing to do. + for (const auto &Block : PN->blocks()) + for (BasicBlock::iterator I = Block->begin(); isa<PHINode>(I); + ++I) { + PHINode *NewPN = cast<PHINode>(I); + for (const auto &val : NewPN->incoming_values()) + if (val == Fixup.OperandValToReplace) + Fixup.UserInst = NewPN; + } + } + } } } |