[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