summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Scalar
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Scalar')
-rw-r--r--llvm/lib/Transforms/Scalar/GVNHoist.cpp62
1 files changed, 34 insertions, 28 deletions
diff --git a/llvm/lib/Transforms/Scalar/GVNHoist.cpp b/llvm/lib/Transforms/Scalar/GVNHoist.cpp
index 8b2164c5071..92b7e35a17f 100644
--- a/llvm/lib/Transforms/Scalar/GVNHoist.cpp
+++ b/llvm/lib/Transforms/Scalar/GVNHoist.cpp
@@ -329,31 +329,36 @@ private:
return I1DFS < I2DFS;
}
- // Return true when there are users of Def in BB.
- bool hasMemoryUseOnPath(MemoryAccess *Def, const BasicBlock *BB,
- const Instruction *OldPt) {
- const BasicBlock *DefBB = Def->getBlock();
- const BasicBlock *OldBB = OldPt->getParent();
+ // Return true when there are memory uses of Def in BB.
+ bool hasMemoryUse(const Instruction *NewPt, MemoryDef *Def,
+ const BasicBlock *BB) {
+ const MemorySSA::AccessList *Acc = MSSA->getBlockAccesses(BB);
+ if (!Acc)
+ return false;
- for (User *U : Def->users())
- if (auto *MU = dyn_cast<MemoryUse>(U)) {
- // FIXME: MU->getBlock() does not get updated when we move the instruction.
- BasicBlock *UBB = MU->getMemoryInst()->getParent();
- // Only analyze uses in BB.
- if (BB != UBB)
- continue;
+ Instruction *OldPt = Def->getMemoryInst();
+ const BasicBlock *OldBB = OldPt->getParent();
+ const BasicBlock *NewBB = NewPt->getParent();
+ bool ReachedNewPt = false;
- // A use in the same block as the Def is on the path.
- if (UBB == DefBB) {
- assert(MSSA->locallyDominates(Def, MU) && "def not dominating use");
- return true;
- }
+ for (const MemoryAccess &MA : *Acc)
+ if (const MemoryUse *MU = dyn_cast<MemoryUse>(&MA)) {
+ Instruction *Insn = MU->getMemoryInst();
- if (UBB != OldBB)
- return true;
+ // Do not check whether MU aliases Def when MU occurs after OldPt.
+ if (BB == OldBB && firstInBB(OldPt, Insn))
+ break;
- // It is only harmful to hoist when the use is before OldPt.
- if (firstInBB(MU->getMemoryInst(), OldPt))
+ // Do not check whether MU aliases Def when MU occurs before NewPt.
+ if (BB == NewBB) {
+ if (!ReachedNewPt) {
+ if (firstInBB(Insn, NewPt))
+ continue;
+ ReachedNewPt = true;
+ }
+ }
+ if (instructionClobbersQuery(Def, MemoryLocation::get(Insn), Insn,
+ *AA))
return true;
}
@@ -361,17 +366,18 @@ private:
}
// Return true when there are exception handling or loads of memory Def
- // between OldPt and NewPt.
+ // between Def and NewPt. This function is only called for stores: Def is
+ // the MemoryDef of the store to be hoisted.
// Decrement by 1 NBBsOnAllPaths for each block between HoistPt and BB, and
// return true when the counter NBBsOnAllPaths reaces 0, except when it is
// initialized to -1 which is unlimited.
- bool hasEHOrLoadsOnPath(const Instruction *NewPt, const Instruction *OldPt,
- MemoryAccess *Def, int &NBBsOnAllPaths) {
+ bool hasEHOrLoadsOnPath(const Instruction *NewPt, MemoryDef *Def,
+ int &NBBsOnAllPaths) {
const BasicBlock *NewBB = NewPt->getParent();
- const BasicBlock *OldBB = OldPt->getParent();
+ const BasicBlock *OldBB = Def->getBlock();
assert(DT->dominates(NewBB, OldBB) && "invalid path");
- assert(DT->dominates(Def->getBlock(), NewBB) &&
+ assert(DT->dominates(Def->getDefiningAccess()->getBlock(), NewBB) &&
"def does not dominate new hoisting point");
// Walk all basic blocks reachable in depth-first iteration on the inverse
@@ -390,7 +396,7 @@ private:
return true;
// Check that we do not move a store past loads.
- if (hasMemoryUseOnPath(Def, *I, OldPt))
+ if (hasMemoryUse(NewPt, Def, *I))
return true;
// Stop walk once the limit is reached.
@@ -473,7 +479,7 @@ private:
// Check for unsafe hoistings due to side effects.
if (K == InsKind::Store) {
- if (hasEHOrLoadsOnPath(NewPt, OldPt, D, NBBsOnAllPaths))
+ if (hasEHOrLoadsOnPath(NewPt, dyn_cast<MemoryDef>(U), NBBsOnAllPaths))
return false;
} else if (hasEHOnPath(NewBB, OldBB, NBBsOnAllPaths))
return false;
OpenPOWER on IntegriCloud