[llvm] [NewGVN][1/3] Load coercion between load and store (PR #68659)
Konstantina Mitropoulou via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 26 23:11:22 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;
----------------
kmitropoulou wrote:
Done :)
https://github.com/llvm/llvm-project/pull/68659
More information about the llvm-commits
mailing list