Index: include/llvm/InitializePasses.h =================================================================== --- include/llvm/InitializePasses.h +++ include/llvm/InitializePasses.h @@ -219,7 +219,7 @@ void initializeMemDerefPrinterPass(PassRegistry&); void initializeMemoryDependenceWrapperPassPass(PassRegistry&); void initializeMemorySSALazyPass(PassRegistry&); -void initializeMemorySSAPrinterPassPass(PassRegistry&); +void initializeMemorySSAPrinterLegacyPassPass(PassRegistry&); void initializeMergedLoadStoreMotionPass(PassRegistry &); void initializeMetaRenamerPass(PassRegistry&); void initializeMergeFunctionsPass(PassRegistry&); Index: include/llvm/Transforms/Utils/MemorySSA.h =================================================================== --- include/llvm/Transforms/Utils/MemorySSA.h +++ include/llvm/Transforms/Utils/MemorySSA.h @@ -539,7 +539,7 @@ protected: // Used by Memory SSA annotater, dumpers, and wrapper pass friend class MemorySSAAnnotatedWriter; - friend class MemorySSAPrinterPass; + friend class MemorySSAPrinterLegacyPass; void verifyDefUses(Function &F) const; void verifyDomination(Function &F) const; @@ -577,9 +577,9 @@ // This pass does eager building and then printing of MemorySSA. It is used by // the tests to be able to build, dump, and verify Memory SSA. -class MemorySSAPrinterPass : public FunctionPass { +class MemorySSAPrinterLegacyPass : public FunctionPass { public: - MemorySSAPrinterPass(); + MemorySSAPrinterLegacyPass(); static char ID; bool doInitialization(Module &M) override; @@ -587,18 +587,53 @@ void releaseMemory() override; void getAnalysisUsage(AnalysisUsage &AU) const override; void print(raw_ostream &OS, const Module *M) const override; - static void registerOptions(); MemorySSA &getMSSA() { return *MSSA; } private: - bool VerifyMemorySSA; - std::unique_ptr MSSA; // FIXME(gbiv): It seems that MemorySSA doesn't own the walker it returns? std::unique_ptr Walker; Function *F; }; +/// \brief Printer pass for the \c MemorySSA. +class MemorySSAPrinterPass + : public PassInfoMixin { + raw_ostream &OS; + +public: + explicit MemorySSAPrinterPass(raw_ostream &OS); + PreservedAnalyses run(Function &F, AnalysisManager &AM); +}; + +class MemorySSALazyResults { +public: + MemorySSALazyResults(Function &F); + + MemorySSA &getMSSA() { + assert(MSSA); + return *MSSA; + } + +private: + std::unique_ptr MSSA; +}; + +/// An analysis that produces \c MemorySSA for a function. +/// +/// This is essentially a no-op because the results are computed entirely +/// lazily. +class MemorySSALazyAnalysis + : public AnalysisInfoMixin { + friend AnalysisInfoMixin; + static char PassID; + +public: + typedef MemorySSALazyResults Result; + + MemorySSALazyResults run(Function &F, AnalysisManager &AM); +}; + class MemorySSALazy : public FunctionPass { public: MemorySSALazy(); Index: lib/Passes/PassBuilder.cpp =================================================================== --- lib/Passes/PassBuilder.cpp +++ lib/Passes/PassBuilder.cpp @@ -62,6 +62,7 @@ #include "llvm/Transforms/Scalar/SROA.h" #include "llvm/Transforms/Scalar/SimplifyCFG.h" #include "llvm/Transforms/Scalar/Sink.h" +#include "llvm/Transforms/Utils/MemorySSA.h" #include using namespace llvm; Index: lib/Passes/PassRegistry.def =================================================================== --- lib/Passes/PassRegistry.def +++ lib/Passes/PassRegistry.def @@ -74,6 +74,7 @@ FUNCTION_ANALYSIS("domfrontier", DominanceFrontierAnalysis()) FUNCTION_ANALYSIS("loops", LoopAnalysis()) FUNCTION_ANALYSIS("memdep", MemoryDependenceAnalysis()) +FUNCTION_ANALYSIS("memoryssa", MemorySSALazyAnalysis()) FUNCTION_ANALYSIS("regions", RegionInfoAnalysis()) FUNCTION_ANALYSIS("no-op-function", NoOpFunctionAnalysis()) FUNCTION_ANALYSIS("scalar-evolution", ScalarEvolutionAnalysis()) @@ -112,6 +113,7 @@ FUNCTION_PASS("print", DemandedBitsPrinterPass(dbgs())) FUNCTION_PASS("print", DominanceFrontierPrinterPass(dbgs())) FUNCTION_PASS("print", LoopPrinterPass(dbgs())) +FUNCTION_PASS("print", MemorySSAPrinterPass(dbgs())) FUNCTION_PASS("print", RegionInfoPrinterPass(dbgs())) FUNCTION_PASS("print", ScalarEvolutionPrinterPass(dbgs())) FUNCTION_PASS("reassociate", ReassociatePass()) Index: lib/Transforms/Utils/MemorySSA.cpp =================================================================== --- lib/Transforms/Utils/MemorySSA.cpp +++ lib/Transforms/Utils/MemorySSA.cpp @@ -46,15 +46,19 @@ STATISTIC(NumClobberCacheLookups, "Number of Memory SSA version cache lookups"); STATISTIC(NumClobberCacheHits, "Number of Memory SSA version cache hits"); STATISTIC(NumClobberCacheInserts, "Number of MemorySSA version cache inserts"); -INITIALIZE_PASS_WITH_OPTIONS_BEGIN(MemorySSAPrinterPass, "print-memoryssa", - "Memory SSA", true, true) +INITIALIZE_PASS_BEGIN(MemorySSAPrinterLegacyPass, "print-memoryssa", + "Memory SSA", true, true) INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass) -INITIALIZE_PASS_END(MemorySSAPrinterPass, "print-memoryssa", "Memory SSA", true, - true) +INITIALIZE_PASS_END(MemorySSAPrinterLegacyPass, "print-memoryssa", "Memory SSA", + true, true) INITIALIZE_PASS(MemorySSALazy, "memoryssalazy", "Memory SSA", true, true) +static cl::opt VerifyMemorySSA("verify-memoryssa", cl::init(false), + cl::Hidden, + cl::desc("Run the Memory SSA verifier")); + namespace llvm { /// \brief An assembly annotator class to print Memory SSA information in @@ -677,20 +681,20 @@ dbgs() << "\n"; } -char MemorySSAPrinterPass::ID = 0; +char MemorySSAPrinterLegacyPass::ID = 0; -MemorySSAPrinterPass::MemorySSAPrinterPass() : FunctionPass(ID) { - initializeMemorySSAPrinterPassPass(*PassRegistry::getPassRegistry()); +MemorySSAPrinterLegacyPass::MemorySSAPrinterLegacyPass() : FunctionPass(ID) { + initializeMemorySSAPrinterLegacyPassPass(*PassRegistry::getPassRegistry()); } -void MemorySSAPrinterPass::releaseMemory() { +void MemorySSAPrinterLegacyPass::releaseMemory() { // Subtlety: Be sure to delete the walker before MSSA, because the walker's // dtor may try to access MemorySSA. Walker.reset(); MSSA.reset(); } -void MemorySSAPrinterPass::getAnalysisUsage(AnalysisUsage &AU) const { +void MemorySSAPrinterLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); AU.addRequired(); AU.addRequired(); @@ -698,24 +702,15 @@ AU.addPreserved(); } -bool MemorySSAPrinterPass::doInitialization(Module &M) { - VerifyMemorySSA = M.getContext() - .getOption(); +bool MemorySSAPrinterLegacyPass::doInitialization(Module &M) { return false; } -void MemorySSAPrinterPass::registerOptions() { - OptionRegistry::registerOption( - "verify-memoryssa", "Run the Memory SSA verifier", false); -} - -void MemorySSAPrinterPass::print(raw_ostream &OS, const Module *M) const { +void MemorySSAPrinterLegacyPass::print(raw_ostream &OS, const Module *M) const { MSSA->print(OS); } -bool MemorySSAPrinterPass::runOnFunction(Function &F) { +bool MemorySSAPrinterLegacyPass::runOnFunction(Function &F) { this->F = &F; MSSA.reset(new MemorySSA(F)); AliasAnalysis *AA = &getAnalysis().getAAResults(); @@ -729,6 +724,36 @@ return false; } +MemorySSAPrinterPass::MemorySSAPrinterPass(raw_ostream &OS) : OS(OS) {} + +PreservedAnalyses MemorySSAPrinterPass::run(Function &F, + FunctionAnalysisManager &AM) { + OS << "MemorySSA for function: " << F.getName() << "\n"; + + auto &DT = AM.getResult(F); + auto &AA = AM.getResult(F); + MemorySSA &MSSA = AM.getResult(F).getMSSA(); + + MSSA.buildMemorySSA(&AA, &DT); + MSSA.print(OS); + + if (VerifyMemorySSA) + MSSA.verifyMemorySSA(); + + return PreservedAnalyses::all(); +} + +MemorySSALazyResults::MemorySSALazyResults(Function &F) { + MSSA.reset(new MemorySSA(F)); +} + +char MemorySSALazyAnalysis::PassID; + +MemorySSALazyResults +MemorySSALazyAnalysis::run(Function &F, AnalysisManager &AM) { + return MemorySSALazyResults(F); +} + char MemorySSALazy::ID = 0; MemorySSALazy::MemorySSALazy() : FunctionPass(ID) { Index: lib/Transforms/Utils/Utils.cpp =================================================================== --- lib/Transforms/Utils/Utils.cpp +++ lib/Transforms/Utils/Utils.cpp @@ -34,7 +34,7 @@ initializeInstSimplifierPass(Registry); initializeMetaRenamerPass(Registry); initializeMemorySSALazyPass(Registry); - initializeMemorySSAPrinterPassPass(Registry); + initializeMemorySSAPrinterLegacyPassPass(Registry); } /// LLVMInitializeTransformUtils - C binding for initializeTransformUtilsPasses. Index: test/Transforms/Util/MemorySSA/atomic-clobber.ll =================================================================== --- test/Transforms/Util/MemorySSA/atomic-clobber.ll +++ test/Transforms/Util/MemorySSA/atomic-clobber.ll @@ -1,4 +1,5 @@ ; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa -passes='print' -verify-memoryssa -disable-output < %s 2>&1 | FileCheck %s ; ; Ensures that atomic loads count as MemoryDefs Index: test/Transforms/Util/MemorySSA/cyclicphi.ll =================================================================== --- test/Transforms/Util/MemorySSA/cyclicphi.ll +++ test/Transforms/Util/MemorySSA/cyclicphi.ll @@ -1,4 +1,5 @@ ; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa -passes='print' -verify-memoryssa -disable-output < %s 2>&1 | FileCheck %s %struct.hoge = type { i32, %struct.widget } %struct.widget = type { i64 } Index: test/Transforms/Util/MemorySSA/function-clobber.ll =================================================================== --- test/Transforms/Util/MemorySSA/function-clobber.ll +++ test/Transforms/Util/MemorySSA/function-clobber.ll @@ -1,4 +1,5 @@ ; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa -passes='print' -verify-memoryssa -disable-output < %s 2>&1 | FileCheck %s ; ; Ensuring that external functions without attributes are MemoryDefs Index: test/Transforms/Util/MemorySSA/function-mem-attrs.ll =================================================================== --- test/Transforms/Util/MemorySSA/function-mem-attrs.ll +++ test/Transforms/Util/MemorySSA/function-mem-attrs.ll @@ -1,4 +1,5 @@ ; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa -passes='print' -verify-memoryssa -disable-output < %s 2>&1 | FileCheck %s ; ; Test that various function attributes give us sane results. Index: test/Transforms/Util/MemorySSA/livein.ll =================================================================== --- test/Transforms/Util/MemorySSA/livein.ll +++ test/Transforms/Util/MemorySSA/livein.ll @@ -1,4 +1,5 @@ ; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa -passes='print' -verify-memoryssa -disable-output < %s 2>&1 | FileCheck %s define void @F(i8*) { br i1 true, label %left, label %right left: Index: test/Transforms/Util/MemorySSA/load-invariant.ll =================================================================== --- test/Transforms/Util/MemorySSA/load-invariant.ll +++ test/Transforms/Util/MemorySSA/load-invariant.ll @@ -1,5 +1,6 @@ ; XFAIL: * ; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa -passes='print' -verify-memoryssa -disable-output < %s 2>&1 | FileCheck %s ; ; Invariant loads should be considered live on entry, because, once the ; location is known to be dereferenceable, the value can never change. Index: test/Transforms/Util/MemorySSA/many-dom-backedge.ll =================================================================== --- test/Transforms/Util/MemorySSA/many-dom-backedge.ll +++ test/Transforms/Util/MemorySSA/many-dom-backedge.ll @@ -1,4 +1,5 @@ ; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa -passes='print' -verify-memoryssa -disable-output < %s 2>&1 | FileCheck %s ; ; many-dom.ll, with an added back-edge back into the switch. ; Because people love their gotos. Index: test/Transforms/Util/MemorySSA/many-doms.ll =================================================================== --- test/Transforms/Util/MemorySSA/many-doms.ll +++ test/Transforms/Util/MemorySSA/many-doms.ll @@ -1,4 +1,5 @@ ; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa -passes='print' -verify-memoryssa -disable-output < %s 2>&1 | FileCheck %s ; ; Testing many dominators, specifically from a switch statement in C. Index: test/Transforms/Util/MemorySSA/multi-edges.ll =================================================================== --- test/Transforms/Util/MemorySSA/multi-edges.ll +++ test/Transforms/Util/MemorySSA/multi-edges.ll @@ -1,4 +1,5 @@ ; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa -passes='print' -verify-memoryssa -disable-output < %s 2>&1 | FileCheck %s ; ; Makes sure we have a sane model if both successors of some block is the same ; block. Index: test/Transforms/Util/MemorySSA/multiple-backedges-hal.ll =================================================================== --- test/Transforms/Util/MemorySSA/multiple-backedges-hal.ll +++ test/Transforms/Util/MemorySSA/multiple-backedges-hal.ll @@ -1,4 +1,5 @@ ; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa -passes='print' -verify-memoryssa -disable-output < %s 2>&1 | FileCheck %s ; hfinkel's case ; [entry] Index: test/Transforms/Util/MemorySSA/multiple-locations.ll =================================================================== --- test/Transforms/Util/MemorySSA/multiple-locations.ll +++ test/Transforms/Util/MemorySSA/multiple-locations.ll @@ -1,4 +1,5 @@ ; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa -passes='print' -verify-memoryssa -disable-output < %s 2>&1 | FileCheck %s ; ; Checks that basicAA is doing some amount of disambiguation for us Index: test/Transforms/Util/MemorySSA/no-disconnected.ll =================================================================== --- test/Transforms/Util/MemorySSA/no-disconnected.ll +++ test/Transforms/Util/MemorySSA/no-disconnected.ll @@ -1,4 +1,5 @@ ; RUN: opt -basicaa -print-memoryssa -analyze -verify-memoryssa < %s 2>&1 | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa -passes='print' -verify-memoryssa -disable-output < %s 2>&1 | FileCheck %s ; ; This test ensures we don't end up with multiple reaching defs for a single ; use/phi edge If we were to optimize defs, we would end up with 2= Index: test/Transforms/Util/MemorySSA/optimize-use.ll =================================================================== --- test/Transforms/Util/MemorySSA/optimize-use.ll +++ test/Transforms/Util/MemorySSA/optimize-use.ll @@ -1,4 +1,5 @@ ; RUN: opt -basicaa -print-memoryssa -analyze -verify-memoryssa < %s 2>&1 | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa -passes='print' -verify-memoryssa -disable-output < %s 2>&1 | FileCheck %s ; Function Attrs: ssp uwtable define i32 @main() { Index: test/Transforms/Util/MemorySSA/phi-translation.ll =================================================================== --- test/Transforms/Util/MemorySSA/phi-translation.ll +++ test/Transforms/Util/MemorySSA/phi-translation.ll @@ -1,4 +1,5 @@ ; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa -passes='print' -verify-memoryssa -disable-output < %s 2>&1 | FileCheck %s ; %ptr can't alias %local, so we should be able to optimize the use of %local to ; point to the store to %local. Index: test/Transforms/Util/MemorySSA/volatile-clobber.ll =================================================================== --- test/Transforms/Util/MemorySSA/volatile-clobber.ll +++ test/Transforms/Util/MemorySSA/volatile-clobber.ll @@ -1,4 +1,5 @@ ; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa -passes='print' -verify-memoryssa -disable-output < %s 2>&1 | FileCheck %s ; ; Ensures that volatile stores/loads count as MemoryDefs