Author: Florian Hahn Date: 2022-02-15T15:10:07Z New Revision: 6029d33b407191aa1341ca0ce855523e7c2d6409
URL: https://github.com/llvm/llvm-project/commit/6029d33b407191aa1341ca0ce855523e7c2d6409 DIFF: https://github.com/llvm/llvm-project/commit/6029d33b407191aa1341ca0ce855523e7c2d6409.diff LOG: Exit reads. Added: Modified: llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp Removed: ################################################################################ diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp index 8739ddce91606..d75f6f2d97e38 100644 --- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -100,9 +100,6 @@ STATISTIC(NumFastStores, "Number of stores deleted"); STATISTIC(NumFastOther, "Number of other instrs removed"); STATISTIC(NumCompletePartials, "Number of stores dead by later partials"); STATISTIC(NumModifiedStores, "Number of stores modified"); -STATISTIC(NumCFGChecks, "Number of stores modified"); -STATISTIC(NumCFGTries, "Number of stores modified"); -STATISTIC(NumCFGSuccess, "Number of stores modified"); STATISTIC(NumGetDomMemoryDefPassed, "Number of times a valid candidate is returned from getDomMemoryDef"); STATISTIC(NumDomMemDefChecks, @@ -763,6 +760,9 @@ struct DSEState { DenseMap<const Value *, bool> InvisibleToCallerAfterRet; // Keep track of blocks with throwing instructions not modeled in MemorySSA. SmallPtrSet<BasicBlock *, 16> ThrowingBlocks; + + SmallPtrSet<Instruction *, 4> ExitReads; + // Post-order numbers for each basic block. Used to figure out if memory // accesses are executed before another access. DenseMap<BasicBlock *, unsigned> PostOrderNumbers; @@ -771,6 +771,8 @@ struct DSEState { /// basic block. MapVector<BasicBlock *, InstOverlapIntervalsTy> IOLs; + MemorySSAUpdater Updater; + // Class contains self-reference, make sure it's not copied/moved. DSEState(const DSEState &) = delete; DSEState &operator=(const DSEState &) = delete; @@ -779,7 +781,8 @@ struct DSEState { PostDominatorTree &PDT, const TargetLibraryInfo &TLI, const LoopInfo &LI) : F(F), AA(AA), EI(DT, LI), BatchAA(AA, &EI), MSSA(MSSA), DT(DT), - PDT(PDT), TLI(TLI), DL(F.getParent()->getDataLayout()), LI(LI) { + PDT(PDT), TLI(TLI), DL(F.getParent()->getDataLayout()), LI(LI), + Updater(&MSSA) { // Collect blocks with throwing instructions not modeled in MemorySSA and // alloc-like objects. unsigned PO = 0; @@ -805,6 +808,23 @@ struct DSEState { // Collect whether there is any irreducible control flow in the function. ContainsIrreducibleLoops = mayContainIrreducibleControl(F, &LI); + + LLVMContext &Ctx = F.getContext(); + Type *I8Ty = IntegerType::get(Ctx, 8); + + GlobalVariable *Ext = nullptr; + for (BasicBlock *E : PDT.roots()) { + if (!Ext) + Ext = new GlobalVariable( + *F.getParent(), I8Ty, false, GlobalValue::ExternalLinkage, nullptr, + "", nullptr, GlobalValue::NotThreadLocal, None, true); + auto *Term = E->getTerminator(); + auto *LI = new LoadInst(I8Ty, Ext, "", Term); + auto *MemUse = cast<MemoryUse>( + Updater.createMemoryAccessInBB(LI, nullptr, E, MemorySSA::End)); + Updater.insertUse(MemUse); + ExitReads.insert(LI); + } } /// Return 'OW_Complete' if a store to the 'KillingLoc' location (by \p @@ -1150,7 +1170,10 @@ struct DSEState { if (auto *CB = dyn_cast<CallBase>(UseInst)) if (CB->onlyAccessesInaccessibleMemory()) return false; - + auto *LI = dyn_cast<LoadInst>(UseInst); + if (LI && ExitReads.count(LI)) { + return !isInvisibleToCallerAfterRet(getUnderlyingObject(DefLoc.Ptr)); + } return isRefSet(BatchAA.getModRefInfo(UseInst, DefLoc)); } @@ -1289,6 +1312,7 @@ struct DSEState { if (any_of(Current->uses(), [this, &KillingLoc, StartAccess](Use &U) { if (auto *UseOrDef = dyn_cast<MemoryUseOrDef>(U.getUser())) return !MSSA.dominates(StartAccess, UseOrDef) && + !ExitReads.count(UseOrDef->getMemoryInst()) && isReadClobber(KillingLoc, UseOrDef->getMemoryInst()); return false; })) { @@ -1490,69 +1514,6 @@ struct DSEState { } } - // For accesses to locations visible after the function returns, make sure - // that the location is dead (=overwritten) along all paths from - // MaybeDeadAccess to the exit. - if (!isInvisibleToCallerAfterRet(KillingUndObj)) { - SmallPtrSet<BasicBlock *, 16> KillingBlocks; - for (Instruction *KD : KillingDefs) - KillingBlocks.insert(KD->getParent()); - assert(!KillingBlocks.empty() && - "Expected at least a single killing block"); - - // Find the common post-dominator of all killing blocks. - BasicBlock *CommonPred = *KillingBlocks.begin(); - for (BasicBlock *BB : llvm::drop_begin(KillingBlocks)) { - if (!CommonPred) - break; - CommonPred = PDT.findNearestCommonDominator(CommonPred, BB); - } - - // If the common post-dominator does not post-dominate MaybeDeadAccess, - // there is a path from MaybeDeadAccess to an exit not going through a - // killing block. - if (!PDT.dominates(CommonPred, MaybeDeadAccess->getBlock())) - return None; - - // If CommonPred itself is in the set of killing blocks, we're done. - if (KillingBlocks.count(CommonPred)) - return {MaybeDeadAccess}; - - SetVector<BasicBlock *> WorkList; - - // If CommonPred is null, there are multiple exits from the function. - // They all have to be added to the worklist. - if (CommonPred) - WorkList.insert(CommonPred); - else - for (BasicBlock *R : PDT.roots()) - WorkList.insert(R); - - NumCFGTries++; - // Check if all paths starting from an exit node go through one of the - // killing blocks before reaching MaybeDeadAccess. - for (unsigned I = 0; I < WorkList.size(); I++) { - NumCFGChecks++; - BasicBlock *Current = WorkList[I]; - if (KillingBlocks.count(Current)) - continue; - if (Current == MaybeDeadAccess->getBlock()) - return None; - - // MaybeDeadAccess is reachable from the entry, so we don't have to - // explore unreachable blocks further. - if (!DT.isReachableFromEntry(Current)) - continue; - - for (BasicBlock *Pred : predecessors(Current)) - WorkList.insert(Pred); - - if (WorkList.size() >= MemorySSAPathCheckLimit) - return None; - } - NumCFGSuccess++; - } - // No aliasing MemoryUses of MaybeDeadAccess found, MaybeDeadAccess is // potentially dead. return {MaybeDeadAccess}; @@ -1560,7 +1521,6 @@ struct DSEState { // Delete dead memory defs void deleteDeadInstruction(Instruction *SI) { - MemorySSAUpdater Updater(&MSSA); SmallVector<Instruction *, 32> NowDeadInsts; NowDeadInsts.push_back(SI); --NumFastOther; @@ -1744,7 +1704,6 @@ struct DSEState { Malloc->getArgOperand(0), IRB, TLI); if (!Calloc) return false; - MemorySSAUpdater Updater(&MSSA); auto *LastDef = cast<MemoryDef>(Updater.getMemorySSA()->getMemoryAccess(Malloc)); auto *NewAccess = @@ -2087,6 +2046,17 @@ static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA, MadeChange |= State.eliminateRedundantStoresOfExistingValues(); MadeChange |= State.eliminateDeadWritesAtEndOfFunction(); + + GlobalVariable *Ext = nullptr; + for (BasicBlock *E : PDT.roots()) { + auto *LI = cast<LoadInst>(E->getTerminator()->getPrevNode()); + Ext = cast<GlobalVariable>(LI->getPointerOperand()); + State.Updater.removeMemoryAccess(LI); + LI->eraseFromParent(); + } + if (Ext) + Ext->eraseFromParent(); + return MadeChange; } } // end anonymous namespace _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits