diff options
| author | Max Kazantsev <max.kazantsev@azul.com> | 2018-11-12 09:29:58 +0000 |
|---|---|---|
| committer | Max Kazantsev <max.kazantsev@azul.com> | 2018-11-12 09:29:58 +0000 |
| commit | 7d49a3a81698a2a9508084b6cb9a8daf5d617252 (patch) | |
| tree | c00a1eecc9e681c4e66ce52e000436118ed8d2ae /llvm/lib | |
| parent | cedcc73d932f7092842e0c80e1321f6ae6b0ee63 (diff) | |
| download | bcm5719-llvm-7d49a3a81698a2a9508084b6cb9a8daf5d617252.tar.gz bcm5719-llvm-7d49a3a81698a2a9508084b6cb9a8daf5d617252.zip | |
[LICM] Hoist guards from non-header blocks
This patch relaxes overconservative checks on whether or not we could write
memory before we execute an instruction. This allows us to hoist guards out of
loops even if they are not in the header block.
Differential Revision: https://reviews.llvm.org/D50891
Reviewed By: fedor.sergeev
llvm-svn: 346643
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(); } } |

