[llvm] a90ac20 - [MemoryEffects][NFCI] Make the MemoryEffects class reusable

Johannes Doerfert via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 3 10:07:25 PDT 2023


Author: Johannes Doerfert
Date: 2023-07-03T10:07:03-07:00
New Revision: a90ac20c528f65ea50d14bc261bb65f7446b2231

URL: https://github.com/llvm/llvm-project/commit/a90ac20c528f65ea50d14bc261bb65f7446b2231
DIFF: https://github.com/llvm/llvm-project/commit/a90ac20c528f65ea50d14bc261bb65f7446b2231.diff

LOG: [MemoryEffects][NFCI] Make the MemoryEffects class reusable

In a follow up we will reuse the logic in MemoryEffectsBase to merge
AAMemoryLocation and AAMemoryBehavior without duplicating all the bit
fiddling code already available in MemoryEffectsBase.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D153305

Added: 
    

Modified: 
    llvm/include/llvm/AsmParser/LLParser.h
    llvm/include/llvm/IR/Attributes.h
    llvm/include/llvm/Support/ModRef.h
    llvm/lib/Analysis/AliasAnalysis.cpp
    llvm/lib/AsmParser/LLParser.cpp
    llvm/lib/IR/Attributes.cpp
    llvm/lib/Transforms/IPO/FunctionAttrs.cpp
    llvm/lib/Transforms/IPO/SCCP.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h
index 63cb61ae3a19df..eca908a24aac7b 100644
--- a/llvm/include/llvm/AsmParser/LLParser.h
+++ b/llvm/include/llvm/AsmParser/LLParser.h
@@ -20,6 +20,7 @@
 #include "llvm/IR/FMF.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/ModuleSummaryIndex.h"
+#include "llvm/Support/ModRef.h"
 #include <map>
 #include <optional>
 
