@@ -383,12 +383,12 @@ enum OverwriteResult {
383383// / write to the same underlying object. In that case, use isPartialOverwrite to
384384// / check if \p Later partially overwrites \p Earlier. Returns 'OW_Unknown' if
385385// / nothing can be determined.
386- static OverwriteResult isOverwrite ( const MemoryLocation &Later,
387- const MemoryLocation &Earlier,
388- const DataLayout &DL ,
389- const TargetLibraryInfo &TLI,
390- int64_t &EarlierOff, int64_t &LaterOff,
391- AliasAnalysis &AA, const Function *F) {
386+ template < typename AATy>
387+ static OverwriteResult
388+ isOverwrite ( const MemoryLocation &Later, const MemoryLocation &Earlier ,
389+ const DataLayout &DL, const TargetLibraryInfo &TLI,
390+ int64_t &EarlierOff, int64_t &LaterOff, AATy &AA ,
391+ const Function *F) {
392392 // FIXME: Vet that this works for size upper-bounds. Seems unlikely that we'll
393393 // get imprecise values here, though (except for unknown sizes).
394394 if (!Later.Size .isPrecise () || !Earlier.Size .isPrecise ())
@@ -643,11 +643,10 @@ static bool isPossibleSelfRead(Instruction *Inst,
643643// / modified between the first and the second instruction.
644644// / Precondition: Second instruction must be dominated by the first
645645// / instruction.
646- static bool memoryIsNotModifiedBetween (Instruction *FirstI,
647- Instruction *SecondI,
648- AliasAnalysis *AA,
649- const DataLayout &DL,
650- DominatorTree *DT) {
646+ template <typename AATy>
647+ static bool
648+ memoryIsNotModifiedBetween (Instruction *FirstI, Instruction *SecondI, AATy &AA,
649+ const DataLayout &DL, DominatorTree *DT) {
651650 // Do a backwards scan through the CFG from SecondI to FirstI. Look for
652651 // instructions which can modify the memory location accessed by SecondI.
653652 //
@@ -696,7 +695,7 @@ static bool memoryIsNotModifiedBetween(Instruction *FirstI,
696695 for (; BI != EI; ++BI) {
697696 Instruction *I = &*BI;
698697 if (I->mayWriteToMemory () && I != SecondI)
699- if (isModSet (AA-> getModRefInfo (I, MemLoc.getWithNewPtr (Ptr))))
698+ if (isModSet (AA. getModRefInfo (I, MemLoc.getWithNewPtr (Ptr))))
700699 return false ;
701700 }
702701 if (B != FirstBB) {
@@ -1132,7 +1131,7 @@ static bool eliminateNoopStore(Instruction *Inst, BasicBlock::iterator &BBI,
11321131 if (LoadInst *DepLoad = dyn_cast<LoadInst>(SI->getValueOperand ())) {
11331132 if (SI->getPointerOperand () == DepLoad->getPointerOperand () &&
11341133 isRemovable (SI) &&
1135- memoryIsNotModifiedBetween (DepLoad, SI, AA, DL, DT)) {
1134+ memoryIsNotModifiedBetween (DepLoad, SI, * AA, DL, DT)) {
11361135
11371136 LLVM_DEBUG (
11381137 dbgs () << " DSE: Remove Store Of Load from same pointer:\n LOAD: "
@@ -1151,7 +1150,7 @@ static bool eliminateNoopStore(Instruction *Inst, BasicBlock::iterator &BBI,
11511150 dyn_cast<Instruction>(getUnderlyingObject (SI->getPointerOperand ()));
11521151
11531152 if (UnderlyingPointer && isCallocLikeFn (UnderlyingPointer, TLI) &&
1154- memoryIsNotModifiedBetween (UnderlyingPointer, SI, AA, DL, DT)) {
1153+ memoryIsNotModifiedBetween (UnderlyingPointer, SI, * AA, DL, DT)) {
11551154 LLVM_DEBUG (
11561155 dbgs () << " DSE: Remove null store to the calloc'ed object:\n DEAD: "
11571156 << *Inst << " \n OBJECT: " << *UnderlyingPointer << ' \n ' );
@@ -1164,11 +1163,10 @@ static bool eliminateNoopStore(Instruction *Inst, BasicBlock::iterator &BBI,
11641163 return false ;
11651164}
11661165
1167- static Constant *
1168- tryToMergePartialOverlappingStores (StoreInst *Earlier, StoreInst *Later,
1169- int64_t InstWriteOffset,
1170- int64_t DepWriteOffset, const DataLayout &DL,
1171- AliasAnalysis *AA, DominatorTree *DT) {
1166+ template <typename AATy>
1167+ static Constant *tryToMergePartialOverlappingStores (
1168+ StoreInst *Earlier, StoreInst *Later, int64_t InstWriteOffset,
1169+ int64_t DepWriteOffset, const DataLayout &DL, AATy &AA, DominatorTree *DT) {
11721170
11731171 if (Earlier && isa<ConstantInt>(Earlier->getValueOperand ()) &&
11741172 DL.typeSizeEqualsStoreSize (Earlier->getValueOperand ()->getType ()) &&
@@ -1361,7 +1359,7 @@ static bool eliminateDeadStores(BasicBlock &BB, AliasAnalysis *AA,
13611359 auto *Earlier = dyn_cast<StoreInst>(DepWrite);
13621360 auto *Later = dyn_cast<StoreInst>(Inst);
13631361 if (Constant *C = tryToMergePartialOverlappingStores (
1364- Earlier, Later, InstWriteOffset, DepWriteOffset, DL, AA,
1362+ Earlier, Later, InstWriteOffset, DepWriteOffset, DL, * AA,
13651363 DT)) {
13661364 auto *SI = new StoreInst (
13671365 C, Earlier->getPointerOperand (), false , Earlier->getAlign (),
@@ -1507,6 +1505,16 @@ bool canSkipDef(MemoryDef *D, bool DefVisibleToCaller) {
15071505struct DSEState {
15081506 Function &F;
15091507 AliasAnalysis &AA;
1508+
1509+ // / The single BatchAA instance that is used to cache AA queries. It will
1510+ // / not be invalidated over the whole run. This is safe, because:
1511+ // / 1. Only memory writes are removed, so the alias cache for memory
1512+ // / locations remains valid.
1513+ // / 2. No new instructions are added (only instructions removed), so cached
1514+ // / information for a deleted value cannot be accessed by a re-used new
1515+ // / value pointer.
1516+ BatchAAResults BatchAA;
1517+
15101518 MemorySSA &MSSA;
15111519 DominatorTree &DT;
15121520 PostDominatorTree &PDT;
@@ -1534,7 +1542,7 @@ struct DSEState {
15341542
15351543 DSEState (Function &F, AliasAnalysis &AA, MemorySSA &MSSA, DominatorTree &DT,
15361544 PostDominatorTree &PDT, const TargetLibraryInfo &TLI)
1537- : F(F), AA(AA), MSSA(MSSA), DT(DT), PDT(PDT), TLI(TLI) {}
1545+ : F(F), AA(AA), BatchAA(AA), MSSA(MSSA), DT(DT), PDT(PDT), TLI(TLI) {}
15381546
15391547 static DSEState get (Function &F, AliasAnalysis &AA, MemorySSA &MSSA,
15401548 DominatorTree &DT, PostDominatorTree &PDT,
@@ -1623,7 +1631,7 @@ struct DSEState {
16231631 }
16241632
16251633 // / Returns true if \p Use completely overwrites \p DefLoc.
1626- bool isCompleteOverwrite (MemoryLocation DefLoc, Instruction *UseInst) const {
1634+ bool isCompleteOverwrite (MemoryLocation DefLoc, Instruction *UseInst) {
16271635 // UseInst has a MemoryDef associated in MemorySSA. It's possible for a
16281636 // MemoryDef to not write to memory, e.g. a volatile load is modeled as a
16291637 // MemoryDef.
@@ -1638,7 +1646,7 @@ struct DSEState {
16381646 auto CC = getLocForWriteEx (UseInst);
16391647 const DataLayout &DL = F.getParent ()->getDataLayout ();
16401648 return CC && isOverwrite (*CC, DefLoc, DL, TLI, DepWriteOffset,
1641- InstWriteOffset, AA , &F) == OW_Complete;
1649+ InstWriteOffset, BatchAA , &F) == OW_Complete;
16421650 }
16431651
16441652 // / Returns true if \p Def is not read before returning from the function.
@@ -1717,7 +1725,7 @@ struct DSEState {
17171725
17181726 // / Returns true if \p MaybeTerm is a memory terminator for the same
17191727 // / underlying object as \p DefLoc.
1720- bool isMemTerminator (MemoryLocation DefLoc, Instruction *MaybeTerm) const {
1728+ bool isMemTerminator (MemoryLocation DefLoc, Instruction *MaybeTerm) {
17211729 Optional<std::pair<MemoryLocation, bool >> MaybeTermLoc =
17221730 getLocForTerminator (MaybeTerm);
17231731
@@ -1730,19 +1738,19 @@ struct DSEState {
17301738 DataLayout DL = MaybeTerm->getParent ()->getModule ()->getDataLayout ();
17311739 DefLoc = MemoryLocation (getUnderlyingObject (DefLoc.Ptr ));
17321740 }
1733- return AA .isMustAlias (MaybeTermLoc->first , DefLoc);
1741+ return BatchAA .isMustAlias (MaybeTermLoc->first , DefLoc);
17341742 }
17351743
17361744 // Returns true if \p Use may read from \p DefLoc.
1737- bool isReadClobber (MemoryLocation DefLoc, Instruction *UseInst) const {
1745+ bool isReadClobber (MemoryLocation DefLoc, Instruction *UseInst) {
17381746 if (!UseInst->mayReadFromMemory ())
17391747 return false ;
17401748
17411749 if (auto *CB = dyn_cast<CallBase>(UseInst))
17421750 if (CB->onlyAccessesInaccessibleMemory ())
17431751 return false ;
17441752
1745- ModRefInfo MR = AA .getModRefInfo (UseInst, DefLoc);
1753+ ModRefInfo MR = BatchAA .getModRefInfo (UseInst, DefLoc);
17461754 // If necessary, perform additional analysis.
17471755 if (isRefSet (MR))
17481756 MR = AA.callCapturesBefore (UseInst, DefLoc, &DT);
@@ -1758,7 +1766,7 @@ struct DSEState {
17581766 Optional<MemoryAccess *>
17591767 getDomMemoryDef (MemoryDef *KillingDef, MemoryAccess *Current,
17601768 MemoryLocation DefLoc, bool DefVisibleToCallerBeforeRet,
1761- bool DefVisibleToCallerAfterRet, unsigned &ScanLimit) const {
1769+ bool DefVisibleToCallerAfterRet, unsigned &ScanLimit) {
17621770 if (ScanLimit == 0 ) {
17631771 LLVM_DEBUG (dbgs () << " \n ... hit scan limit\n " );
17641772 return None;
@@ -2285,7 +2293,7 @@ bool eliminateDeadStoresMemorySSA(Function &F, AliasAnalysis &AA,
22852293 // Check if NI overwrites SI.
22862294 int64_t InstWriteOffset, DepWriteOffset;
22872295 OverwriteResult OR = isOverwrite (SILoc, NILoc, DL, TLI, DepWriteOffset,
2288- InstWriteOffset, State.AA , &F);
2296+ InstWriteOffset, State.BatchAA , &F);
22892297 if (OR == OW_MaybePartial) {
22902298 auto Iter = State.IOLs .insert (
22912299 std::make_pair<BasicBlock *, InstOverlapIntervalsTy>(
@@ -2303,8 +2311,8 @@ bool eliminateDeadStoresMemorySSA(Function &F, AliasAnalysis &AA,
23032311 // TODO: implement tryToMergeParialOverlappingStores using MemorySSA.
23042312 if (Earlier && Later && DT.dominates (Earlier, Later)) {
23052313 if (Constant *Merged = tryToMergePartialOverlappingStores (
2306- Earlier, Later, InstWriteOffset, DepWriteOffset, DL, &AA,
2307- &DT)) {
2314+ Earlier, Later, InstWriteOffset, DepWriteOffset, DL,
2315+ State. BatchAA , &DT)) {
23082316
23092317 // Update stored value of earlier store to merged constant.
23102318 Earlier->setOperand (0 , Merged);
0 commit comments