Skip to content

Commit

Permalink
[MemorySSA] Don't optimize uses during construction
Browse files Browse the repository at this point in the history
This changes MemorySSA to be constructed in unoptimized form.
MemorySSA::ensureOptimizedUses() can be called to optimize all
uses (once). This should be done by passes where having optimized
uses is beneficial, either because we're going to query all uses
anyway, or because we're doing def-use walks.

This should help reduce the compile-time impact of MemorySSA for
some use cases (the reason why I started looking into this is
D117926), which can avoid optimizing all uses upfront, and instead
only optimize those that are actually queried.

Actually, we have an existing use-case for this, which is EarlyCSE.
Disabling eager use optimization there gives a significant
compile-time improvement, because EarlyCSE will generally only query
clobbers for a subset of all uses (this change is not included in
this patch).

Differential Revision: https://reviews.llvm.org/D121381
  • Loading branch information
nikic committed Mar 18, 2022
1 parent 4a699ae commit f96428e
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 9 deletions.
14 changes: 11 additions & 3 deletions llvm/include/llvm/Analysis/MemorySSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -346,9 +346,9 @@ class MemoryUse final : public MemoryUseOrDef {
setOperand(0, DMA);
}

/// The defining access of a MemoryUses are always optimized if queried from
/// outside MSSA construction itself. This result is only useful inside
/// the MSSA implementation.
/// Whether the MemoryUse is optimized. If ensureOptimizedUses() was called,
/// uses will usually be optimized, but this is not guaranteed (e.g. due to
/// invalidation and optimization limits.)
bool isOptimized() const {
return getDefiningAccess() && OptimizedID == getDefiningAccess()->getID();
}
Expand Down Expand Up @@ -801,6 +801,13 @@ class MemorySSA {
/// about the beginning or end of a block.
enum InsertionPlace { Beginning, End, BeforeTerminator };

/// By default, uses are *not* optimized during MemorySSA construction.
/// Calling this method will attempt to optimize all MemoryUses, if this has
/// not happened yet for this MemorySSA instance. This should be done if you
/// plan to query the clobbering access for most uses, or if you walk the
/// def-use chain of uses.
void ensureOptimizedUses();

protected:
// Used by Memory SSA dumpers and wrapper pass
friend class MemorySSAPrinterLegacyPass;
Expand Down Expand Up @@ -903,6 +910,7 @@ class MemorySSA {
std::unique_ptr<CachingWalker<AliasAnalysis>> Walker;
std::unique_ptr<SkipSelfWalker<AliasAnalysis>> SkipWalker;
unsigned NextID = 0;
bool IsOptimized = false;
};

/// Enables verification of MemorySSA.
Expand Down
20 changes: 16 additions & 4 deletions llvm/lib/Analysis/MemorySSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1397,6 +1397,9 @@ void MemorySSA::OptimizeUses::optimizeUsesInBlock(
continue;
}

if (MU->isOptimized())
continue;

if (isUseTriviallyOptimizableToLiveOnEntry(*AA, MU->getMemoryInst())) {
MU->setDefiningAccess(MSSA->getLiveOnEntryDef(), true, None);
continue;
Expand Down Expand Up @@ -1585,10 +1588,6 @@ void MemorySSA::buildMemorySSA(BatchAAResults &BAA) {
SmallPtrSet<BasicBlock *, 16> Visited;
renamePass(DT->getRootNode(), LiveOnEntryDef.get(), Visited);

ClobberWalkerBase<BatchAAResults> WalkerBase(this, &BAA, DT);
CachingWalker<BatchAAResults> WalkerLocal(this, &WalkerBase);
OptimizeUses(this, &WalkerLocal, &BAA, DT).optimizeUses();

// Mark the uses in unreachable blocks as live on entry, so that they go
// somewhere.
for (auto &BB : F)
Expand Down Expand Up @@ -2178,6 +2177,17 @@ bool MemorySSA::dominates(const MemoryAccess *Dominator,
return dominates(Dominator, cast<MemoryAccess>(Dominatee.getUser()));
}

void MemorySSA::ensureOptimizedUses() {
if (IsOptimized)
return;

BatchAAResults BatchAA(*AA);
ClobberWalkerBase<BatchAAResults> WalkerBase(this, &BatchAA, DT);
CachingWalker<BatchAAResults> WalkerLocal(this, &WalkerBase);
OptimizeUses(this, &WalkerLocal, &BatchAA, DT).optimizeUses();
IsOptimized = true;
}

void MemoryAccess::print(raw_ostream &OS) const {
switch (getValueID()) {
case MemoryPhiVal: return static_cast<const MemoryPhi *>(this)->print(OS);
Expand Down Expand Up @@ -2350,6 +2360,7 @@ struct DOTGraphTraits<DOTFuncMSSAInfo *> : public DefaultDOTGraphTraits {

bool MemorySSAPrinterLegacyPass::runOnFunction(Function &F) {
auto &MSSA = getAnalysis<MemorySSAWrapperPass>().getMSSA();
MSSA.ensureOptimizedUses();
if (DotCFGMSSA != "") {
DOTFuncMSSAInfo CFGInfo(F, MSSA);
WriteGraph(&CFGInfo, "", false, "MSSA", DotCFGMSSA);
Expand Down Expand Up @@ -2382,6 +2393,7 @@ bool MemorySSAAnalysis::Result::invalidate(
PreservedAnalyses MemorySSAPrinterPass::run(Function &F,
FunctionAnalysisManager &AM) {
auto &MSSA = AM.getResult<MemorySSAAnalysis>(F).getMSSA();
MSSA.ensureOptimizedUses();
if (DotCFGMSSA != "") {
DOTFuncMSSAInfo CFGInfo(F, MSSA);
WriteGraph(&CFGInfo, "", false, "MSSA", DotCFGMSSA);
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1933,6 +1933,7 @@ static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA,
const LoopInfo &LI) {
bool MadeChange = false;

MSSA.ensureOptimizedUses();
DSEState State(F, AA, MSSA, DT, PDT, TLI, LI);
// For each store:
for (unsigned I = 0; I < State.MemDefs.size(); I++) {
Expand Down
5 changes: 4 additions & 1 deletion llvm/lib/Transforms/Scalar/EarlyCSE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,10 @@ class EarlyCSE {
const TargetTransformInfo &TTI, DominatorTree &DT,
AssumptionCache &AC, MemorySSA *MSSA)
: TLI(TLI), TTI(TTI), DT(DT), AC(AC), SQ(DL, &TLI, &DT, &AC), MSSA(MSSA),
MSSAUpdater(std::make_unique<MemorySSAUpdater>(MSSA)) {}
MSSAUpdater(std::make_unique<MemorySSAUpdater>(MSSA)) {
if (MSSA)
MSSA->ensureOptimizedUses();
}

bool run();

Expand Down
4 changes: 3 additions & 1 deletion llvm/lib/Transforms/Scalar/GVNHoist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,9 @@ class GVNHoist {
GVNHoist(DominatorTree *DT, PostDominatorTree *PDT, AliasAnalysis *AA,
MemoryDependenceResults *MD, MemorySSA *MSSA)
: DT(DT), PDT(PDT), AA(AA), MD(MD), MSSA(MSSA),
MSSAUpdater(std::make_unique<MemorySSAUpdater>(MSSA)) {}
MSSAUpdater(std::make_unique<MemorySSAUpdater>(MSSA)) {
MSSA->ensureOptimizedUses();
}

bool run(Function &F);

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Transforms/Scalar/LICM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ bool LoopInvariantCodeMotion::runOnLoop(
bool Changed = false;

assert(L->isLCSSAForm(*DT) && "Loop is not in LCSSA form.");
MSSA->ensureOptimizedUses();

// If this loop has metadata indicating that LICM is not to be performed then
// just exit.
Expand Down
2 changes: 2 additions & 0 deletions llvm/unittests/Analysis/MemorySSATest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,7 @@ TEST_F(MemorySSATest, TestLoadMustAlias) {

setupAnalyses();
MemorySSA &MSSA = *Analyses->MSSA;
MSSA.ensureOptimizedUses();

unsigned I = 0;
for (LoadInst *V : {LA1, LA2}) {
Expand Down Expand Up @@ -1119,6 +1120,7 @@ TEST_F(MemorySSATest, TestLoadMayAlias) {

setupAnalyses();
MemorySSA &MSSA = *Analyses->MSSA;
MSSA.ensureOptimizedUses();

unsigned I = 0;
for (LoadInst *V : {LA1, LB1}) {
Expand Down

0 comments on commit f96428e

Please sign in to comment.