/// def-use chain of uses.
void ensureOptimizedUses();
+ AliasAnalysis &getAA() { return *AA; }
+
protected:
// Used by Memory SSA dumpers and wrapper pass
friend class MemorySSAPrinterLegacyPass;
bool CreationMustSucceed = true);
private:
- template <class AliasAnalysisType> class ClobberWalkerBase;
- template <class AliasAnalysisType> class CachingWalker;
- template <class AliasAnalysisType> class SkipSelfWalker;
+ class ClobberWalkerBase;
+ class CachingWalker;
+ class SkipSelfWalker;
class OptimizeUses;
- CachingWalker<AliasAnalysis> *getWalkerImpl();
+ CachingWalker *getWalkerImpl();
void buildMemorySSA(BatchAAResults &BAA);
void prepareForMoveTo(MemoryAccess *, BasicBlock *);
mutable DenseMap<const MemoryAccess *, unsigned long> BlockNumbering;
// Memory SSA building info
- std::unique_ptr<ClobberWalkerBase<AliasAnalysis>> WalkerBase;
- std::unique_ptr<CachingWalker<AliasAnalysis>> Walker;
- std::unique_ptr<SkipSelfWalker<AliasAnalysis>> SkipWalker;
+ std::unique_ptr<ClobberWalkerBase> WalkerBase;
+ std::unique_ptr<CachingWalker> Walker;
+ std::unique_ptr<SkipSelfWalker> SkipWalker;
unsigned NextID = 0;
bool IsOptimized = false;
};
///
/// calling this API on load(%a) will return the MemoryPhi, not the MemoryDef
/// in the if (a) branch.
- MemoryAccess *getClobberingMemoryAccess(const Instruction *I) {
+ MemoryAccess *getClobberingMemoryAccess(const Instruction *I,
+ BatchAAResults &AA) {
MemoryAccess *MA = MSSA->getMemoryAccess(I);
assert(MA && "Handed an instruction that MemorySSA doesn't recognize?");
- return getClobberingMemoryAccess(MA);
+ return getClobberingMemoryAccess(MA, AA);
}
/// Does the same thing as getClobberingMemoryAccess(const Instruction *I),
/// but takes a MemoryAccess instead of an Instruction.
- virtual MemoryAccess *getClobberingMemoryAccess(MemoryAccess *) = 0;
+ virtual MemoryAccess *getClobberingMemoryAccess(MemoryAccess *,
+ BatchAAResults &AA) = 0;
/// Given a potentially clobbering memory access and a new location,
/// calling this will give you the nearest dominating clobbering MemoryAccess
/// will return that MemoryDef, whereas the above would return the clobber
/// starting from the use side of the memory def.
virtual MemoryAccess *getClobberingMemoryAccess(MemoryAccess *,
- const MemoryLocation &) = 0;
+ const MemoryLocation &,
+ BatchAAResults &AA) = 0;
+
+ MemoryAccess *getClobberingMemoryAccess(const Instruction *I) {
+ BatchAAResults BAA(MSSA->getAA());
+ return getClobberingMemoryAccess(I, BAA);
+ }
+
+ MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA) {
+ BatchAAResults BAA(MSSA->getAA());
+ return getClobberingMemoryAccess(MA, BAA);
+ }
+
+ MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA,
+ const MemoryLocation &Loc) {
+ BatchAAResults BAA(MSSA->getAA());
+ return getClobberingMemoryAccess(MA, Loc, BAA);
+ }
/// Given a memory access, invalidate anything this walker knows about
/// that access.
// getClobberingMemoryAccess.
using MemorySSAWalker::getClobberingMemoryAccess;
- MemoryAccess *getClobberingMemoryAccess(MemoryAccess *) override;
MemoryAccess *getClobberingMemoryAccess(MemoryAccess *,
- const MemoryLocation &) override;
+ BatchAAResults &) override;
+ MemoryAccess *getClobberingMemoryAccess(MemoryAccess *,
+ const MemoryLocation &,
+ BatchAAResults &) override;
};
using MemoryAccessPair = std::pair<MemoryAccess *, MemoryLocation>;
class MemorySSAWalkerAnnotatedWriter : public AssemblyAnnotationWriter {
MemorySSA *MSSA;
MemorySSAWalker *Walker;
+ BatchAAResults BAA;
public:
MemorySSAWalkerAnnotatedWriter(MemorySSA *M)
- : MSSA(M), Walker(M->getWalker()) {}
+ : MSSA(M), Walker(M->getWalker()), BAA(M->getAA()) {}
void emitBasicBlockStartAnnot(const BasicBlock *BB,
formatted_raw_ostream &OS) override {
void emitInstructionAnnot(const Instruction *I,
formatted_raw_ostream &OS) override {
if (MemoryAccess *MA = MSSA->getMemoryAccess(I)) {
- MemoryAccess *Clobber = Walker->getClobberingMemoryAccess(MA);
+ MemoryAccess *Clobber = Walker->getClobberingMemoryAccess(MA, BAA);
OS << "; " << *MA;
if (Clobber) {
OS << " - clobbered by ";
} // end anonymous namespace
-template <typename AliasAnalysisType>
-static bool isUseTriviallyOptimizableToLiveOnEntry(AliasAnalysisType &AA,
+static bool isUseTriviallyOptimizableToLiveOnEntry(BatchAAResults &AA,
const Instruction *I) {
// If the memory can't be changed, then loads of the memory can't be
// clobbered.
/// \param AA The AliasAnalysis we used for our search.
/// \param AllowImpreciseClobber Always false, unless we do relaxed verify.
-template <typename AliasAnalysisType>
LLVM_ATTRIBUTE_UNUSED static void
checkClobberSanity(const MemoryAccess *Start, MemoryAccess *ClobberAt,
const MemoryLocation &StartLoc, const MemorySSA &MSSA,
- const UpwardsMemoryQuery &Query, AliasAnalysisType &AA,
+ const UpwardsMemoryQuery &Query, BatchAAResults &AA,
bool AllowImpreciseClobber = false) {
assert(MSSA.dominates(ClobberAt, Start) && "Clobber doesn't dominate start?");
/// Our algorithm for walking (and trying to optimize) clobbers, all wrapped up
/// in one class.
-template <class AliasAnalysisType> class ClobberWalker {
+class ClobberWalker {
/// Save a few bytes by using unsigned instead of size_t.
using ListIndex = unsigned;
};
const MemorySSA &MSSA;
- AliasAnalysisType &AA;
DominatorTree &DT;
+ BatchAAResults *AA;
UpwardsMemoryQuery *Query;
unsigned *UpwardWalkLimit;
if (!--*UpwardWalkLimit)
return {Current, true};
- if (instructionClobbersQuery(MD, Desc.Loc, Query->Inst, AA))
+ if (instructionClobbersQuery(MD, Desc.Loc, Query->Inst, *AA))
return {MD, true};
}
}
}
public:
- ClobberWalker(const MemorySSA &MSSA, AliasAnalysisType &AA, DominatorTree &DT)
- : MSSA(MSSA), AA(AA), DT(DT) {}
+ ClobberWalker(const MemorySSA &MSSA, DominatorTree &DT)
+ : MSSA(MSSA), DT(DT) {}
- AliasAnalysisType *getAA() { return &AA; }
/// Finds the nearest clobber for the given query, optimizing phis if
/// possible.
- MemoryAccess *findClobber(MemoryAccess *Start, UpwardsMemoryQuery &Q,
- unsigned &UpWalkLimit) {
+ MemoryAccess *findClobber(BatchAAResults &BAA, MemoryAccess *Start,
+ UpwardsMemoryQuery &Q, unsigned &UpWalkLimit) {
+ AA = &BAA;
Query = &Q;
UpwardWalkLimit = &UpWalkLimit;
// Starting limit must be > 0.
#ifdef EXPENSIVE_CHECKS
if (!Q.SkipSelfAccess && *UpwardWalkLimit > 0)
- checkClobberSanity(Current, Result, Q.StartingLoc, MSSA, Q, AA);
+ checkClobberSanity(Current, Result, Q.StartingLoc, MSSA, Q, BAA);
#endif
return Result;
}
namespace llvm {
-template <class AliasAnalysisType> class MemorySSA::ClobberWalkerBase {
- ClobberWalker<AliasAnalysisType> Walker;
+class MemorySSA::ClobberWalkerBase {
+ ClobberWalker Walker;
MemorySSA *MSSA;
public:
- ClobberWalkerBase(MemorySSA *M, AliasAnalysisType *A, DominatorTree *D)
- : Walker(*M, *A, *D), MSSA(M) {}
+ ClobberWalkerBase(MemorySSA *M, DominatorTree *D) : Walker(*M, *D), MSSA(M) {}
MemoryAccess *getClobberingMemoryAccessBase(MemoryAccess *,
const MemoryLocation &,
- unsigned &);
+ BatchAAResults &, unsigned &);
// Third argument (bool), defines whether the clobber search should skip the
// original queried access. If true, there will be a follow-up query searching
// for a clobber access past "self". Note that the Optimized access is not
// updated if a new clobber is found by this SkipSelf search. If this
// additional query becomes heavily used we may decide to cache the result.
// Walker instantiations will decide how to set the SkipSelf bool.
- MemoryAccess *getClobberingMemoryAccessBase(MemoryAccess *, unsigned &, bool,
+ MemoryAccess *getClobberingMemoryAccessBase(MemoryAccess *, BatchAAResults &,
+ unsigned &, bool,
bool UseInvariantGroup = true);
};
/// A MemorySSAWalker that does AA walks to disambiguate accesses. It no
/// longer does caching on its own, but the name has been retained for the
/// moment.
-template <class AliasAnalysisType>
class MemorySSA::CachingWalker final : public MemorySSAWalker {
- ClobberWalkerBase<AliasAnalysisType> *Walker;
+ ClobberWalkerBase *Walker;
public:
- CachingWalker(MemorySSA *M, ClobberWalkerBase<AliasAnalysisType> *W)
+ CachingWalker(MemorySSA *M, ClobberWalkerBase *W)
: MemorySSAWalker(M), Walker(W) {}
~CachingWalker() override = default;
using MemorySSAWalker::getClobberingMemoryAccess;
- MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA, unsigned &UWL) {
- return Walker->getClobberingMemoryAccessBase(MA, UWL, false);
+ MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA, BatchAAResults &BAA,
+ unsigned &UWL) {
+ return Walker->getClobberingMemoryAccessBase(MA, BAA, UWL, false);
}
MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA,
const MemoryLocation &Loc,
- unsigned &UWL) {
- return Walker->getClobberingMemoryAccessBase(MA, Loc, UWL);
+ BatchAAResults &BAA, unsigned &UWL) {
+ return Walker->getClobberingMemoryAccessBase(MA, Loc, BAA, UWL);
}
// This method is not accessible outside of this file.
- MemoryAccess *getClobberingMemoryAccessWithoutInvariantGroup(MemoryAccess *MA,
- unsigned &UWL) {
- return Walker->getClobberingMemoryAccessBase(MA, UWL, false, false);
+ MemoryAccess *getClobberingMemoryAccessWithoutInvariantGroup(
+ MemoryAccess *MA, BatchAAResults &BAA, unsigned &UWL) {
+ return Walker->getClobberingMemoryAccessBase(MA, BAA, UWL, false, false);
}
- MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA) override {
+ MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA,
+ BatchAAResults &BAA) override {
unsigned UpwardWalkLimit = MaxCheckLimit;
- return getClobberingMemoryAccess(MA, UpwardWalkLimit);
+ return getClobberingMemoryAccess(MA, BAA, UpwardWalkLimit);
}
MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA,
- const MemoryLocation &Loc) override {
+ const MemoryLocation &Loc,
+ BatchAAResults &BAA) override {
unsigned UpwardWalkLimit = MaxCheckLimit;
- return getClobberingMemoryAccess(MA, Loc, UpwardWalkLimit);
+ return getClobberingMemoryAccess(MA, Loc, BAA, UpwardWalkLimit);
}
void invalidateInfo(MemoryAccess *MA) override {
}
};
-template <class AliasAnalysisType>
class MemorySSA::SkipSelfWalker final : public MemorySSAWalker {
- ClobberWalkerBase<AliasAnalysisType> *Walker;
+ ClobberWalkerBase *Walker;
public:
- SkipSelfWalker(MemorySSA *M, ClobberWalkerBase<AliasAnalysisType> *W)
+ SkipSelfWalker(MemorySSA *M, ClobberWalkerBase *W)
: MemorySSAWalker(M), Walker(W) {}
~SkipSelfWalker() override = default;
using MemorySSAWalker::getClobberingMemoryAccess;
- MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA, unsigned &UWL) {
- return Walker->getClobberingMemoryAccessBase(MA, UWL, true);
+ MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA, BatchAAResults &BAA,
+ unsigned &UWL) {
+ return Walker->getClobberingMemoryAccessBase(MA, BAA, UWL, true);
}
MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA,
const MemoryLocation &Loc,
- unsigned &UWL) {
- return Walker->getClobberingMemoryAccessBase(MA, Loc, UWL);
+ BatchAAResults &BAA, unsigned &UWL) {
+ return Walker->getClobberingMemoryAccessBase(MA, Loc, BAA, UWL);
}
- MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA) override {
+ MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA,
+ BatchAAResults &BAA) override {
unsigned UpwardWalkLimit = MaxCheckLimit;
- return getClobberingMemoryAccess(MA, UpwardWalkLimit);
+ return getClobberingMemoryAccess(MA, BAA, UpwardWalkLimit);
}
MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA,
- const MemoryLocation &Loc) override {
+ const MemoryLocation &Loc,
+ BatchAAResults &BAA) override {
unsigned UpwardWalkLimit = MaxCheckLimit;
- return getClobberingMemoryAccess(MA, Loc, UpwardWalkLimit);
+ return getClobberingMemoryAccess(MA, Loc, BAA, UpwardWalkLimit);
}
void invalidateInfo(MemoryAccess *MA) override {
/// which is walking bottom-up.
class MemorySSA::OptimizeUses {
public:
- OptimizeUses(MemorySSA *MSSA, CachingWalker<BatchAAResults> *Walker,
- BatchAAResults *BAA, DominatorTree *DT)
+ OptimizeUses(MemorySSA *MSSA, CachingWalker *Walker, BatchAAResults *BAA,
+ DominatorTree *DT)
: MSSA(MSSA), Walker(Walker), AA(BAA), DT(DT) {}
void optimizeUses();
DenseMap<MemoryLocOrCall, MemlocStackInfo> &);
MemorySSA *MSSA;
- CachingWalker<BatchAAResults> *Walker;
+ CachingWalker *Walker;
BatchAAResults *AA;
DominatorTree *DT;
};
// support updates, so don't use it to optimize uses.
MemoryAccess *Result =
Walker->getClobberingMemoryAccessWithoutInvariantGroup(
- MU, UpwardWalkLimit);
+ MU, *AA, UpwardWalkLimit);
// We are guaranteed to find it or something is wrong.
while (VersionStack[UpperBound] != Result) {
assert(UpperBound != 0);
MemorySSAWalker *MemorySSA::getWalker() { return getWalkerImpl(); }
-MemorySSA::CachingWalker<AliasAnalysis> *MemorySSA::getWalkerImpl() {
+MemorySSA::CachingWalker *MemorySSA::getWalkerImpl() {
if (Walker)
return Walker.get();
if (!WalkerBase)
- WalkerBase =
- std::make_unique<ClobberWalkerBase<AliasAnalysis>>(this, AA, DT);
+ WalkerBase = std::make_unique<ClobberWalkerBase>(this, DT);
- Walker =
- std::make_unique<CachingWalker<AliasAnalysis>>(this, WalkerBase.get());
+ Walker = std::make_unique<CachingWalker>(this, WalkerBase.get());
return Walker.get();
}
return SkipWalker.get();
if (!WalkerBase)
- WalkerBase =
- std::make_unique<ClobberWalkerBase<AliasAnalysis>>(this, AA, DT);
+ WalkerBase = std::make_unique<ClobberWalkerBase>(this, DT);
- SkipWalker =
- std::make_unique<SkipSelfWalker<AliasAnalysis>>(this, WalkerBase.get());
+ SkipWalker = std::make_unique<SkipSelfWalker>(this, WalkerBase.get());
return SkipWalker.get();
}
return;
BatchAAResults BatchAA(*AA);
- ClobberWalkerBase<BatchAAResults> WalkerBase(this, &BatchAA, DT);
- CachingWalker<BatchAAResults> WalkerLocal(this, &WalkerBase);
+ ClobberWalkerBase WalkerBase(this, DT);
+ CachingWalker WalkerLocal(this, &WalkerBase);
OptimizeUses(this, &WalkerLocal, &BatchAA, DT).optimizeUses();
IsOptimized = true;
}
/// the MemoryAccess that actually clobbers Loc.
///
/// \returns our clobbering memory access
-template <typename AliasAnalysisType>
-MemoryAccess *
-MemorySSA::ClobberWalkerBase<AliasAnalysisType>::getClobberingMemoryAccessBase(
+MemoryAccess *MemorySSA::ClobberWalkerBase::getClobberingMemoryAccessBase(
MemoryAccess *StartingAccess, const MemoryLocation &Loc,
- unsigned &UpwardWalkLimit) {
+ BatchAAResults &BAA, unsigned &UpwardWalkLimit) {
assert(!isa<MemoryUse>(StartingAccess) && "Use cannot be defining access");
Instruction *I = nullptr;
// handed something we already believe is the clobbering access.
// We never set SkipSelf to true in Q in this method.
MemoryAccess *Clobber =
- Walker.findClobber(StartingAccess, Q, UpwardWalkLimit);
+ Walker.findClobber(BAA, StartingAccess, Q, UpwardWalkLimit);
LLVM_DEBUG({
dbgs() << "Clobber starting at access " << *StartingAccess << "\n";
if (I)
return MostDominatingInstruction == &I ? nullptr : MostDominatingInstruction;
}
-template <typename AliasAnalysisType>
-MemoryAccess *
-MemorySSA::ClobberWalkerBase<AliasAnalysisType>::getClobberingMemoryAccessBase(
- MemoryAccess *MA, unsigned &UpwardWalkLimit, bool SkipSelf,
- bool UseInvariantGroup) {
+MemoryAccess *MemorySSA::ClobberWalkerBase::getClobberingMemoryAccessBase(
+ MemoryAccess *MA, BatchAAResults &BAA, unsigned &UpwardWalkLimit,
+ bool SkipSelf, bool UseInvariantGroup) {
auto *StartingAccess = dyn_cast<MemoryUseOrDef>(MA);
// If this is a MemoryPhi, we can't do anything.
if (!StartingAccess)
UpwardsMemoryQuery Q(I, StartingAccess);
- if (isUseTriviallyOptimizableToLiveOnEntry(*Walker.getAA(), I)) {
+ if (isUseTriviallyOptimizableToLiveOnEntry(BAA, I)) {
MemoryAccess *LiveOnEntry = MSSA->getLiveOnEntryDef();
StartingAccess->setOptimized(LiveOnEntry);
return LiveOnEntry;
return DefiningAccess;
}
- OptimizedAccess = Walker.findClobber(DefiningAccess, Q, UpwardWalkLimit);
+ OptimizedAccess =
+ Walker.findClobber(BAA, DefiningAccess, Q, UpwardWalkLimit);
StartingAccess->setOptimized(OptimizedAccess);
} else
OptimizedAccess = StartingAccess->getOptimized();
isa<MemoryDef>(StartingAccess) && UpwardWalkLimit) {
assert(isa<MemoryDef>(Q.OriginalAccess));
Q.SkipSelfAccess = true;
- Result = Walker.findClobber(OptimizedAccess, Q, UpwardWalkLimit);
+ Result = Walker.findClobber(BAA, OptimizedAccess, Q, UpwardWalkLimit);
} else
Result = OptimizedAccess;
}
MemoryAccess *
-DoNothingMemorySSAWalker::getClobberingMemoryAccess(MemoryAccess *MA) {
+DoNothingMemorySSAWalker::getClobberingMemoryAccess(MemoryAccess *MA,
+ BatchAAResults &) {
if (auto *Use = dyn_cast<MemoryUseOrDef>(MA))
return Use->getDefiningAccess();
return MA;
}
MemoryAccess *DoNothingMemorySSAWalker::getClobberingMemoryAccess(
- MemoryAccess *StartingAccess, const MemoryLocation &) {
+ MemoryAccess *StartingAccess, const MemoryLocation &, BatchAAResults &) {
if (auto *Use = dyn_cast<MemoryUseOrDef>(StartingAccess))
return Use->getDefiningAccess();
return StartingAccess;