From eddb810ffd5499f0984123fe4bfea6064ebad3c8 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 3 Nov 2022 07:18:33 +0000 Subject: [PATCH] Bug 1798840 - Revert clang trunk change that heavily breaks Firefox. Differential Revision: https://phabricator.services.mozilla.com/D161112 --- build/build-clang/clang-trunk.json | 1 + ...t-llvmorg-16-init-9324-g01859da84bad.patch | 869 ++++++++++++++++++ 2 files changed, 870 insertions(+) create mode 100644 build/build-clang/revert-llvmorg-16-init-9324-g01859da84bad.patch diff --git a/build/build-clang/clang-trunk.json b/build/build-clang/clang-trunk.json index 4b2ec7a81453..b52978ef8e53 100644 --- a/build/build-clang/clang-trunk.json +++ b/build/build-clang/clang-trunk.json @@ -7,6 +7,7 @@ "bug47258-extract-symbols-mbcs.patch", "fuzzing_ccov_build_clang_12.patch", "win64-no-symlink_clang_16.patch", + "revert-llvmorg-16-init-9324-g01859da84bad.patch", "revert-llvmorg-16-init-8201-ge0fb01e97b6b.patch", "revert-llvmorg-16-init-7694-g19e984ef8f49.patch", "revert-llvmorg-16-init-7598-g54bfd0484615.patch", diff --git a/build/build-clang/revert-llvmorg-16-init-9324-g01859da84bad.patch b/build/build-clang/revert-llvmorg-16-init-9324-g01859da84bad.patch new file mode 100644 index 000000000000..73ee827ab56b --- /dev/null +++ b/build/build-clang/revert-llvmorg-16-init-9324-g01859da84bad.patch @@ -0,0 +1,869 @@ +From 4ebea86ddf20d3f9be3cb363eed3f313591bee66 Mon Sep 17 00:00:00 2001 +From: Mike Hommey +Date: Thu, 3 Nov 2022 13:54:08 +0900 +Subject: [PATCH] Revert "[AliasAnalysis] Introduce getModRefInfoMask() as a + generalization of pointsToConstantMemory()." + +This reverts commit 01859da84bad95fd51d6a03b08b60c660e642a4f +for causing https://github.com/llvm/llvm-project/issues/58776 +--- + llvm/docs/AliasAnalysis.rst | 26 +++----- + llvm/include/llvm/Analysis/AliasAnalysis.h | 51 ++++----------- + .../llvm/Analysis/BasicAliasAnalysis.h | 12 +--- + .../llvm/Analysis/ObjCARCAliasAnalysis.h | 4 +- + .../llvm/Analysis/TypeBasedAliasAnalysis.h | 4 +- + llvm/lib/Analysis/AliasAnalysis.cpp | 63 +++++++++---------- + llvm/lib/Analysis/BasicAliasAnalysis.cpp | 43 ++++--------- + .../lib/Analysis/MemoryDependenceAnalysis.cpp | 2 +- + llvm/lib/Analysis/MemorySSA.cpp | 5 +- + llvm/lib/Analysis/ObjCARCAliasAnalysis.cpp | 19 +++--- + llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp | 14 ++--- + .../lib/Target/AMDGPU/AMDGPUAliasAnalysis.cpp | 47 ++++++++++++-- + llvm/lib/Target/AMDGPU/AMDGPUAliasAnalysis.h | 4 +- + llvm/lib/Transforms/IPO/FunctionAttrs.cpp | 7 +-- + .../InstCombine/InstCombineCalls.cpp | 4 +- + .../InstCombineLoadStoreAlloca.cpp | 33 +++++----- + llvm/lib/Transforms/Scalar/LICM.cpp | 2 +- + .../lib/Transforms/Scalar/LoopPredication.cpp | 2 +- + llvm/test/Analysis/BasicAA/constant-memory.ll | 14 +++-- + .../InstCombine/memcpy-from-global.ll | 6 +- + llvm/test/Transforms/InstCombine/store.ll | 4 +- + 21 files changed, 168 insertions(+), 198 deletions(-) + +diff --git a/llvm/docs/AliasAnalysis.rst b/llvm/docs/AliasAnalysis.rst +index 046dd24d7332..b9a8a3a4eb52 100644 +--- a/llvm/docs/AliasAnalysis.rst ++++ b/llvm/docs/AliasAnalysis.rst +@@ -161,24 +161,14 @@ Other useful ``AliasAnalysis`` methods + Several other tidbits of information are often collected by various alias + analysis implementations and can be put to good use by various clients. + +-The ``getModRefInfoMask`` method +-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- +-The ``getModRefInfoMask`` method returns a bound on Mod/Ref information for +-the supplied pointer, based on knowledge about whether the pointer points to +-globally-constant memory (for which it returns ``NoModRef``) or +-locally-invariant memory (for which it returns ``Ref``). Globally-constant +-memory includes functions, constant global variables, and the null pointer. +-Locally-invariant memory is memory that we know is invariant for the lifetime +-of its SSA value, but not necessarily for the life of the program: for example, +-the memory pointed to by ``readonly`` ``noalias`` parameters is known-invariant +-for the duration of the corresponding function call. Given Mod/Ref information +-``MRI`` for a memory location ``Loc``, ``MRI`` can be refined with a statement +-like ``MRI &= AA.getModRefInfoMask(Loc);``. Another useful idiom is +-``isModSet(AA.getModRefInfoMask(Loc))``; this checks to see if the given +-location can be modified at all. For convenience, there is also a method +-``pointsToConstantMemory(Loc)``; this is synonymous with +-``isNoModRef(AA.getModRefInfoMask(Loc))``. ++The ``pointsToConstantMemory`` method ++^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++ ++The ``pointsToConstantMemory`` method returns true if and only if the analysis ++can prove that the pointer only points to unchanging memory locations ++(functions, constant global variables, and the null pointer). This information ++can be used to refine mod/ref information: it is impossible for an unchanging ++memory location to be modified. + + .. _never access memory or only read memory: + +diff --git a/llvm/include/llvm/Analysis/AliasAnalysis.h b/llvm/include/llvm/Analysis/AliasAnalysis.h +index a6c7da910121..a2d65e53810a 100644 +--- a/llvm/include/llvm/Analysis/AliasAnalysis.h ++++ b/llvm/include/llvm/Analysis/AliasAnalysis.h +@@ -359,9 +359,7 @@ public: + + /// Checks whether the given location points to constant memory, or if + /// \p OrLocal is true whether it points to a local alloca. +- bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal = false) { +- return isNoModRef(getModRefInfoMask(Loc, OrLocal)); +- } ++ bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal = false); + + /// A convenience wrapper around the primary \c pointsToConstantMemory + /// interface. +@@ -374,22 +372,6 @@ public: + /// \name Simple mod/ref information + /// @{ + +- /// Returns a bitmask that should be unconditionally applied to the ModRef +- /// info of a memory location. This allows us to eliminate Mod and/or Ref +- /// from the ModRef info based on the knowledge that the memory location +- /// points to constant and/or locally-invariant memory. +- /// +- /// If IgnoreLocals is true, then this method returns NoModRef for memory +- /// that points to a local alloca. +- ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, +- bool IgnoreLocals = false); +- +- /// A convenience wrapper around the primary \c getModRefInfoMask +- /// interface. +- ModRefInfo getModRefInfoMask(const Value *P, bool IgnoreLocals = false) { +- return getModRefInfoMask(MemoryLocation::getBeforeOrAfter(P), IgnoreLocals); +- } +- + /// Get the ModRef info associated with a pointer argument of a call. The + /// result's bits are set to indicate the allowed aliasing ModRef kinds. Note + /// that these bits do not necessarily account for the overall behavior of +@@ -536,8 +518,6 @@ public: + AAQueryInfo &AAQI); + bool pointsToConstantMemory(const MemoryLocation &Loc, AAQueryInfo &AAQI, + bool OrLocal = false); +- ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, AAQueryInfo &AAQI, +- bool IgnoreLocals = false); + ModRefInfo getModRefInfo(const Instruction *I, const CallBase *Call2, + AAQueryInfo &AAQIP); + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, +@@ -605,10 +585,6 @@ public: + bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal = false) { + return AA.pointsToConstantMemory(Loc, AAQI, OrLocal); + } +- ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, +- bool IgnoreLocals = false) { +- return AA.getModRefInfoMask(Loc, AAQI, IgnoreLocals); +- } + ModRefInfo getModRefInfo(const Instruction *I, + const Optional &OptLoc) { + return AA.getModRefInfo(I, OptLoc, AAQI); +@@ -665,19 +641,16 @@ public: + virtual AliasResult alias(const MemoryLocation &LocA, + const MemoryLocation &LocB, AAQueryInfo &AAQI) = 0; + ++ /// Checks whether the given location points to constant memory, or if ++ /// \p OrLocal is true whether it points to a local alloca. ++ virtual bool pointsToConstantMemory(const MemoryLocation &Loc, ++ AAQueryInfo &AAQI, bool OrLocal) = 0; ++ + /// @} + //===--------------------------------------------------------------------===// + /// \name Simple mod/ref information + /// @{ + +- /// Returns a bitmask that should be unconditionally applied to the ModRef +- /// info of a memory location. This allows us to eliminate Mod and/or Ref from +- /// the ModRef info based on the knowledge that the memory location points to +- /// constant and/or locally-invariant memory. +- virtual ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, +- AAQueryInfo &AAQI, +- bool IgnoreLocals) = 0; +- + /// Get the ModRef info associated with a pointer argument of a callsite. The + /// result's bits are set to indicate the allowed aliasing ModRef kinds. Note + /// that these bits do not necessarily account for the overall behavior of +@@ -726,9 +699,9 @@ public: + return Result.alias(LocA, LocB, AAQI); + } + +- ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, AAQueryInfo &AAQI, +- bool IgnoreLocals) override { +- return Result.getModRefInfoMask(Loc, AAQI, IgnoreLocals); ++ bool pointsToConstantMemory(const MemoryLocation &Loc, AAQueryInfo &AAQI, ++ bool OrLocal) override { ++ return Result.pointsToConstantMemory(Loc, AAQI, OrLocal); + } + + ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) override { +@@ -781,9 +754,9 @@ public: + return AliasResult::MayAlias; + } + +- ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, AAQueryInfo &AAQI, +- bool IgnoreLocals) { +- return ModRefInfo::ModRef; ++ bool pointsToConstantMemory(const MemoryLocation &Loc, AAQueryInfo &AAQI, ++ bool OrLocal) { ++ return false; + } + + ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) { +diff --git a/llvm/include/llvm/Analysis/BasicAliasAnalysis.h b/llvm/include/llvm/Analysis/BasicAliasAnalysis.h +index a2909f46e3ba..8f4a8d4a8d8b 100644 +--- a/llvm/include/llvm/Analysis/BasicAliasAnalysis.h ++++ b/llvm/include/llvm/Analysis/BasicAliasAnalysis.h +@@ -75,15 +75,9 @@ public: + ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2, + AAQueryInfo &AAQI); + +- /// Returns a bitmask that should be unconditionally applied to the ModRef +- /// info of a memory location. This allows us to eliminate Mod and/or Ref +- /// from the ModRef info based on the knowledge that the memory location +- /// points to constant and/or locally-invariant memory. +- /// +- /// If IgnoreLocals is true, then this method returns NoModRef for memory +- /// that points to a local alloca. +- ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, AAQueryInfo &AAQI, +- bool IgnoreLocals = false); ++ /// Chases pointers until we find a (constant global) or not. ++ bool pointsToConstantMemory(const MemoryLocation &Loc, AAQueryInfo &AAQI, ++ bool OrLocal); + + /// Get the location associated with a pointer argument of a callsite. + ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx); +diff --git a/llvm/include/llvm/Analysis/ObjCARCAliasAnalysis.h b/llvm/include/llvm/Analysis/ObjCARCAliasAnalysis.h +index 790fbaf07e7f..ba8b28a5adda 100644 +--- a/llvm/include/llvm/Analysis/ObjCARCAliasAnalysis.h ++++ b/llvm/include/llvm/Analysis/ObjCARCAliasAnalysis.h +@@ -52,8 +52,8 @@ public: + + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, + AAQueryInfo &AAQI); +- ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, AAQueryInfo &AAQI, +- bool IgnoreLocals); ++ bool pointsToConstantMemory(const MemoryLocation &Loc, AAQueryInfo &AAQI, ++ bool OrLocal); + + using AAResultBase::getMemoryEffects; + MemoryEffects getMemoryEffects(const Function *F); +diff --git a/llvm/include/llvm/Analysis/TypeBasedAliasAnalysis.h b/llvm/include/llvm/Analysis/TypeBasedAliasAnalysis.h +index 791ec65990e2..2e7af99ed495 100644 +--- a/llvm/include/llvm/Analysis/TypeBasedAliasAnalysis.h ++++ b/llvm/include/llvm/Analysis/TypeBasedAliasAnalysis.h +@@ -40,8 +40,8 @@ public: + + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, + AAQueryInfo &AAQI); +- ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, AAQueryInfo &AAQI, +- bool IgnoreLocals); ++ bool pointsToConstantMemory(const MemoryLocation &Loc, AAQueryInfo &AAQI, ++ bool OrLocal); + MemoryEffects getMemoryEffects(const CallBase *Call, AAQueryInfo &AAQI); + MemoryEffects getMemoryEffects(const Function *F); + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, +diff --git a/llvm/lib/Analysis/AliasAnalysis.cpp b/llvm/lib/Analysis/AliasAnalysis.cpp +index 4f27acade05a..6b8ad367b54e 100644 +--- a/llvm/lib/Analysis/AliasAnalysis.cpp ++++ b/llvm/lib/Analysis/AliasAnalysis.cpp +@@ -147,25 +147,19 @@ AliasResult AAResults::alias(const MemoryLocation &LocA, + return Result; + } + +-ModRefInfo AAResults::getModRefInfoMask(const MemoryLocation &Loc, +- bool IgnoreLocals) { ++bool AAResults::pointsToConstantMemory(const MemoryLocation &Loc, ++ bool OrLocal) { + SimpleAAQueryInfo AAQIP(*this); +- return getModRefInfoMask(Loc, AAQIP, IgnoreLocals); ++ return pointsToConstantMemory(Loc, AAQIP, OrLocal); + } + +-ModRefInfo AAResults::getModRefInfoMask(const MemoryLocation &Loc, +- AAQueryInfo &AAQI, bool IgnoreLocals) { +- ModRefInfo Result = ModRefInfo::ModRef; +- +- for (const auto &AA : AAs) { +- Result &= AA->getModRefInfoMask(Loc, AAQI, IgnoreLocals); +- +- // Early-exit the moment we reach the bottom of the lattice. +- if (isNoModRef(Result)) +- return ModRefInfo::NoModRef; +- } ++bool AAResults::pointsToConstantMemory(const MemoryLocation &Loc, ++ AAQueryInfo &AAQI, bool OrLocal) { ++ for (const auto &AA : AAs) ++ if (AA->pointsToConstantMemory(Loc, AAQI, OrLocal)) ++ return true; + +- return Result; ++ return false; + } + + ModRefInfo AAResults::getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) { +@@ -254,11 +248,10 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call, + + Result &= ArgMR | OtherMR; + +- // Apply the ModRef mask. This ensures that if Loc is a constant memory +- // location, we take into account the fact that the call definitely could not ++ // If Loc is a constant memory location, the call definitely could not + // modify the memory location. +- if (!isNoModRef(Result)) +- Result &= getModRefInfoMask(Loc); ++ if (isModSet(Result) && pointsToConstantMemory(Loc, AAQI, /*OrLocal*/ false)) ++ Result &= ModRefInfo::Ref; + + return Result; + } +@@ -496,11 +489,9 @@ ModRefInfo AAResults::getModRefInfo(const StoreInst *S, + if (AR == AliasResult::NoAlias) + return ModRefInfo::NoModRef; + +- // Examine the ModRef mask. If Mod isn't present, then return NoModRef. +- // This ensures that if Loc is a constant memory location, we take into +- // account the fact that the store definitely could not modify the memory +- // location. +- if (!isModSet(getModRefInfoMask(Loc))) ++ // If the pointer is a pointer to constant memory, then it could not have ++ // been modified by this store. ++ if (pointsToConstantMemory(Loc, AAQI)) + return ModRefInfo::NoModRef; + } + +@@ -511,11 +502,10 @@ ModRefInfo AAResults::getModRefInfo(const StoreInst *S, + ModRefInfo AAResults::getModRefInfo(const FenceInst *S, + const MemoryLocation &Loc, + AAQueryInfo &AAQI) { +- // All we know about a fence instruction is what we get from the ModRef +- // mask: if Loc is a constant memory location, the fence definitely could +- // not modify it. +- if (Loc.Ptr) +- return getModRefInfoMask(Loc); ++ // If we know that the location is a constant memory location, the fence ++ // cannot modify this location. ++ if (Loc.Ptr && pointsToConstantMemory(Loc, AAQI)) ++ return ModRefInfo::Ref; + return ModRefInfo::ModRef; + } + +@@ -529,9 +519,10 @@ ModRefInfo AAResults::getModRefInfo(const VAArgInst *V, + if (AR == AliasResult::NoAlias) + return ModRefInfo::NoModRef; + +- // If the pointer is a pointer to invariant memory, then it could not have ++ // If the pointer is a pointer to constant memory, then it could not have + // been modified by this va_arg. +- return getModRefInfoMask(Loc, AAQI); ++ if (pointsToConstantMemory(Loc, AAQI)) ++ return ModRefInfo::NoModRef; + } + + // Otherwise, a va_arg reads and writes. +@@ -542,9 +533,10 @@ ModRefInfo AAResults::getModRefInfo(const CatchPadInst *CatchPad, + const MemoryLocation &Loc, + AAQueryInfo &AAQI) { + if (Loc.Ptr) { +- // If the pointer is a pointer to invariant memory, ++ // If the pointer is a pointer to constant memory, + // then it could not have been modified by this catchpad. +- return getModRefInfoMask(Loc, AAQI); ++ if (pointsToConstantMemory(Loc, AAQI)) ++ return ModRefInfo::NoModRef; + } + + // Otherwise, a catchpad reads and writes. +@@ -555,9 +547,10 @@ ModRefInfo AAResults::getModRefInfo(const CatchReturnInst *CatchRet, + const MemoryLocation &Loc, + AAQueryInfo &AAQI) { + if (Loc.Ptr) { +- // If the pointer is a pointer to invariant memory, ++ // If the pointer is a pointer to constant memory, + // then it could not have been modified by this catchpad. +- return getModRefInfoMask(Loc, AAQI); ++ if (pointsToConstantMemory(Loc, AAQI)) ++ return ModRefInfo::NoModRef; + } + + // Otherwise, a catchret reads and writes. +diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp +index 2bbc2486fec0..fa03a82f78b2 100644 +--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp ++++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp +@@ -676,46 +676,33 @@ BasicAAResult::DecomposeGEPExpression(const Value *V, const DataLayout &DL, + return Decomposed; + } + +-ModRefInfo BasicAAResult::getModRefInfoMask(const MemoryLocation &Loc, +- AAQueryInfo &AAQI, +- bool IgnoreLocals) { ++/// Returns whether the given pointer value points to memory that is local to ++/// the function, with global constants being considered local to all ++/// functions. ++bool BasicAAResult::pointsToConstantMemory(const MemoryLocation &Loc, ++ AAQueryInfo &AAQI, bool OrLocal) { + assert(Visited.empty() && "Visited must be cleared after use!"); +- auto _ = make_scope_exit([&] { Visited.clear(); }); ++ auto _ = make_scope_exit([&]{ Visited.clear(); }); + + unsigned MaxLookup = 8; + SmallVector Worklist; + Worklist.push_back(Loc.Ptr); +- ModRefInfo Result = ModRefInfo::NoModRef; +- + do { + const Value *V = getUnderlyingObject(Worklist.pop_back_val()); + if (!Visited.insert(V).second) + continue; + +- // Ignore allocas if we were instructed to do so. +- if (IgnoreLocals && isa(V)) ++ // An alloca instruction defines local memory. ++ if (OrLocal && isa(V)) + continue; + +- // If the location points to memory that is known to be invariant for +- // the life of the underlying SSA value, then we can exclude Mod from +- // the set of valid memory effects. +- // +- // An argument that is marked readonly and noalias is known to be +- // invariant while that function is executing. +- if (const Argument *Arg = dyn_cast(V)) { +- if (Arg->hasNoAliasAttr() && Arg->onlyReadsMemory()) { +- Result |= ModRefInfo::Ref; +- continue; +- } +- } +- +- // A global constant can't be mutated. ++ // A global constant counts as local memory for our purposes. + if (const GlobalVariable *GV = dyn_cast(V)) { + // Note: this doesn't require GV to be "ODR" because it isn't legal for a + // global to be marked constant in some modules and non-constant in + // others. GV may even be a declaration, not a definition. + if (!GV->isConstant()) +- return AAResultBase::getModRefInfoMask(Loc, AAQI, IgnoreLocals); ++ return AAResultBase::pointsToConstantMemory(Loc, AAQI, OrLocal); + continue; + } + +@@ -731,20 +718,16 @@ ModRefInfo BasicAAResult::getModRefInfoMask(const MemoryLocation &Loc, + if (const PHINode *PN = dyn_cast(V)) { + // Don't bother inspecting phi nodes with many operands. + if (PN->getNumIncomingValues() > MaxLookup) +- return AAResultBase::getModRefInfoMask(Loc, AAQI, IgnoreLocals); ++ return AAResultBase::pointsToConstantMemory(Loc, AAQI, OrLocal); + append_range(Worklist, PN->incoming_values()); + continue; + } + + // Otherwise be conservative. +- return AAResultBase::getModRefInfoMask(Loc, AAQI, IgnoreLocals); ++ return AAResultBase::pointsToConstantMemory(Loc, AAQI, OrLocal); + } while (!Worklist.empty() && --MaxLookup); + +- // If we hit the maximum number of instructions to examine, be conservative. +- if (!Worklist.empty()) +- return AAResultBase::getModRefInfoMask(Loc, AAQI, IgnoreLocals); +- +- return Result; ++ return Worklist.empty(); + } + + static bool isIntrinsicCall(const CallBase *Call, Intrinsic::ID IID) { +diff --git a/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp b/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp +index f0446b21e288..d9bae54b05be 100644 +--- a/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp ++++ b/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp +@@ -525,7 +525,7 @@ MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom( + } + + // Stores don't alias loads from read-only memory. +- if (!isModSet(BatchAA.getModRefInfoMask(LoadLoc))) ++ if (BatchAA.pointsToConstantMemory(LoadLoc)) + continue; + + // Stores depend on may/must aliased loads. +diff --git a/llvm/lib/Analysis/MemorySSA.cpp b/llvm/lib/Analysis/MemorySSA.cpp +index 1660321990bf..461886650261 100644 +--- a/llvm/lib/Analysis/MemorySSA.cpp ++++ b/llvm/lib/Analysis/MemorySSA.cpp +@@ -378,10 +378,9 @@ static bool isUseTriviallyOptimizableToLiveOnEntry(AliasAnalysisType &AA, + const Instruction *I) { + // If the memory can't be changed, then loads of the memory can't be + // clobbered. +- if (auto *LI = dyn_cast(I)) { ++ if (auto *LI = dyn_cast(I)) + return I->hasMetadata(LLVMContext::MD_invariant_load) || +- !isModSet(AA.getModRefInfoMask(MemoryLocation::get(LI))); +- } ++ AA.pointsToConstantMemory(MemoryLocation::get(LI)); + return false; + } + +diff --git a/llvm/lib/Analysis/ObjCARCAliasAnalysis.cpp b/llvm/lib/Analysis/ObjCARCAliasAnalysis.cpp +index 93d56931d01c..76f6a74384b4 100644 +--- a/llvm/lib/Analysis/ObjCARCAliasAnalysis.cpp ++++ b/llvm/lib/Analysis/ObjCARCAliasAnalysis.cpp +@@ -68,29 +68,28 @@ AliasResult ObjCARCAAResult::alias(const MemoryLocation &LocA, + return AliasResult::MayAlias; + } + +-ModRefInfo ObjCARCAAResult::getModRefInfoMask(const MemoryLocation &Loc, +- AAQueryInfo &AAQI, +- bool IgnoreLocals) { ++bool ObjCARCAAResult::pointsToConstantMemory(const MemoryLocation &Loc, ++ AAQueryInfo &AAQI, bool OrLocal) { + if (!EnableARCOpts) +- return AAResultBase::getModRefInfoMask(Loc, AAQI, IgnoreLocals); ++ return AAResultBase::pointsToConstantMemory(Loc, AAQI, OrLocal); + + // First, strip off no-ops, including ObjC-specific no-ops, and try making + // a precise alias query. + const Value *S = GetRCIdentityRoot(Loc.Ptr); +- if (isNoModRef(AAResultBase::getModRefInfoMask( +- MemoryLocation(S, Loc.Size, Loc.AATags), AAQI, IgnoreLocals))) +- return ModRefInfo::NoModRef; ++ if (AAResultBase::pointsToConstantMemory( ++ MemoryLocation(S, Loc.Size, Loc.AATags), AAQI, OrLocal)) ++ return true; + + // If that failed, climb to the underlying object, including climbing through + // ObjC-specific no-ops, and try making an imprecise alias query. + const Value *U = GetUnderlyingObjCPtr(S); + if (U != S) +- return AAResultBase::getModRefInfoMask(MemoryLocation::getBeforeOrAfter(U), +- AAQI, IgnoreLocals); ++ return AAResultBase::pointsToConstantMemory( ++ MemoryLocation::getBeforeOrAfter(U), AAQI, OrLocal); + + // If that failed, fail. We don't need to chain here, since that's covered + // by the earlier precise query. +- return ModRefInfo::ModRef; ++ return false; + } + + MemoryEffects ObjCARCAAResult::getMemoryEffects(const Function *F) { +diff --git a/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp b/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp +index b7121ea8326b..8360246915e4 100644 +--- a/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp ++++ b/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp +@@ -385,23 +385,23 @@ AliasResult TypeBasedAAResult::alias(const MemoryLocation &LocA, + return AliasResult::NoAlias; + } + +-ModRefInfo TypeBasedAAResult::getModRefInfoMask(const MemoryLocation &Loc, +- AAQueryInfo &AAQI, +- bool IgnoreLocals) { ++bool TypeBasedAAResult::pointsToConstantMemory(const MemoryLocation &Loc, ++ AAQueryInfo &AAQI, ++ bool OrLocal) { + if (!EnableTBAA) +- return AAResultBase::getModRefInfoMask(Loc, AAQI, IgnoreLocals); ++ return AAResultBase::pointsToConstantMemory(Loc, AAQI, OrLocal); + + const MDNode *M = Loc.AATags.TBAA; + if (!M) +- return AAResultBase::getModRefInfoMask(Loc, AAQI, IgnoreLocals); ++ return AAResultBase::pointsToConstantMemory(Loc, AAQI, OrLocal); + + // If this is an "immutable" type, we can assume the pointer is pointing + // to constant memory. + if ((!isStructPathTBAA(M) && TBAANode(M).isTypeImmutable()) || + (isStructPathTBAA(M) && TBAAStructTagNode(M).isTypeImmutable())) +- return ModRefInfo::NoModRef; ++ return true; + +- return AAResultBase::getModRefInfoMask(Loc, AAQI, IgnoreLocals); ++ return AAResultBase::pointsToConstantMemory(Loc, AAQI, OrLocal); + } + + MemoryEffects TypeBasedAAResult::getMemoryEffects(const CallBase *Call, +diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAliasAnalysis.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAliasAnalysis.cpp +index e97c993f4b25..dd3eb3849eac 100644 +--- a/llvm/lib/Target/AMDGPU/AMDGPUAliasAnalysis.cpp ++++ b/llvm/lib/Target/AMDGPU/AMDGPUAliasAnalysis.cpp +@@ -124,19 +124,54 @@ AliasResult AMDGPUAAResult::alias(const MemoryLocation &LocA, + return AAResultBase::alias(LocA, LocB, AAQI); + } + +-ModRefInfo AMDGPUAAResult::getModRefInfoMask(const MemoryLocation &Loc, +- AAQueryInfo &AAQI, +- bool IgnoreLocals) { ++bool AMDGPUAAResult::pointsToConstantMemory(const MemoryLocation &Loc, ++ AAQueryInfo &AAQI, bool OrLocal) { + unsigned AS = Loc.Ptr->getType()->getPointerAddressSpace(); + if (AS == AMDGPUAS::CONSTANT_ADDRESS || + AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT) +- return ModRefInfo::NoModRef; ++ return true; + + const Value *Base = getUnderlyingObject(Loc.Ptr); + AS = Base->getType()->getPointerAddressSpace(); + if (AS == AMDGPUAS::CONSTANT_ADDRESS || + AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT) +- return ModRefInfo::NoModRef; ++ return true; ++ ++ if (const GlobalVariable *GV = dyn_cast(Base)) { ++ if (GV->isConstant()) ++ return true; ++ } else if (const Argument *Arg = dyn_cast(Base)) { ++ const Function *F = Arg->getParent(); ++ ++ // Only assume constant memory for arguments on kernels. ++ switch (F->getCallingConv()) { ++ default: ++ return AAResultBase::pointsToConstantMemory(Loc, AAQI, OrLocal); ++ case CallingConv::AMDGPU_LS: ++ case CallingConv::AMDGPU_HS: ++ case CallingConv::AMDGPU_ES: ++ case CallingConv::AMDGPU_GS: ++ case CallingConv::AMDGPU_VS: ++ case CallingConv::AMDGPU_PS: ++ case CallingConv::AMDGPU_CS: ++ case CallingConv::AMDGPU_KERNEL: ++ case CallingConv::SPIR_KERNEL: ++ break; ++ } + +- return AAResultBase::getModRefInfoMask(Loc, AAQI, IgnoreLocals); ++ unsigned ArgNo = Arg->getArgNo(); ++ /* On an argument, ReadOnly attribute indicates that the function does ++ not write through this pointer argument, even though it may write ++ to the memory that the pointer points to. ++ On an argument, ReadNone attribute indicates that the function does ++ not dereference that pointer argument, even though it may read or write ++ the memory that the pointer points to if accessed through other pointers. ++ */ ++ if (F->hasParamAttribute(ArgNo, Attribute::NoAlias) && ++ (F->hasParamAttribute(ArgNo, Attribute::ReadNone) || ++ F->hasParamAttribute(ArgNo, Attribute::ReadOnly))) { ++ return true; ++ } ++ } ++ return AAResultBase::pointsToConstantMemory(Loc, AAQI, OrLocal); + } +diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAliasAnalysis.h b/llvm/lib/Target/AMDGPU/AMDGPUAliasAnalysis.h +index acd437e8987c..db2372d911b1 100644 +--- a/llvm/lib/Target/AMDGPU/AMDGPUAliasAnalysis.h ++++ b/llvm/lib/Target/AMDGPU/AMDGPUAliasAnalysis.h +@@ -38,8 +38,8 @@ public: + + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, + AAQueryInfo &AAQI); +- ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, AAQueryInfo &AAQI, +- bool IgnoreLocals); ++ bool pointsToConstantMemory(const MemoryLocation &Loc, AAQueryInfo &AAQI, ++ bool OrLocal); + }; + + /// Analysis pass providing a never-invalidated alias analysis result. +diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp +index a187cb1e4790..932feea044b3 100644 +--- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp ++++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp +@@ -140,14 +140,13 @@ static MemoryEffects checkFunctionMemoryAccess(Function &F, bool ThisBody, + ME |= MemoryEffects::argMemOnly(ModRefInfo::ModRef); + + auto AddLocAccess = [&](const MemoryLocation &Loc, ModRefInfo MR) { +- // Ignore accesses to known-invariant or local memory. +- MR &= AAR.getModRefInfoMask(Loc, /*IgnoreLocal=*/true); +- if (isNoModRef(MR)) ++ // Ignore accesses to local memory. ++ if (AAR.pointsToConstantMemory(Loc, /*OrLocal=*/true)) + return; + + const Value *UO = getUnderlyingObject(Loc.Ptr); + assert(!isa(UO) && +- "Should have been handled by getModRefInfoMask()"); ++ "Should have been handled by pointsToConstantMemory()"); + if (isa(UO)) { + ME |= MemoryEffects::argMemOnly(MR); + return; +diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +index 3df5af6ac517..5adb898f2607 100644 +--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp ++++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +@@ -135,7 +135,7 @@ Instruction *InstCombinerImpl::SimplifyAnyMemTransfer(AnyMemTransferInst *MI) { + // If we have a store to a location which is known constant, we can conclude + // that the store must be storing the constant value (else the memory + // wouldn't be constant), and this must be a noop. +- if (!isModSet(AA->getModRefInfoMask(MI->getDest()))) { ++ if (AA->pointsToConstantMemory(MI->getDest())) { + // Set the size of the copy to 0, it will be deleted on the next iteration. + MI->setLength(Constant::getNullValue(MI->getLength()->getType())); + return MI; +@@ -252,7 +252,7 @@ Instruction *InstCombinerImpl::SimplifyAnyMemSet(AnyMemSetInst *MI) { + // If we have a store to a location which is known constant, we can conclude + // that the store must be storing the constant value (else the memory + // wouldn't be constant), and this must be a noop. +- if (!isModSet(AA->getModRefInfoMask(MI->getDest()))) { ++ if (AA->pointsToConstantMemory(MI->getDest())) { + // Set the size of the copy to 0, it will be deleted on the next iteration. + MI->setLength(Constant::getNullValue(MI->getLength()->getType())); + return MI; +diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +index c4efd0301711..9acfa612bc27 100644 +--- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp ++++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +@@ -31,20 +31,20 @@ using namespace PatternMatch; + STATISTIC(NumDeadStore, "Number of dead stores eliminated"); + STATISTIC(NumGlobalCopies, "Number of allocas copied from constant global"); + +-/// isOnlyCopiedFromConstantMemory - Recursively walk the uses of a (derived) ++/// isOnlyCopiedFromConstantGlobal - Recursively walk the uses of a (derived) + /// pointer to an alloca. Ignore any reads of the pointer, return false if we + /// see any stores or other unknown uses. If we see pointer arithmetic, keep + /// track of whether it moves the pointer (with IsOffset) but otherwise traverse + /// the uses. If we see a memcpy/memmove that targets an unoffseted pointer to +-/// the alloca, and if the source pointer is a pointer to a constant memory +-/// location, we can optimize this. ++/// the alloca, and if the source pointer is a pointer to a constant global, we ++/// can optimize this. + static bool + isOnlyCopiedFromConstantMemory(AAResults *AA, AllocaInst *V, + MemTransferInst *&TheCopy, + SmallVectorImpl &ToDelete) { + // We track lifetime intrinsics as we encounter them. If we decide to go +- // ahead and replace the value with the memory location, this lets the caller +- // quickly eliminate the markers. ++ // ahead and replace the value with the global, this lets the caller quickly ++ // eliminate the markers. + + SmallVector, 35> ValuesToInspect; + ValuesToInspect.emplace_back(V, false); +@@ -131,8 +131,8 @@ isOnlyCopiedFromConstantMemory(AAResults *AA, AllocaInst *V, + // If the memintrinsic isn't using the alloca as the dest, reject it. + if (U.getOperandNo() != 0) return false; + +- // If the source of the memcpy/move is not constant, reject it. +- if (isModSet(AA->getModRefInfoMask(MI->getSource()))) ++ // If the source of the memcpy/move is not a constant global, reject it. ++ if (!AA->pointsToConstantMemory(MI->getSource())) + return false; + + // Otherwise, the transform is safe. Remember the copy instruction. +@@ -142,10 +142,9 @@ isOnlyCopiedFromConstantMemory(AAResults *AA, AllocaInst *V, + return true; + } + +-/// isOnlyCopiedFromConstantMemory - Return true if the specified alloca is only +-/// modified by a copy from a constant memory location. If we can prove this, we +-/// can replace any uses of the alloca with uses of the memory location +-/// directly. ++/// isOnlyCopiedFromConstantGlobal - Return true if the specified alloca is only ++/// modified by a copy from a constant global. If we can prove this, we can ++/// replace any uses of the alloca with uses of the global directly. + static MemTransferInst * + isOnlyCopiedFromConstantMemory(AAResults *AA, + AllocaInst *AI, +@@ -399,11 +398,11 @@ Instruction *InstCombinerImpl::visitAllocaInst(AllocaInst &AI) { + } + + // Check to see if this allocation is only modified by a memcpy/memmove from +- // a memory location whose alignment is equal to or exceeds that of the +- // allocation. If this is the case, we can change all users to use the +- // constant memory location instead. This is commonly produced by the CFE by +- // constructs like "void foo() { int A[] = {1,2,3,4,5,6,7,8,9...}; }" if 'A' +- // is only subsequently read. ++ // a constant whose alignment is equal to or exceeds that of the allocation. ++ // If this is the case, we can change all users to use the constant global ++ // instead. This is commonly produced by the CFE by constructs like "void ++ // foo() { int A[] = {1,2,3,4,5,6,7,8,9...}; }" if 'A' is only subsequently ++ // read. + SmallVector ToDelete; + if (MemTransferInst *Copy = isOnlyCopiedFromConstantMemory(AA, &AI, ToDelete)) { + Value *TheSrc = Copy->getSource(); +@@ -1379,7 +1378,7 @@ Instruction *InstCombinerImpl::visitStoreInst(StoreInst &SI) { + // If we have a store to a location which is known constant, we can conclude + // that the store must be storing the constant value (else the memory + // wouldn't be constant), and this must be a noop. +- if (!isModSet(AA->getModRefInfoMask(Ptr))) ++ if (AA->pointsToConstantMemory(Ptr)) + return eraseInstFromFunction(SI); + + // Do really simple DSE, to catch cases where there are several consecutive +diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp +index 001937cc1670..cddee7d3eb07 100644 +--- a/llvm/lib/Transforms/Scalar/LICM.cpp ++++ b/llvm/lib/Transforms/Scalar/LICM.cpp +@@ -1161,7 +1161,7 @@ bool llvm::canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT, + + // Loads from constant memory are always safe to move, even if they end up + // in the same alias set as something that ends up being modified. +- if (!isModSet(AA->getModRefInfoMask(LI->getOperand(0)))) ++ if (AA->pointsToConstantMemory(LI->getOperand(0))) + return true; + if (LI->hasMetadata(LLVMContext::MD_invariant_load)) + return true; +diff --git a/llvm/lib/Transforms/Scalar/LoopPredication.cpp b/llvm/lib/Transforms/Scalar/LoopPredication.cpp +index 1e4060abeb88..36b0020b9ce9 100644 +--- a/llvm/lib/Transforms/Scalar/LoopPredication.cpp ++++ b/llvm/lib/Transforms/Scalar/LoopPredication.cpp +@@ -569,7 +569,7 @@ bool LoopPredication::isLoopInvariantValue(const SCEV* S) { + if (const SCEVUnknown *U = dyn_cast(S)) + if (const auto *LI = dyn_cast(U->getValue())) + if (LI->isUnordered() && L->hasLoopInvariantOperands(LI)) +- if (!isModSet(AA->getModRefInfoMask(LI->getOperand(0))) || ++ if (AA->pointsToConstantMemory(LI->getOperand(0)) || + LI->hasMetadata(LLVMContext::MD_invariant_load)) + return true; + return false; +diff --git a/llvm/test/Analysis/BasicAA/constant-memory.ll b/llvm/test/Analysis/BasicAA/constant-memory.ll +index 2b197d6dbc71..6ef875d9358e 100644 +--- a/llvm/test/Analysis/BasicAA/constant-memory.ll ++++ b/llvm/test/Analysis/BasicAA/constant-memory.ll +@@ -6,16 +6,18 @@ declare void @dummy() + + declare void @foo(ptr) + ++; FIXME: This could be NoModRef + ; CHECK-LABEL: Function: basic +-; CHECK: NoModRef: Ptr: i32* @c <-> call void @dummy() ++; CHECK: Just Ref: Ptr: i32* @c <-> call void @dummy() + define void @basic(ptr %p) { + call void @dummy() + load i32, ptr @c + ret void + } + ++; FIXME: This could be NoModRef + ; CHECK-LABEL: Function: recphi +-; CHECK: NoModRef: Ptr: i32* %p <-> call void @dummy() ++; CHECK: Just Ref: Ptr: i32* %p <-> call void @dummy() + define void @recphi() { + entry: + br label %loop +@@ -32,20 +34,20 @@ exit: + ret void + } + +-; Tests that readonly noalias implies !Mod. ++; Tests that readonly noalias doesn't imply !Mod yet. + ; + ; CHECK-LABEL: Function: readonly_noalias +-; CHECK: Just Ref: Ptr: i32* %p <-> call void @foo(ptr %p) ++; CHECK: Both ModRef: Ptr: i32* %p <-> call void @foo(ptr %p) + define void @readonly_noalias(ptr readonly noalias %p) { + call void @foo(ptr %p) + load i32, ptr %p + ret void + } + +-; Tests that readnone noalias implies !Mod. ++; Tests that readnone noalias doesn't imply !Mod yet. + ; + ; CHECK-LABEL: Function: readnone_noalias +-; CHECK: Just Ref: Ptr: i32* %p <-> call void @foo(ptr %p) ++; CHECK: Both ModRef: Ptr: i32* %p <-> call void @foo(ptr %p) + define void @readnone_noalias(ptr readnone noalias %p) { + call void @foo(ptr %p) + load i32, ptr %p +diff --git a/llvm/test/Transforms/InstCombine/memcpy-from-global.ll b/llvm/test/Transforms/InstCombine/memcpy-from-global.ll +index b230c1488f75..cd6dfc4561b9 100644 +--- a/llvm/test/Transforms/InstCombine/memcpy-from-global.ll ++++ b/llvm/test/Transforms/InstCombine/memcpy-from-global.ll +@@ -338,10 +338,12 @@ entry: + ret float %r + } + +-; Tests that we can eliminate allocas copied from readonly noalias pointers. ++; Tests that we can't eliminate allocas copied from readonly noalias pointers yet. + define void @memcpy_from_readonly_noalias(ptr readonly noalias align 8 dereferenceable(124) %arg) { + ; CHECK-LABEL: @memcpy_from_readonly_noalias( +-; CHECK-NEXT: call void @bar(ptr nonnull [[ARG:%.*]]) #[[ATTR3]] ++; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [[T:%.*]], align 8 ++; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(124) [[ALLOCA]], ptr noundef nonnull align 8 dereferenceable(124) [[ARG:%.*]], i64 124, i1 false) ++; CHECK-NEXT: call void @bar(ptr nonnull [[ALLOCA]]) #[[ATTR3]] + ; CHECK-NEXT: ret void + ; + %alloca = alloca %T, align 8 +diff --git a/llvm/test/Transforms/InstCombine/store.ll b/llvm/test/Transforms/InstCombine/store.ll +index 95ba64c9e640..7cbe91b44beb 100644 +--- a/llvm/test/Transforms/InstCombine/store.ll ++++ b/llvm/test/Transforms/InstCombine/store.ll +@@ -336,10 +336,12 @@ define void @store_to_constant() { + ret void + } + +-; Delete stores to readonly noalias pointers. ++; We can't delete stores to readonly noalias pointers yet. + define void @store_to_readonly_noalias(ptr readonly noalias %0) { + ; CHECK-LABEL: @store_to_readonly_noalias( ++; CHECK-NEXT: store i32 3, ptr [[TMP0:%.*]], align 4 + ; CHECK-NEXT: ret void ++; + store i32 3, ptr %0, align 4 + ret void + } +-- +2.38.1.1.g6d9df9d320 +