[llvm] [GVN] Permit load PRE to happen in more cases (PR #79324)
Paul Walker via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 19 10:30:07 PST 2024
================
@@ -1143,34 +1143,100 @@ static void reportMayClobberedLoad(LoadInst *Load, MemDepResult DepInfo,
ORE->emit(R);
}
+static bool findDominatingValueInBlock(const MemoryLocation &Loc, Type *LoadTy,
+ Instruction *From,
+ BatchAAResults *BatchAA,
+ uint32_t &NumVisitedInsts,
+ Value *&FoundVal) {
+ for (auto *Inst = From; Inst != nullptr;
+ Inst = Inst->getPrevNonDebugInstruction()) {
+ // Stop the search if limit is reached.
+ if (++NumVisitedInsts > MaxNumVisitedInsts) {
+ return false;
+ }
+ if (isModSet(BatchAA->getModRefInfo(Inst, Loc))) {
+ return false;
+ }
+ if (auto *LI = dyn_cast<LoadInst>(Inst))
+ if (LI->getPointerOperand() == Loc.Ptr && LI->getType() == LoadTy) {
+ FoundVal = LI;
+ return true;
+ }
+ }
+ FoundVal = nullptr;
+ return true;
+}
+
// Find non-clobbered value for Loc memory location in extended basic block
// (chain of basic blocks with single predecessors) starting From instruction.
static Value *findDominatingValue(const MemoryLocation &Loc, Type *LoadTy,
Instruction *From, AAResults *AA) {
- uint32_t NumVisitedInsts = 0;
BasicBlock *FromBB = From->getParent();
+ uint32_t NumVisitedInsts = 0;
BatchAAResults BatchAA(*AA);
- for (BasicBlock *BB = FromBB; BB; BB = BB->getSinglePredecessor())
- for (auto *Inst = BB == FromBB ? From : BB->getTerminator();
- Inst != nullptr; Inst = Inst->getPrevNonDebugInstruction()) {
- // Stop the search if limit is reached.
- if (++NumVisitedInsts > MaxNumVisitedInsts)
- return nullptr;
- if (isModSet(BatchAA.getModRefInfo(Inst, Loc)))
- return nullptr;
- if (auto *LI = dyn_cast<LoadInst>(Inst))
- if (LI->getPointerOperand() == Loc.Ptr && LI->getType() == LoadTy)
- return LI;
- }
+ for (BasicBlock *BB = FromBB; BB; BB = BB->getSinglePredecessor()) {
+ Value *FoundVal;
+ if (!findDominatingValueInBlock(Loc, LoadTy,
+ BB == FromBB ? From : BB->getTerminator(),
+ &BatchAA, NumVisitedInsts, FoundVal))
+ return nullptr;
+ else if (FoundVal)
+ return FoundVal;
+ }
return nullptr;
}
std::optional<AvailableValue>
-GVNPass::AnalyzeLoadAvailability(LoadInst *Load, MemDepResult DepInfo,
- Value *Address) {
+GVNPass::AnalyzeLoadAvailability(LoadInst *Load, BasicBlock *DepBB,
+ MemDepResult DepInfo, Value *Address) {
assert(Load->isUnordered() && "rules below are incorrect for ordered access");
- assert(DepInfo.isLocal() && "expected a local dependence");
+ // Even for an unknown memory dependence we can still walk backwards through
+ // any predecessor blocks to see if we can find an available load for the
+ // address. This load needs to be the same for every possible predecessor.
+ // Here is one such example:
+ // LoadBB
+ // | \
+ // | MidBB
+ // | /
+ // DepBB
+ // This is similar to what we already do for a SelectInst further down.
+ // There must be no instructions between the load and the end of DepBB
+ // that could clobber the load.
+ if (!DepInfo.isLocal()) {
+ if (!Address || pred_empty(DepBB))
----------------
paulwalker-arm wrote:
What if `DepBB` is null?
https://github.com/llvm/llvm-project/pull/79324
More information about the llvm-commits
mailing list