diff options
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Analysis/InstructionPrecedenceTracking.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/Analysis/MustExecute.cpp | 31 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Scalar/LICM.cpp | 14 |
3 files changed, 39 insertions, 11 deletions
diff --git a/llvm/lib/Analysis/InstructionPrecedenceTracking.cpp b/llvm/lib/Analysis/InstructionPrecedenceTracking.cpp index c667c282281..b98975b006a 100644 --- a/llvm/lib/Analysis/InstructionPrecedenceTracking.cpp +++ b/llvm/lib/Analysis/InstructionPrecedenceTracking.cpp @@ -142,3 +142,8 @@ bool ImplicitControlFlowTracking::isSpecialInstruction( } return true; } + +bool MemoryWriteTracking::isSpecialInstruction( + const Instruction *Insn) const { + return Insn->mayWriteToMemory(); +} diff --git a/llvm/lib/Analysis/MustExecute.cpp b/llvm/lib/Analysis/MustExecute.cpp index 23e012626e2..281b8f5ab98 100644 --- a/llvm/lib/Analysis/MustExecute.cpp +++ b/llvm/lib/Analysis/MustExecute.cpp @@ -72,6 +72,7 @@ bool ICFLoopSafetyInfo::anyBlockMayThrow() const { void ICFLoopSafetyInfo::computeLoopSafetyInfo(const Loop *CurLoop) { assert(CurLoop != nullptr && "CurLoop can't be null"); ICF.clear(); + MW.clear(); MayThrow = false; // Figure out the fact that at least one block may throw. for (auto &BB : CurLoop->blocks()) @@ -84,12 +85,14 @@ void ICFLoopSafetyInfo::computeLoopSafetyInfo(const Loop *CurLoop) { void ICFLoopSafetyInfo::insertInstructionTo(const BasicBlock *BB) { ICF.invalidateBlock(BB); + MW.invalidateBlock(BB); } void ICFLoopSafetyInfo::removeInstruction(const Instruction *Inst) { // TODO: So far we just conservatively drop cache, but maybe we can not do it // when Inst is not an ICF instruction. Follow-up on that. ICF.invalidateBlock(Inst->getParent()); + MW.invalidateBlock(Inst->getParent()); } void LoopSafetyInfo::computeBlockColors(const Loop *CurLoop) { @@ -256,6 +259,34 @@ bool ICFLoopSafetyInfo::isGuaranteedToExecute(const Instruction &Inst, allLoopPathsLeadToBlock(CurLoop, Inst.getParent(), DT); } +bool ICFLoopSafetyInfo::doesNotWriteMemoryBefore(const BasicBlock *BB, + const Loop *CurLoop) const { + assert(CurLoop->contains(BB) && "Should only be called for loop blocks!"); + + // Fast path: there are no instructions before header. + if (BB == CurLoop->getHeader()) + return true; + + // Collect all transitive predecessors of BB in the same loop. This set will + // be a subset of the blocks within the loop. + SmallPtrSet<const BasicBlock *, 4> Predecessors; + collectTransitivePredecessors(CurLoop, BB, Predecessors); + // Find if there any instruction in either predecessor that could write + // to memory. + for (auto *Pred : Predecessors) + if (MW.mayWriteToMemory(Pred)) + return false; + return true; +} + +bool ICFLoopSafetyInfo::doesNotWriteMemoryBefore(const Instruction &I, + const Loop *CurLoop) const { + auto *BB = I.getParent(); + assert(CurLoop->contains(BB) && "Should only be called for loop blocks!"); + return !MW.isDominatedByMemoryWriteFromSameBlock(&I) && + doesNotWriteMemoryBefore(BB, CurLoop); +} + namespace { struct MustExecutePrinter : public FunctionPass { diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp index e7402ea579b..e30c25da6b4 100644 --- a/llvm/lib/Transforms/Scalar/LICM.cpp +++ b/llvm/lib/Transforms/Scalar/LICM.cpp @@ -463,12 +463,6 @@ bool llvm::hoistRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI, if (inSubLoop(BB, CurLoop, LI)) continue; - // Keep track of whether the prefix instructions could have written memory. - // TODO: This may be done smarter if we keep track of all throwing and - // mem-writing operations in every block, e.g. using something similar to - // isGuaranteedToExecute. - bool IsMemoryNotModified = CurLoop->getHeader() == BB; - for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;) { Instruction &I = *II++; // Try constant folding this instruction. If all the operands are @@ -529,15 +523,13 @@ bool llvm::hoistRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI, if (((I.use_empty() && match(&I, m_Intrinsic<Intrinsic::invariant_start>())) || isGuard(&I)) && - IsMemoryNotModified && CurLoop->hasLoopInvariantOperands(&I) && - SafetyInfo->isGuaranteedToExecute(I, DT, CurLoop)) { + CurLoop->hasLoopInvariantOperands(&I) && + SafetyInfo->isGuaranteedToExecute(I, DT, CurLoop) && + SafetyInfo->doesNotWriteMemoryBefore(I, CurLoop)) { hoist(I, DT, CurLoop, SafetyInfo, ORE); Changed = true; continue; } - - if (IsMemoryNotModified) - IsMemoryNotModified = !I.mayWriteToMemory(); } } |

