[llvm] [NewGVN][1/3] Load coercion between load and store (PR #68659)

Arthur Eubanks via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 24 15:38:36 PDT 2023


================
@@ -3821,6 +3998,206 @@ Value *NewGVN::findPHIOfOpsLeader(const Expression *E,
   return nullptr;
 }
 
+// Update MemorySSA for the newly emitted load instruction.
+void NewGVN::updateMemorySSA(Instruction *LoadToOptimize,
+                             Instruction *NewLoad) {
+  MemorySSAUpdater MemSSAUpdater(MSSA);
+  MemoryAccess *DefiningAccess = MSSA->getLiveOnEntryDef();
+  MemoryAccess *NewAccess = MemSSAUpdater.createMemoryAccessInBB(
+      NewLoad, DefiningAccess, NewLoad->getParent(),
+      MemorySSA::BeforeTerminator);
+  if (auto *NewDef = dyn_cast<MemoryDef>(NewAccess))
+    MemSSAUpdater.insertDef(NewDef, /*RenameUses=*/true);
+  else
+    MemSSAUpdater.insertUse(cast<MemoryUse>(NewAccess),
+                            /*RenameUses=*/true);
+}
+
+// Extract the correct value from the depending instruction.
+Value *NewGVN::getExtractedValue(LoadInst *LI, Instruction *DepI) {
+
+  Type *LoadTy = LI->getType();
+  Value *NewValue = nullptr;
+  Instruction *InsertPtr = nullptr;
+  // Emit the instructions that extract the coerced value from the depending
+  // instruction.
+  if (auto *Store = dyn_cast<StoreInst>(DepI)) {
+    int Offset = analyzeLoadFromClobberingStore(LoadTy, LI->getPointerOperand(),
+                                                Store, DL);
+    InsertPtr = Store->getNextNode();
+    NewValue = getValueForLoad(Store->getValueOperand(), Offset, LoadTy,
+                               InsertPtr, DL);
+  } else if (LoadInst *Load = dyn_cast<LoadInst>(DepI)) {
+    int Offset = analyzeLoadFromClobberingLoad(LoadTy, LI->getPointerOperand(),
+                                               Load, DL);
+    InsertPtr = Load->getNextNode();
+    NewValue = getValueForLoad(Load, Offset, LoadTy, InsertPtr, DL);
+  }
+
+  // Get the newly generated instructions and add them to NewLoadsInLoadCoercion
+  // and NewlyGeneratedInsns.
+  if (!isa<Constant>(NewValue) && !isa<Argument>(NewValue))
+    for (Instruction *CurInsn = DepI->getNextNode(); CurInsn != InsertPtr;
+         CurInsn = CurInsn->getNextNode()) {
+      if (LoadInst *NewLI = dyn_cast<LoadInst>(CurInsn)) {
+        updateMemorySSA(LI, NewLI);
+        NewLoadsInLoadCoercion.push_back(LI);
+      }
+      NewlyGeneratedInsns.push_back(CurInsn);
+    }
+
+  return NewValue;
+}
+
+void NewGVN::updateUsesAfterLoadCoercionImpl(
+    LoadInst *LI, SmallVectorImpl<Instruction *> &LIUses) {
+  // Run value numbering for the users of the candidate load instruction.
+  while (!LIUses.empty()) {
+    Instruction *I = LIUses.front();
+    assert(I != LI &&
+           "Vanity check that we do not process the optimized load.\n");
+    LIUses.erase(&*(LIUses.begin()));
+    if (InstructionsToErase.count(I))
+      continue;
+    CongruenceClass *OrigClass = ValueToClass.lookup(I);
+    valueNumberInstruction(I);
+    updateProcessedCount(I);
+    CongruenceClass *NewClass = ValueToClass.lookup(I);
+    if (OrigClass != NewClass) {
+      for (auto *User : I->users()) {
+        auto *UserI = cast<Instruction>(User);
+        LIUses.push_back(UserI);
+      }
+      if (auto *NewLI = dyn_cast<LoadInst>(I))
+        if (MemoryAccess *MA = getMemoryAccess(NewLI))
+          for (auto *MAU : MA->users()) {
+            Instruction *MAUInst = cast<Instruction>(MAU);
+            LIUses.push_back(MAUInst);
+          }
+      auto It = PredicateToUsers.find(I);
+      if (It != PredicateToUsers.end())
+        for (auto *PredI : PredicateToUsers[I]) {
+          LIUses.push_back(PredI);
+        }
+    }
+  }
+}
+
+void NewGVN::updateUsesAfterLoadCoercion(LoadInst *LI, Value *NewValue) {
+  SmallVector<Instruction *, 2> LIUses;
+  if (!NewValue) {
+    Value *LoadAddressLeader = lookupOperandLeader(LI->getPointerOperand());
+    MemoryAccess *OriginalAccess = getMemoryAccess(LI);
+    MemoryAccess *DefiningAccess =
+        MSSAWalker->getClobberingMemoryAccess(OriginalAccess);
+    const Expression *Symbolized = createLoadExpAndUpdateMemUses(
+        LI, LoadAddressLeader, OriginalAccess, DefiningAccess);
+    performCongruenceFinding(LI, Symbolized);
+    for (Use &U : LI->uses())
+      LIUses.push_back(cast<Instruction>(U.getUser()));
+    updateUsesAfterLoadCoercionImpl(LI, LIUses);
+  } else {
+    CongruenceClass *LIClass = ValueToClass.lookup(LI);
+    InstructionsToErase.insert(LI);
+    LI->replaceAllUsesWith(NewValue);
+    // Collect the instructions for which we have to run value numbering.
+    // These are all the instructions that are in the same congruence class as
+    // LI and all the newly generated instructions.
+    for (auto *Member : *LIClass) {
+      auto *I = cast<Instruction>(Member);
+      if (LI == I)
+        continue;
+      LIUses.push_back(I);
+    }
+    for (Instruction *I : NewlyGeneratedInsns) {
+      TOPClass->insert(I);
+      ValueToClass[I] = TOPClass;
+      LIUses.push_back(I);
+    }
+
+    updateUsesAfterLoadCoercionImpl(LI, LIUses);
+
+    if (isa<PHINode>(NewValue)) {
+      NewValue->takeName(LI);
+    }
+    if (Instruction *I = dyn_cast<Instruction>(NewValue))
+      I->setDebugLoc(LI->getDebugLoc());
+    LLVM_DEBUG(dbgs() << "Load coersion: The load " << *LI
+                      << " was eliminated and its uses were replaced by "
+                      << *NewValue << "\n");
+  }
+  LIUses.clear();
+  NewlyGeneratedInsns.clear();
+}
+
+// Iterate over the load instructions of LoadCoercion map and replace them with
+// the right sequence of instructions.
+bool NewGVN::implementLoadCoercion() {
+  bool AnythingReplaced = false;
----------------
aeubanks wrote:

nit: `Changed` or `MadeChange` are more idiomatic

https://github.com/llvm/llvm-project/pull/68659


More information about the llvm-commits mailing list