#include "llvm/Analysis/MemorySSA.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/CFGPrinter.h"
#include "llvm/Analysis/IteratedDominanceFrontier.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/AssemblyAnnotationWriter.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Use.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/AtomicOrdering.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <iterator>
#include <memory>
#include <utility>
usingnamespacellvm;
#define DEBUG_TYPE …
static cl::opt<std::string>
DotCFGMSSA("dot-cfg-mssa",
cl::value_desc("file name for generated dot file"),
cl::desc("file name for generated dot file"), cl::init(""));
INITIALIZE_PASS_BEGIN(MemorySSAWrapperPass, "memoryssa", "Memory SSA", false,
true)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
INITIALIZE_PASS_END(MemorySSAWrapperPass, "memoryssa", "Memory SSA", false,
true)
static cl::opt<unsigned> MaxCheckLimit(
"memssa-check-limit", cl::Hidden, cl::init(100),
cl::desc("The maximum number of stores/phis MemorySSA"
"will consider trying to walk past (default = 100)"));
#ifdef EXPENSIVE_CHECKS
bool llvm::VerifyMemorySSA = true;
#else
bool llvm::VerifyMemorySSA = …;
#endif
static cl::opt<bool, true>
VerifyMemorySSAX("verify-memoryssa", cl::location(VerifyMemorySSA),
cl::Hidden, cl::desc("Enable verification of MemorySSA."));
const static char LiveOnEntryStr[] = …;
namespace {
class MemorySSAAnnotatedWriter : public AssemblyAnnotationWriter { … };
class MemorySSAWalkerAnnotatedWriter : public AssemblyAnnotationWriter { … };
}
namespace {
class MemoryLocOrCall { … };
}
namespace llvm {
template <> struct DenseMapInfo<MemoryLocOrCall> { … };
}
static bool areLoadsReorderable(const LoadInst *Use,
const LoadInst *MayClobber) { … }
template <typename AliasAnalysisType>
static bool
instructionClobbersQuery(const MemoryDef *MD, const MemoryLocation &UseLoc,
const Instruction *UseInst, AliasAnalysisType &AA) { … }
template <typename AliasAnalysisType>
static bool instructionClobbersQuery(MemoryDef *MD, const MemoryUseOrDef *MU,
const MemoryLocOrCall &UseMLOC,
AliasAnalysisType &AA) { … }
bool MemorySSAUtil::defClobbersUseOrDef(MemoryDef *MD, const MemoryUseOrDef *MU,
AliasAnalysis &AA) { … }
namespace {
struct UpwardsMemoryQuery { … };
}
template <typename AliasAnalysisType>
static bool isUseTriviallyOptimizableToLiveOnEntry(AliasAnalysisType &AA,
const Instruction *I) { … }
LLVM_ATTRIBUTE_UNUSED static void
checkClobberSanity(const MemoryAccess *Start, MemoryAccess *ClobberAt,
const MemoryLocation &StartLoc, const MemorySSA &MSSA,
const UpwardsMemoryQuery &Query, BatchAAResults &AA,
bool AllowImpreciseClobber = false) { … }
namespace {
class ClobberWalker { … };
struct RenamePassData { … };
}
namespace llvm {
class MemorySSA::ClobberWalkerBase { … };
class MemorySSA::CachingWalker final : public MemorySSAWalker { … };
class MemorySSA::SkipSelfWalker final : public MemorySSAWalker { … };
}
void MemorySSA::renameSuccessorPhis(BasicBlock *BB, MemoryAccess *IncomingVal,
bool RenameAllUses) { … }
MemoryAccess *MemorySSA::renameBlock(BasicBlock *BB, MemoryAccess *IncomingVal,
bool RenameAllUses) { … }
void MemorySSA::renamePass(DomTreeNode *Root, MemoryAccess *IncomingVal,
SmallPtrSetImpl<BasicBlock *> &Visited,
bool SkipVisited, bool RenameAllUses) { … }
void MemorySSA::markUnreachableAsLiveOnEntry(BasicBlock *BB) { … }
MemorySSA::MemorySSA(Function &Func, AliasAnalysis *AA, DominatorTree *DT)
: … { … }
MemorySSA::MemorySSA(Loop &L, AliasAnalysis *AA, DominatorTree *DT)
: … { … }
MemorySSA::~MemorySSA() { … }
MemorySSA::AccessList *MemorySSA::getOrCreateAccessList(const BasicBlock *BB) { … }
MemorySSA::DefsList *MemorySSA::getOrCreateDefsList(const BasicBlock *BB) { … }
namespace llvm {
class MemorySSA::OptimizeUses { … };
}
void MemorySSA::OptimizeUses::optimizeUsesInBlock(
const BasicBlock *BB, unsigned long &StackEpoch, unsigned long &PopEpoch,
SmallVectorImpl<MemoryAccess *> &VersionStack,
DenseMap<MemoryLocOrCall, MemlocStackInfo> &LocStackInfo) { … }
void MemorySSA::OptimizeUses::optimizeUses() { … }
void MemorySSA::placePHINodes(
const SmallPtrSetImpl<BasicBlock *> &DefiningBlocks) { … }
template <typename IterT>
void MemorySSA::buildMemorySSA(BatchAAResults &BAA, IterT Blocks) { … }
MemorySSAWalker *MemorySSA::getWalker() { … }
MemorySSA::CachingWalker *MemorySSA::getWalkerImpl() { … }
MemorySSAWalker *MemorySSA::getSkipSelfWalker() { … }
void MemorySSA::insertIntoListsForBlock(MemoryAccess *NewAccess,
const BasicBlock *BB,
InsertionPlace Point) { … }
void MemorySSA::insertIntoListsBefore(MemoryAccess *What, const BasicBlock *BB,
AccessList::iterator InsertPt) { … }
void MemorySSA::prepareForMoveTo(MemoryAccess *What, BasicBlock *BB) { … }
void MemorySSA::moveTo(MemoryUseOrDef *What, BasicBlock *BB,
AccessList::iterator Where) { … }
void MemorySSA::moveTo(MemoryAccess *What, BasicBlock *BB,
InsertionPlace Point) { … }
MemoryPhi *MemorySSA::createMemoryPhi(BasicBlock *BB) { … }
MemoryUseOrDef *MemorySSA::createDefinedAccess(Instruction *I,
MemoryAccess *Definition,
const MemoryUseOrDef *Template,
bool CreationMustSucceed) { … }
static inline bool isOrdered(const Instruction *I) { … }
template <typename AliasAnalysisType>
MemoryUseOrDef *MemorySSA::createNewAccess(Instruction *I,
AliasAnalysisType *AAP,
const MemoryUseOrDef *Template) { … }
void MemorySSA::removeFromLookups(MemoryAccess *MA) { … }
void MemorySSA::removeFromLists(MemoryAccess *MA, bool ShouldDelete) { … }
void MemorySSA::print(raw_ostream &OS) const { … }
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void MemorySSA::dump() const { print(dbgs()); }
#endif
void MemorySSA::verifyMemorySSA(VerificationLevel VL) const { … }
template <typename IterT>
void MemorySSA::verifyPrevDefInPhis(IterT Blocks) const { … }
template <typename IterT>
void MemorySSA::verifyDominationNumbers(IterT Blocks) const { … }
template <typename IterT>
void MemorySSA::verifyOrderingDominationAndDefUses(IterT Blocks,
VerificationLevel VL) const { … }
void MemorySSA::verifyUseInDefs(MemoryAccess *Def, MemoryAccess *Use) const { … }
void MemorySSA::renumberBlock(const BasicBlock *B) const { … }
bool MemorySSA::locallyDominates(const MemoryAccess *Dominator,
const MemoryAccess *Dominatee) const { … }
bool MemorySSA::dominates(const MemoryAccess *Dominator,
const MemoryAccess *Dominatee) const { … }
bool MemorySSA::dominates(const MemoryAccess *Dominator,
const Use &Dominatee) const { … }
void MemorySSA::ensureOptimizedUses() { … }
void MemoryAccess::print(raw_ostream &OS) const { … }
void MemoryDef::print(raw_ostream &OS) const { … }
void MemoryPhi::print(raw_ostream &OS) const { … }
void MemoryUse::print(raw_ostream &OS) const { … }
void MemoryAccess::dump() const { … }
class DOTFuncMSSAInfo { … };
namespace llvm {
template <>
struct GraphTraits<DOTFuncMSSAInfo *> : public GraphTraits<const BasicBlock *> { … };
template <>
struct DOTGraphTraits<DOTFuncMSSAInfo *> : public DefaultDOTGraphTraits { … };
}
AnalysisKey MemorySSAAnalysis::Key;
MemorySSAAnalysis::Result MemorySSAAnalysis::run(Function &F,
FunctionAnalysisManager &AM) { … }
bool MemorySSAAnalysis::Result::invalidate(
Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &Inv) { … }
PreservedAnalyses MemorySSAPrinterPass::run(Function &F,
FunctionAnalysisManager &AM) { … }
PreservedAnalyses MemorySSAWalkerPrinterPass::run(Function &F,
FunctionAnalysisManager &AM) { … }
PreservedAnalyses MemorySSAVerifierPass::run(Function &F,
FunctionAnalysisManager &AM) { … }
char MemorySSAWrapperPass::ID = …;
MemorySSAWrapperPass::MemorySSAWrapperPass() : … { … }
void MemorySSAWrapperPass::releaseMemory() { … }
void MemorySSAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { … }
bool MemorySSAWrapperPass::runOnFunction(Function &F) { … }
void MemorySSAWrapperPass::verifyAnalysis() const { … }
void MemorySSAWrapperPass::print(raw_ostream &OS, const Module *M) const { … }
MemorySSAWalker::MemorySSAWalker(MemorySSA *M) : … { … }
MemoryAccess *MemorySSA::ClobberWalkerBase::getClobberingMemoryAccessBase(
MemoryAccess *StartingAccess, const MemoryLocation &Loc,
BatchAAResults &BAA, unsigned &UpwardWalkLimit) { … }
static const Instruction *
getInvariantGroupClobberingInstruction(Instruction &I, DominatorTree &DT) { … }
MemoryAccess *MemorySSA::ClobberWalkerBase::getClobberingMemoryAccessBase(
MemoryAccess *MA, BatchAAResults &BAA, unsigned &UpwardWalkLimit,
bool SkipSelf, bool UseInvariantGroup) { … }
MemoryAccess *
DoNothingMemorySSAWalker::getClobberingMemoryAccess(MemoryAccess *MA,
BatchAAResults &) { … }
MemoryAccess *DoNothingMemorySSAWalker::getClobberingMemoryAccess(
MemoryAccess *StartingAccess, const MemoryLocation &, BatchAAResults &) { … }
void MemoryPhi::deleteMe(DerivedUser *Self) { … }
void MemoryDef::deleteMe(DerivedUser *Self) { … }
void MemoryUse::deleteMe(DerivedUser *Self) { … }
bool upward_defs_iterator::IsGuaranteedLoopInvariant(const Value *Ptr) const { … }