summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Analysis/InstructionPrecedenceTracking.cpp5
-rw-r--r--llvm/lib/Analysis/MustExecute.cpp31
-rw-r--r--llvm/lib/Transforms/Scalar/LICM.cpp14
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();
}
}
OpenPOWER on IntegriCloud