diff --git a/llvm/include/llvm/Analysis/MemorySSA.h b/llvm/include/llvm/Analysis/MemorySSA.h --- a/llvm/include/llvm/Analysis/MemorySSA.h +++ b/llvm/include/llvm/Analysis/MemorySSA.h @@ -735,6 +735,15 @@ void dump() const; void print(raw_ostream &) const; + // Return true if the *approximate* number of accesses seen by MemorySSA for + // the current function is prohibitively large. + // + // This information can be used to limit optimizations that need to update + // MemorySSA for IRs with pathological patterns. + // FIXME: A better informative number would be the number of Defs, but this + // is currently only targetting extreme cases. Revisit if the usecases change. + bool prohibitivelyLargeNumberOfAccesses() const; + /// Return true if \p MA represents the live on entry value /// /// Loads and stores from pointer arguments and other global values may be diff --git a/llvm/lib/Analysis/MemorySSA.cpp b/llvm/lib/Analysis/MemorySSA.cpp --- a/llvm/lib/Analysis/MemorySSA.cpp +++ b/llvm/lib/Analysis/MemorySSA.cpp @@ -95,6 +95,12 @@ "enable-mssa-loop-dependency", cl::Hidden, cl::init(true), cl::desc("Enable MemorySSA dependency for loop pass manager")); +static cl::opt ProhibitivelyLargeAccessNo( + "memssa-prohibitively-large-access-no", cl::Hidden, cl::init(100000), + cl::desc("The number of accesses seen in a function by MemorySSA, past" + "which optimizations should consider updates to MemorySSA to be" + "prohibitively expensive (default = 100000)")); + static cl::opt VerifyMemorySSAX("verify-memoryssa", cl::location(VerifyMemorySSA), cl::Hidden, cl::desc("Enable verification of MemorySSA.")); @@ -1864,6 +1870,10 @@ LLVM_DUMP_METHOD void MemorySSA::dump() const { print(dbgs()); } #endif +bool MemorySSA::prohibitivelyLargeNumberOfAccesses() const { + return NextID > ProhibitivelyLargeAccessNo; +} + void MemorySSA::verifyMemorySSA() const { verifyOrderingDominationAndDefUses(F); verifyDominationNumbers(F); diff --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp --- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp +++ b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp @@ -1760,6 +1760,10 @@ if (!TLI->has(LibFunc_memset) || !TLI->has(LibFunc_memcpy)) return false; + // If the number of memory accesses is prohibitively large, skip the pass. + if (MSSA && MSSA->prohibitivelyLargeNumberOfAccesses()) + return false; + while (true) { if (!iterateOnFunction(F)) break;