From 4bd8dfc4a6778ba9e119fb91035637f31ddab364 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Fri, 21 Aug 2020 09:13:59 +0100 Subject: [PATCH] [DSE,MemorySSA] Split off partial tracking from isOverwite. When traversing memory uses to look for aliasing reads/writes, we only care about complete overwrites. This patch splits off the partial overwrite tracking from isOverwrite This avoids some unnecessary work when checking for read/write clobbers with MemorySSA-DSE. isOverwrite, which skips the partial overwrite tracking. This gives a relatively small improvement http://llvm-compile-time-tracker.com/compare.php?from=ef2a2f77f87553a0a4a39f518eb9ac86b756bda6&to=658f3905dd96d3415f3782adc712c79fa59a4665&stat=instructions This is part of the patches to bring down compile-time to the level referenced in http://lists.llvm.org/pipermail/llvm-dev/2020-August/144417.html Reviewed By: asbirlea Differential Revision: https://reviews.llvm.org/D86280 --- .../Scalar/DeadStoreElimination.cpp | 67 ++++++++++++------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/lib/Transforms/Scalar/DeadStoreElimination.cpp b/lib/Transforms/Scalar/DeadStoreElimination.cpp index a29b6353f17..4504c1f0cb1 100644 --- a/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -371,27 +371,24 @@ enum OverwriteResult { OW_Complete, OW_End, OW_PartialEarlierWithFullLater, + OW_MaybePartial, OW_Unknown }; } // end anonymous namespace /// Return 'OW_Complete' if a store to the 'Later' location completely -/// overwrites a store to the 'Earlier' location, 'OW_End' if the end of the -/// 'Earlier' location is completely overwritten by 'Later', 'OW_Begin' if the -/// beginning of the 'Earlier' location is overwritten by 'Later'. -/// 'OW_PartialEarlierWithFullLater' means that an earlier (big) store was -/// overwritten by a latter (smaller) store which doesn't write outside the big -/// store's memory locations. Returns 'OW_Unknown' if nothing can be determined. +/// overwrites a store to the 'Earlier' location. Return OW_MaybePartial +/// if \p Later does not completely overwrite \p Earlier, but they both +/// write to the same underlying object. In that case, use isPartialOverwrite to +/// check if \p Later partially overwrites \p Earlier. Returns 'OW_Unknown' if +/// nothing can be determined. static OverwriteResult isOverwrite(const MemoryLocation &Later, const MemoryLocation &Earlier, const DataLayout &DL, const TargetLibraryInfo &TLI, int64_t &EarlierOff, int64_t &LaterOff, - Instruction *DepWrite, - InstOverlapIntervalsTy &IOL, - AliasAnalysis &AA, - const Function *F) { + AliasAnalysis &AA, const Function *F) { // FIXME: Vet that this works for size upper-bounds. Seems unlikely that we'll // get imprecise values here, though (except for unknown sizes). if (!Later.Size.isPrecise() || !Earlier.Size.isPrecise()) @@ -459,6 +456,27 @@ static OverwriteResult isOverwrite(const MemoryLocation &Later, uint64_t(EarlierOff - LaterOff) + EarlierSize <= LaterSize) return OW_Complete; + // Later may overwrite earlier completely with other partial writes. + return OW_MaybePartial; +} + +/// Return 'OW_Complete' if a store to the 'Later' location completely +/// overwrites a store to the 'Earlier' location, 'OW_End' if the end of the +/// 'Earlier' location is completely overwritten by 'Later', 'OW_Begin' if the +/// beginning of the 'Earlier' location is overwritten by 'Later'. +/// 'OW_PartialEarlierWithFullLater' means that an earlier (big) store was +/// overwritten by a latter (smaller) store which doesn't write outside the big +/// store's memory locations. Returns 'OW_Unknown' if nothing can be determined. +/// NOTE: This function must only be called if both \p Later and \p Earlier +/// write to the same underlying object with valid \p EarlierOff and \p +/// LaterOff. +static OverwriteResult isPartialOverwrite(const MemoryLocation &Later, + const MemoryLocation &Earlier, + int64_t EarlierOff, int64_t LaterOff, + Instruction *DepWrite, + InstOverlapIntervalsTy &IOL) { + const uint64_t LaterSize = Later.Size.getValue(); + const uint64_t EarlierSize = Earlier.Size.getValue(); // We may now overlap, although the overlap is not complete. There might also // be other incomplete overlaps, and together, they might cover the complete // earlier write. @@ -1308,8 +1326,11 @@ static bool eliminateDeadStores(BasicBlock &BB, AliasAnalysis *AA, !isPossibleSelfRead(Inst, Loc, DepWrite, *TLI, *AA)) { int64_t InstWriteOffset, DepWriteOffset; OverwriteResult OR = isOverwrite(Loc, DepLoc, DL, *TLI, DepWriteOffset, - InstWriteOffset, DepWrite, IOL, *AA, - BB.getParent()); + InstWriteOffset, *AA, BB.getParent()); + if (OR == OW_MaybePartial) + OR = isPartialOverwrite(Loc, DepLoc, DepWriteOffset, InstWriteOffset, + DepWrite, IOL); + if (OR == OW_Complete) { LLVM_DEBUG(dbgs() << "DSE: Remove Dead Store:\n DEAD: " << *DepWrite << "\n KILLER: " << *Inst << '\n'); @@ -1615,13 +1636,9 @@ struct DSEState { int64_t InstWriteOffset, DepWriteOffset; auto CC = getLocForWriteEx(UseInst); - InstOverlapIntervalsTy IOL; - const DataLayout &DL = F.getParent()->getDataLayout(); - - return CC && - isOverwrite(*CC, DefLoc, DL, TLI, DepWriteOffset, InstWriteOffset, - UseInst, IOL, AA, &F) == OW_Complete; + return CC && isOverwrite(*CC, DefLoc, DL, TLI, DepWriteOffset, + InstWriteOffset, AA, &F) == OW_Complete; } /// Returns true if \p Def is not read before returning from the function. @@ -2262,12 +2279,16 @@ bool eliminateDeadStoresMemorySSA(Function &F, AliasAnalysis &AA, } else { // Check if NI overwrites SI. int64_t InstWriteOffset, DepWriteOffset; - auto Iter = State.IOLs.insert( - std::make_pair( - NI->getParent(), InstOverlapIntervalsTy())); - auto &IOL = Iter.first->second; OverwriteResult OR = isOverwrite(SILoc, NILoc, DL, TLI, DepWriteOffset, - InstWriteOffset, NI, IOL, AA, &F); + InstWriteOffset, State.AA, &F); + if (OR == OW_MaybePartial) { + auto Iter = State.IOLs.insert( + std::make_pair( + NI->getParent(), InstOverlapIntervalsTy())); + auto &IOL = Iter.first->second; + OR = isPartialOverwrite(SILoc, NILoc, DepWriteOffset, InstWriteOffset, + NI, IOL); + } if (EnablePartialStoreMerging && OR == OW_PartialEarlierWithFullLater) { auto *Earlier = dyn_cast(NI);