@@ -42,7 +43,6 @@ namespace llvm {
   class Comdat;
   class MDString;
   class MDNode;
-  class MemoryEffects;
   struct SlotMapping;
 
   /// ValID - Represents a reference of a definition of some sort with no type.

diff  --git a/llvm/include/llvm/IR/Attributes.h b/llvm/include/llvm/IR/Attributes.h
index 4982b11ece6fb4..db33b540047168 100644
--- a/llvm/include/llvm/IR/Attributes.h
+++ b/llvm/include/llvm/IR/Attributes.h
@@ -22,6 +22,7 @@
 #include "llvm/Config/llvm-config.h"
 #include "llvm/Support/Alignment.h"
 #include "llvm/Support/CodeGen.h"
+#include "llvm/Support/ModRef.h"
 #include "llvm/Support/PointerLikeTypeTraits.h"
 #include <cassert>
 #include <cstdint>
@@ -39,7 +40,6 @@ class AttributeSetNode;
 class FoldingSetNodeID;
 class Function;
 class LLVMContext;
-class MemoryEffects;
 class Type;
 class raw_ostream;
 enum FPClassTest : unsigned;

diff  --git a/llvm/include/llvm/Support/ModRef.h b/llvm/include/llvm/Support/ModRef.h
index d135625fc8a1ac..ac088620e2ba80 100644
--- a/llvm/include/llvm/Support/ModRef.h
+++ b/llvm/include/llvm/Support/ModRef.h
@@ -55,22 +55,23 @@ enum class ModRefInfo : uint8_t {
 /// Debug print ModRefInfo.
 raw_ostream &operator<<(raw_ostream &OS, ModRefInfo MR);
 
-/// Summary of how a function affects memory in the program.
-///
-/// Loads from constant globals are not considered memory accesses for this
-/// interface. Also, functions may freely modify stack space local to their
-/// invocation without having to report it through these interfaces.
-class MemoryEffects {
+/// The locations at which a function might access memory.
+enum IRMemLocation {
+  /// Access to memory via argument pointers.
+  ArgMem = 0,
+  /// Memory that is inaccessible via LLVM IR.
+  InaccessibleMem = 1,
+  /// Any other memory.
+  Other = 2,
+
+  /// Helpers to iterate all locations in the MemoryEffectsBase class.
+  First = ArgMem,
+  Last = Other,
+};
+
+template <typename LocationEnum> class MemoryEffectsBase {
 public:
-  /// The locations at which a function might access memory.
-  enum Location {
-    /// Access to memory via argument pointers.
-    ArgMem = 0,
-    /// Memory that is inaccessible via LLVM IR.
-    InaccessibleMem = 1,
-    /// Any other memory.
-    Other = 2,
-  };
+  using Location = LocationEnum;
 
 private:
   uint32_t Data = 0;
@@ -82,79 +83,79 @@ class MemoryEffects {
     return (uint32_t)Loc * BitsPerLoc;
   }
 
-  MemoryEffects(uint32_t Data) : Data(Data) {}
+  MemoryEffectsBase(uint32_t Data) : Data(Data) {}
 
   void setModRef(Location Loc, ModRefInfo MR) {
     Data &= ~(LocMask << getLocationPos(Loc));
     Data |= static_cast<uint32_t>(MR) << getLocationPos(Loc);
   }
 
-  friend raw_ostream &operator<<(raw_ostream &OS, MemoryEffects RMRB);
-
 public:
   /// Returns iterator over all supported location kinds.
   static auto locations() {
-    return enum_seq_inclusive(Location::ArgMem, Location::Other,
+    return enum_seq_inclusive(Location::First, Location::Last,
                               force_iteration_on_noniterable_enum);
   }
 
-  /// Create MemoryEffects that can access only the given location with the
+  /// Create MemoryEffectsBase that can access only the given location with the
   /// given ModRefInfo.
-  MemoryEffects(Location Loc, ModRefInfo MR) { setModRef(Loc, MR); }
+  MemoryEffectsBase(Location Loc, ModRefInfo MR) { setModRef(Loc, MR); }
 
-  /// Create MemoryEffects that can access any location with the given
+  /// Create MemoryEffectsBase that can access any location with the given
   /// ModRefInfo.
-  explicit MemoryEffects(ModRefInfo MR) {
+  explicit MemoryEffectsBase(ModRefInfo MR) {
     for (Location Loc : locations())
       setModRef(Loc, MR);
   }
 
-  /// Create MemoryEffects that can read and write any memory.
-  static MemoryEffects unknown() {
-    return MemoryEffects(ModRefInfo::ModRef);
+  /// Create MemoryEffectsBase that can read and write any memory.
+  static MemoryEffectsBase unknown() {
+    return MemoryEffectsBase(ModRefInfo::ModRef);
   }
 
-  /// Create MemoryEffects that cannot read or write any memory.
-  static MemoryEffects none() {
-    return MemoryEffects(ModRefInfo::NoModRef);
+  /// Create MemoryEffectsBase that cannot read or write any memory.
+  static MemoryEffectsBase none() {
+    return MemoryEffectsBase(ModRefInfo::NoModRef);
   }
 
-  /// Create MemoryEffects that can read any memory.
-  static MemoryEffects readOnly() {
-    return MemoryEffects(ModRefInfo::Ref);
+  /// Create MemoryEffectsBase that can read any memory.
+  static MemoryEffectsBase readOnly() {
+    return MemoryEffectsBase(ModRefInfo::Ref);
   }
 
-  /// Create MemoryEffects that can write any memory.
-  static MemoryEffects writeOnly() {
-    return MemoryEffects(ModRefInfo::Mod);
+  /// Create MemoryEffectsBase that can write any memory.
+  static MemoryEffectsBase writeOnly() {
+    return MemoryEffectsBase(ModRefInfo::Mod);
   }
 
-  /// Create MemoryEffects that can only access argument memory.
-  static MemoryEffects argMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
-    return MemoryEffects(ArgMem, MR);
+  /// Create MemoryEffectsBase that can only access argument memory.
+  static MemoryEffectsBase argMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
+    return MemoryEffectsBase(Location::ArgMem, MR);
   }
 
-  /// Create MemoryEffects that can only access inaccessible memory.
-  static MemoryEffects inaccessibleMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
-    return MemoryEffects(InaccessibleMem, MR);
+  /// Create MemoryEffectsBase that can only access inaccessible memory.
+  static MemoryEffectsBase
+  inaccessibleMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
+    return MemoryEffectsBase(Location::InaccessibleMem, MR);
   }
 
-  /// Create MemoryEffects that can only access inaccessible or argument memory.
-  static MemoryEffects
+  /// Create MemoryEffectsBase that can only access inaccessible or argument
+  /// memory.
+  static MemoryEffectsBase
   inaccessibleOrArgMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
-    MemoryEffects FRMB = none();
-    FRMB.setModRef(ArgMem, MR);
-    FRMB.setModRef(InaccessibleMem, MR);
+    MemoryEffectsBase FRMB = none();
+    FRMB.setModRef(Location::ArgMem, MR);
+    FRMB.setModRef(Location::InaccessibleMem, MR);
     return FRMB;
   }
 
-  /// Create MemoryEffects from an encoded integer value (used by memory
+  /// Create MemoryEffectsBase from an encoded integer value (used by memory
   /// attribute).
-  static MemoryEffects createFromIntValue(uint32_t Data) {
-    return MemoryEffects(Data);
+  static MemoryEffectsBase createFromIntValue(uint32_t Data) {
+    return MemoryEffectsBase(Data);
   }
 
-  /// Convert MemoryEffects into an encoded integer value (used by memory
+  /// Convert MemoryEffectsBase into an encoded integer value (used by memory
   /// attribute).
   uint32_t toIntValue() const {
     return Data;
@@ -165,16 +166,16 @@ class MemoryEffects {
     return ModRefInfo((Data >> getLocationPos(Loc)) & LocMask);
   }
 
-  /// Get new MemoryEffects with modified ModRefInfo for Loc.
-  MemoryEffects getWithModRef(Location Loc, ModRefInfo MR) const {
-    MemoryEffects ME = *this;
+  /// Get new MemoryEffectsBase with modified ModRefInfo for Loc.
+  MemoryEffectsBase getWithModRef(Location Loc, ModRefInfo MR) const {
+    MemoryEffectsBase ME = *this;
     ME.setModRef(Loc, MR);
     return ME;
   }
 
-  /// Get new MemoryEffects with NoModRef on the given Loc.
-  MemoryEffects getWithoutLoc(Location Loc) const {
-    MemoryEffects ME = *this;
+  /// Get new MemoryEffectsBase with NoModRef on the given Loc.
+  MemoryEffectsBase getWithoutLoc(Location Loc) const {
+    MemoryEffectsBase ME = *this;
     ME.setModRef(Loc, ModRefInfo::NoModRef);
     return ME;
   }
@@ -198,58 +199,74 @@ class MemoryEffects {
 
   /// Whether this function only (at most) accesses argument memory.
   bool onlyAccessesArgPointees() const {
-    return getWithoutLoc(ArgMem).doesNotAccessMemory();
+    return getWithoutLoc(Location::ArgMem).doesNotAccessMemory();
   }
 
   /// Whether this function may access argument memory.
   bool doesAccessArgPointees() const {
-    return isModOrRefSet(getModRef(ArgMem));
+    return isModOrRefSet(getModRef(Location::ArgMem));
   }
 
   /// Whether this function only (at most) accesses inaccessible memory.
   bool onlyAccessesInaccessibleMem() const {
-    return getWithoutLoc(InaccessibleMem).doesNotAccessMemory();
+    return getWithoutLoc(Location::InaccessibleMem).doesNotAccessMemory();
   }
 
   /// Whether this function only (at most) accesses argument and inaccessible
   /// memory.
   bool onlyAccessesInaccessibleOrArgMem() const {
-    return isNoModRef(getModRef(Other));
+    return getWithoutLoc(Location::InaccessibleMem)
+        .getWithoutLoc(Location::ArgMem)
+        .doesNotAccessMemory();
   }
 
-  /// Intersect with other MemoryEffects.
-  MemoryEffects operator&(MemoryEffects Other) const {
-    return MemoryEffects(Data & Other.Data);
+  /// Intersect with other MemoryEffectsBase.
+  MemoryEffectsBase operator&(MemoryEffectsBase Other) const {
+    return MemoryEffectsBase(Data & Other.Data);
   }
 
-  /// Intersect (in-place) with other MemoryEffects.
-  MemoryEffects &operator&=(MemoryEffects Other) {
+  /// Intersect (in-place) with other MemoryEffectsBase.
+  MemoryEffectsBase &operator&=(MemoryEffectsBase Other) {
     Data &= Other.Data;
     return *this;
   }
 
-  /// Union with other MemoryEffects.
-  MemoryEffects operator|(MemoryEffects Other) const {
-    return MemoryEffects(Data | Other.Data);
+  /// Union with other MemoryEffectsBase.
+  MemoryEffectsBase operator|(MemoryEffectsBase Other) const {
+    return MemoryEffectsBase(Data | Other.Data);
   }
 
-  /// Union (in-place) with other MemoryEffects.
-  MemoryEffects &operator|=(MemoryEffects Other) {
+  /// Union (in-place) with other MemoryEffectsBase.
+  MemoryEffectsBase &operator|=(MemoryEffectsBase Other) {
     Data |= Other.Data;
     return *this;
   }
 
-  /// Check whether this is the same as other MemoryEffects.
-  bool operator==(MemoryEffects Other) const {
-    return Data == Other.Data;
+  /// Subtract other MemoryEffectsBase.
+  MemoryEffectsBase operator-(MemoryEffectsBase Other) const {
+    return MemoryEffectsBase(Data & ~Other.Data);
   }
 
-  /// Check whether this is 
diff erent from other MemoryEffects.
-  bool operator!=(MemoryEffects Other) const {
-    return !operator==(Other);
+  /// Subtract (in-place) with other MemoryEffectsBase.
+  MemoryEffectsBase &operator-=(MemoryEffectsBase Other) {
+    Data &= ~Other.Data;
+    return *this;
   }
+
+  /// Check whether this is the same as other MemoryEffectsBase.
+  bool operator==(MemoryEffectsBase Other) const { return Data == Other.Data; }
+
+  /// Check whether this is 
diff erent from other MemoryEffectsBase.
+  bool operator!=(MemoryEffectsBase Other) const { return !operator==(Other); }
 };
 
+/// Summary of how a function affects memory in the program.
+///
+/// Loads from constant globals are not considered memory accesses for this
+/// interface. Also, functions may freely modify stack space local to their
+/// invocation without having to report it through these interfaces.
+using MemoryEffects = MemoryEffectsBase<IRMemLocation>;
+
 /// Debug print MemoryEffects.
 raw_ostream &operator<<(raw_ostream &OS, MemoryEffects RMRB);
 

diff  --git a/llvm/lib/Analysis/AliasAnalysis.cpp b/llvm/lib/Analysis/AliasAnalysis.cpp
index a5338afee85b1e..7b2f91f5392a5b 100644
--- a/llvm/lib/Analysis/AliasAnalysis.cpp
+++ b/llvm/lib/Analysis/AliasAnalysis.cpp
@@ -227,12 +227,12 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call,
   // We can completely ignore inaccessible memory here, because MemoryLocations
   // can only reference accessible memory.
   auto ME = getMemoryEffects(Call, AAQI)
-                .getWithoutLoc(MemoryEffects::InaccessibleMem);
+                .getWithoutLoc(IRMemLocation::InaccessibleMem);
   if (ME.doesNotAccessMemory())
     return ModRefInfo::NoModRef;
 
-  ModRefInfo ArgMR = ME.getModRef(MemoryEffects::ArgMem);
-  ModRefInfo OtherMR = ME.getWithoutLoc(MemoryEffects::ArgMem).getModRef();
+  ModRefInfo ArgMR = ME.getModRef(IRMemLocation::ArgMem);
+  ModRefInfo OtherMR = ME.getWithoutLoc(IRMemLocation::ArgMem).getModRef();
   if ((ArgMR | OtherMR) != OtherMR) {
     // Refine the modref info for argument memory. We only bother to do this
     // if ArgMR is not a subset of OtherMR, otherwise this won't have an impact
@@ -442,15 +442,15 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, ModRefInfo MR) {
 }
 
 raw_ostream &llvm::operator<<(raw_ostream &OS, MemoryEffects ME) {
-  for (MemoryEffects::Location Loc : MemoryEffects::locations()) {
+  for (IRMemLocation Loc : MemoryEffects::locations()) {
     switch (Loc) {
-    case MemoryEffects::ArgMem:
+    case IRMemLocation::ArgMem:
       OS << "ArgMem: ";
       break;
-    case MemoryEffects::InaccessibleMem:
+    case IRMemLocation::InaccessibleMem:
       OS << "InaccessibleMem: ";
       break;
-    case MemoryEffects::Other:
+    case IRMemLocation::Other:
       OS << "Other: ";
       break;
     }

diff  --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 1638791e3f5eb2..dcb3476a2d840a 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -2279,9 +2279,9 @@ bool LLParser::parseAllocKind(AllocFnKind &Kind) {
 static std::optional<MemoryEffects::Location> keywordToLoc(lltok::Kind Tok) {
   switch (Tok) {
   case lltok::kw_argmem:
-    return MemoryEffects::ArgMem;
+    return IRMemLocation::ArgMem;
   case lltok::kw_inaccessiblemem:
-    return MemoryEffects::InaccessibleMem;
+    return IRMemLocation::InaccessibleMem;
   default:
     return std::nullopt;
   }
@@ -2318,7 +2318,7 @@ std::optional<MemoryEffects> LLParser::parseMemoryAttr() {
 
   bool SeenLoc = false;
   do {
-    std::optional<MemoryEffects::Location> Loc = keywordToLoc(Lex.getKind());
+    std::optional<IRMemLocation> Loc = keywordToLoc(Lex.getKind());
     if (Loc) {
       Lex.Lex();
       if (!EatIfPresent(lltok::colon)) {

diff  --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index 710e29e348a865..3d89d18e5822be 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -523,7 +523,7 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
 
     // Print access kind for "other" as the default access kind. This way it
     // will apply to any new location kinds that get split out of "other".
-    ModRefInfo OtherMR = ME.getModRef(MemoryEffects::Other);
+    ModRefInfo OtherMR = ME.getModRef(IRMemLocation::Other);
     if (OtherMR != ModRefInfo::NoModRef || ME.getModRef() == OtherMR) {
       First = false;
       OS << getModRefStr(OtherMR);
@@ -539,13 +539,13 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
       First = false;
 
       switch (Loc) {
-      case MemoryEffects::ArgMem:
+      case IRMemLocation::ArgMem:
         OS << "argmem: ";
         break;
-      case MemoryEffects::InaccessibleMem:
+      case IRMemLocation::InaccessibleMem:
         OS << "inaccessiblemem: ";
         break;
-      case MemoryEffects::Other:
+      case IRMemLocation::Other:
         llvm_unreachable("This is represented as the default access kind");
       }
       OS << getModRefStr(MR);

diff  --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
index e7a0c93f2afdac..34299f9dbb2325 100644
--- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
@@ -152,7 +152,7 @@ static MemoryEffects checkFunctionMemoryAccess(Function &F, bool ThisBody,
     // If it's not an identified object, it might be an argument.
     if (!isIdentifiedObject(UO))
       ME |= MemoryEffects::argMemOnly(MR);
-    ME |= MemoryEffects(MemoryEffects::Other, MR);
+    ME |= MemoryEffects(IRMemLocation::Other, MR);
   };
   // Scan the function body for instructions that may read or write memory.
   for (Instruction &I : instructions(F)) {
@@ -179,17 +179,17 @@ static MemoryEffects checkFunctionMemoryAccess(Function &F, bool ThisBody,
       if (isa<PseudoProbeInst>(I))
         continue;
 
-      ME |= CallME.getWithoutLoc(MemoryEffects::ArgMem);
+      ME |= CallME.getWithoutLoc(IRMemLocation::ArgMem);
 
       // If the call accesses captured memory (currently part of "other") and
       // an argument is captured (currently not tracked), then it may also
       // access argument memory.
-      ModRefInfo OtherMR = CallME.getModRef(MemoryEffects::Other);
+      ModRefInfo OtherMR = CallME.getModRef(IRMemLocation::Other);
       ME |= MemoryEffects::argMemOnly(OtherMR);
 
       // Check whether all pointer arguments point to local memory, and
       // ignore calls that only access local memory.
-      ModRefInfo ArgMR = CallME.getModRef(MemoryEffects::ArgMem);
+      ModRefInfo ArgMR = CallME.getModRef(IRMemLocation::ArgMem);
       if (ArgMR != ModRefInfo::NoModRef) {
         for (const Use &U : Call->args()) {
           const Value *Arg = U;

diff  --git a/llvm/lib/Transforms/IPO/SCCP.cpp b/llvm/lib/Transforms/IPO/SCCP.cpp
index 985ae0062b0ec4..e2e6364df9065a 100644
--- a/llvm/lib/Transforms/IPO/SCCP.cpp
+++ b/llvm/lib/Transforms/IPO/SCCP.cpp
@@ -191,8 +191,8 @@ static bool runIPSCCP(
           if (ME == MemoryEffects::unknown())
             return AL;
 
-          ME |= MemoryEffects(MemoryEffects::Other,
-                              ME.getModRef(MemoryEffects::ArgMem));
+          ME |= MemoryEffects(IRMemLocation::Other,
+                              ME.getModRef(IRMemLocation::ArgMem));
           return AL.addFnAttribute(
               F.getContext(),
               Attribute::getWithMemoryEffects(F.getContext(), ME));


        


More information about the llvm-commits mailing list