Index: include/llvm/Transforms/Utils/MemorySSA.h =================================================================== --- include/llvm/Transforms/Utils/MemorySSA.h +++ include/llvm/Transforms/Utils/MemorySSA.h @@ -539,7 +539,8 @@ /// accesses. class MemorySSA { public: - MemorySSA(Function &, AliasAnalysis *, DominatorTree *); + MemorySSA(Function &, AliasAnalysis *, DominatorTree *, + bool OptimizeUses = true); ~MemorySSA(); MemorySSAWalker *getWalker(); @@ -659,7 +660,7 @@ class OptimizeUses; CachingWalker *getWalkerImpl(); - void buildMemorySSA(); + void buildMemorySSA(bool OptimizeUses); void optimizeUses(); void verifyUseInDefs(MemoryAccess *, MemoryAccess *) const; Index: lib/Transforms/Utils/MemorySSA.cpp =================================================================== --- lib/Transforms/Utils/MemorySSA.cpp +++ lib/Transforms/Utils/MemorySSA.cpp @@ -1254,10 +1254,11 @@ } } -MemorySSA::MemorySSA(Function &Func, AliasAnalysis *AA, DominatorTree *DT) +MemorySSA::MemorySSA(Function &Func, AliasAnalysis *AA, DominatorTree *DT, + bool OptimizeUses) : AA(AA), DT(DT), F(Func), LiveOnEntryDef(nullptr), Walker(nullptr), NextID(INVALID_MEMORYACCESS_ID) { - buildMemorySSA(); + buildMemorySSA(OptimizeUses); } MemorySSA::~MemorySSA() { @@ -1512,7 +1513,7 @@ createMemoryPhi(BB); } -void MemorySSA::buildMemorySSA() { +void MemorySSA::buildMemorySSA(bool DoOptimizeUses) { // We create an access to represent "live on entry", for things like // arguments or users of globals, where the memory they use is defined before // the beginning of the function. We do not actually insert it into the IR. @@ -1568,7 +1569,8 @@ // We're doing a batch of updates; don't drop useful caches between them. Walker->setAutoResetWalker(false); - OptimizeUses(this, Walker, AA, DT).optimizeUses(); + if (DoOptimizeUses) + OptimizeUses(this, Walker, AA, DT).optimizeUses(); Walker->setAutoResetWalker(true); Walker->resetClobberWalker(); Index: unittests/Transforms/Utils/MemorySSA.cpp =================================================================== --- unittests/Transforms/Utils/MemorySSA.cpp +++ unittests/Transforms/Utils/MemorySSA.cpp @@ -48,20 +48,20 @@ std::unique_ptr MSSA; MemorySSAWalker *Walker; - TestAnalyses(MemorySSATest &Test) + TestAnalyses(MemorySSATest &Test, bool OptimizeMSSAUses) : DT(*Test.F), AC(*Test.F), AA(Test.TLI), BAA(Test.DL, Test.TLI, AC, &DT) { AA.addAAResult(BAA); - MSSA = make_unique(*Test.F, &AA, &DT); + MSSA = make_unique(*Test.F, &AA, &DT, OptimizeMSSAUses); Walker = MSSA->getWalker(); } }; std::unique_ptr Analyses; - void setupAnalyses() { + void setupAnalyses(bool OptimizeMSSAUses = true) { assert(F); - Analyses.reset(new TestAnalyses(*this)); + Analyses.reset(new TestAnalyses(*this, OptimizeMSSAUses)); } public: @@ -712,11 +712,8 @@ EXPECT_EQ(UseClobber, MSSA.getMemoryAccess(FirstStore)); } -// Test that our walker properly handles loads with the invariant group -// attribute. It's a bit hacky, since we add the invariant attribute *after* -// building MSSA. Otherwise, the use optimizer will optimize it for us, which -// isn't what we want. -// FIXME: It may be easier/cleaner to just add an 'optimize uses?' flag to MSSA. +// Test that our walker properly handles loads with the `invariant.load` +// attribute. TEST_F(MemorySSATest, WalkerInvariantLoadOpt) { F = Function::Create(FunctionType::get(B.getVoidTy(), {}, false), GlobalValue::ExternalLinkage, "F", &M); @@ -727,8 +724,9 @@ Instruction *Store = B.CreateStore(One, AllocA); Instruction *Load = B.CreateLoad(AllocA); + Load->setMetadata(LLVMContext::MD_invariant_load, MDNode::get(C, {})); - setupAnalyses(); + setupAnalyses(/*OptimizeMSSAUses*/ false); MemorySSA &MSSA = *Analyses->MSSA; MemorySSAWalker *Walker = Analyses->Walker; @@ -739,7 +737,6 @@ // ...At the time of writing, no cache should exist for LoadMA. Be a bit // flexible to future changes. Walker->invalidateInfo(LoadMA); - Load->setMetadata(LLVMContext::MD_invariant_load, MDNode::get(C, {})); MemoryAccess *LoadClobber = Walker->getClobberingMemoryAccess(LoadMA); EXPECT_EQ(LoadClobber, MSSA.getLiveOnEntryDef());