diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp --- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -87,6 +87,8 @@ STATISTIC(NumCFGChecks, "Number of stores modified"); STATISTIC(NumCFGTries, "Number of stores modified"); STATISTIC(NumCFGSuccess, "Number of stores modified"); +STATISTIC(NumDomMemDefChecks, + "Number iterations check for reads in getDomMemoryDef"); DEBUG_COUNTER(MemorySSACounter, "dse-memoryssa", "Controls which MemoryDefs are eliminated."); @@ -1543,6 +1545,18 @@ /// basic block. DenseMap IOLs; + struct CheckCache { + SmallPtrSet KnownNoReads; + SmallPtrSet KnownReads; + + bool isKnownNoRead(MemoryAccess *A) const { + return KnownNoReads.find(A) != KnownNoReads.end(); + } + bool isKnownRead(MemoryAccess *A) const { + return KnownReads.find(A) != KnownReads.end(); + } + }; + DSEState(Function &F, AliasAnalysis &AA, MemorySSA &MSSA, DominatorTree &DT, PostDominatorTree &PDT, const TargetLibraryInfo &TLI) : F(F), AA(AA), BatchAA(AA), MSSA(MSSA), DT(DT), PDT(PDT), TLI(TLI), @@ -1797,17 +1811,17 @@ // MemoryDef, return None. The returned value may not (completely) overwrite // \p DefLoc. Currently we bail out when we encounter an aliasing MemoryUse // (read). - Optional getDomMemoryDef(MemoryDef *KillingDef, - MemoryAccess *Current, - MemoryLocation DefLoc, - const Value *DefUO, - unsigned &ScanLimit) { + Optional + getDomMemoryDef(MemoryDef *KillingDef, MemoryAccess *Current, + MemoryLocation DefLoc, const Value *DefUO, CheckCache &Cache, + unsigned &ScanLimit) { if (ScanLimit == 0) { LLVM_DEBUG(dbgs() << "\n ... hit scan limit\n"); return None; } MemoryAccess *DomAccess; + MemoryAccess *StartAccess = Current; bool StepAgain; LLVM_DEBUG(dbgs() << " trying to get dominating access for " << *Current << "\n"); @@ -1847,10 +1861,13 @@ // they cover all paths from DomAccess to any function exit. SmallPtrSet KillingDefs; KillingDefs.insert(KillingDef->getMemoryInst()); + Instruction *DomMemInst = isa(DomAccess) + ? cast(DomAccess)->getMemoryInst() + : nullptr; LLVM_DEBUG({ dbgs() << " Checking for reads of " << *DomAccess; - if (isa(DomAccess)) - dbgs() << " (" << *cast(DomAccess)->getMemoryInst() << ")\n"; + if (DomMemInst) + dbgs() << " (" << *DomMemInst << ")\n"; else dbgs() << ")\n"; }); @@ -1862,6 +1879,11 @@ }; PushMemUses(DomAccess); + // Optimistically collect all accesses we for reads. If we do not find any + // read clobbers, add them to the cache. + SmallPtrSet KnownNoReads; + if (!DomMemInst || !DomMemInst->mayReadFromMemory()) + KnownNoReads.insert(DomAccess); // Check if DomDef may be read. for (unsigned I = 0; I < WorkList.size(); I++) { MemoryAccess *UseAccess = WorkList[I]; @@ -1873,6 +1895,20 @@ return None; } --ScanLimit; + NumDomMemDefChecks++; + + // Check if we already visited this access. + if (Cache.isKnownNoRead(UseAccess)) { + LLVM_DEBUG(dbgs() << " ... skip, discovered that " << *UseAccess + << " is safe earlier.\n"); + continue; + } + if (Cache.isKnownRead(UseAccess)) { + LLVM_DEBUG(dbgs() << " ... bail out, discovered that " << *UseAccess + << " is has a read-clobber earlier.\n"); + return None; + } + KnownNoReads.insert(UseAccess); if (isa(UseAccess)) { if (any_of(KillingDefs, [this, UseAccess](Instruction *KI) { @@ -1912,6 +1948,9 @@ // original MD. Stop walk. if (isReadClobber(DefLoc, UseInst)) { LLVM_DEBUG(dbgs() << " ... found read clobber\n"); + Cache.KnownReads.insert(UseAccess); + Cache.KnownReads.insert(StartAccess); + Cache.KnownReads.insert(DomAccess); return None; } @@ -2028,6 +2067,7 @@ return None; } + Cache.KnownNoReads.insert(KnownNoReads.begin(), KnownNoReads.end()); // No aliasing MemoryUses of DomAccess found, DomAccess is potentially dead. return {DomAccess}; } @@ -2235,6 +2275,7 @@ ToCheck.insert(KillingDef->getDefiningAccess()); //State.PointerMayBeCapturedBeforeCache.clear(); + DSEState::CheckCache Cache; // Check if MemoryAccesses in the worklist are killed by KillingDef. for (unsigned I = 0; I < ToCheck.size(); I++) { Current = ToCheck[I]; @@ -2242,7 +2283,7 @@ continue; Optional Next = State.getDomMemoryDef( - KillingDef, Current, SILoc, SILocUnd, ScanLimit); + KillingDef, Current, SILoc, SILocUnd, Cache, ScanLimit); if (!Next) { LLVM_DEBUG(dbgs() << " finished walk\n");