[llvm] [RFC][Draft] Extend MemoryEffects to Support Target-Specific Memory L… (PR #148650)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 15 05:11:46 PDT 2025


https://github.com/CarolineConcatto updated https://github.com/llvm/llvm-project/pull/148650

>From b2cb9de3a835615d80df05a2fcb377bffe2d44fa Mon Sep 17 00:00:00 2001
From: CarolineConcatto <caroline.concatto at arm.com>
Date: Tue, 1 Jul 2025 11:48:55 +0000
Subject: [PATCH 1/2] [RFC][Draft] Extend MemoryEffects to Support
 Target-Specific Memory Locations
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This patch introduces preliminary support for additional memory locations,
such as FPMR and ZA, needed to model AArch64 architectural registers as
memory dependencies.

Currently, these locations are not yet target-specific. The goal is to enable
the compiler to express read/write effects on these resources.

What This Patch Does:
  Adds two new memory locations: FPMR and ZA, intended to represent
AArch64-specific inaccessible memory types.

Current Limitations:
  These new locations are not yet target-specific in the type-safe sense,
they are globally visible and hardcoded.
  There is no mechanism yet to associate a memory location with its
corresponding target (e.g., AArch64 vs RISCV).
  No changes are made yet to bitcode serialization, parser support, or alias
analysis behavior.

This patch is not functionally complete — it is a structural prototype to
solicit feedback on the direction and I would like some suggestion on
how to proceed.
---
 llvm/include/llvm/AsmParser/LLParser.h        |  1 +
 llvm/include/llvm/AsmParser/LLToken.h         |  4 +
 llvm/include/llvm/IR/Intrinsics.td            | 11 +++
 llvm/include/llvm/IR/IntrinsicsAArch64.td     |  3 +-
 llvm/include/llvm/Support/ModRef.h            | 24 ++++-
 llvm/include/llvm/TableGen/Record.h           |  3 +
 llvm/lib/AsmParser/LLLexer.cpp                |  4 +
 llvm/lib/AsmParser/LLParser.cpp               | 94 ++++++++++++++++---
 llvm/lib/IR/Attributes.cpp                    | 13 +++
 llvm/lib/Support/ModRef.cpp                   |  9 ++
 llvm/lib/TableGen/Record.cpp                  | 15 +++
 llvm/test/Assembler/memory-attribute.ll       | 21 +++++
 .../Inputs/memory-attribute-upgrade.ll        |  0
 llvm/test/Bitcode/attributes.ll               | 44 +++++++++
 llvm/test/TableGen/intrinsic-attrs-fp8.td     | 24 +++++
 llvm/unittests/Support/ModRefTest.cpp         |  2 +-
 .../TableGen/Basic/CodeGenIntrinsics.cpp      |  8 +-
 17 files changed, 262 insertions(+), 18 deletions(-)
 create mode 100644 llvm/test/Bitcode/Inputs/memory-attribute-upgrade.ll
 create mode 100644 llvm/test/TableGen/intrinsic-attrs-fp8.td

diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h
index c01de4a289a69..ee7f133961031 100644
--- a/llvm/include/llvm/AsmParser/LLParser.h
+++ b/llvm/include/llvm/AsmParser/LLParser.h
@@ -295,6 +295,7 @@ namespace llvm {
     };
     bool parseEnumAttribute(Attribute::AttrKind Attr, AttrBuilder &B,
                             bool InAttrGroup);
+    bool parseInaccessibleMemLocation(IRMemLocation &MemLoc);
     bool parseOptionalParamOrReturnAttrs(AttrBuilder &B, bool IsParam);
     bool parseOptionalParamAttrs(AttrBuilder &B) {
       return parseOptionalParamOrReturnAttrs(B, true);
diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h
index c7e4bdf3ff811..68920af75c667 100644
--- a/llvm/include/llvm/AsmParser/LLToken.h
+++ b/llvm/include/llvm/AsmParser/LLToken.h
@@ -202,11 +202,15 @@ enum Kind {
   kw_readwrite,
   kw_argmem,
   kw_inaccessiblemem,
+  kw_fpmr,
+  kw_za,
   kw_errnomem,
 
   // Legacy attributes:
   kw_argmemonly,
   kw_inaccessiblememonly,
+  kw_inaccessiblereadmemonly,
+  kw_inaccessiblewritememonly,
   kw_inaccessiblemem_or_argmemonly,
   kw_nocapture,
 
diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td
index bd6f94ac1286c..ad1b0b462be37 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -49,6 +49,17 @@ def IntrArgMemOnly : IntrinsicProperty;
 // accessible by the module being compiled. This is a weaker form of IntrNoMem.
 def IntrInaccessibleMemOnly : IntrinsicProperty;
 
+
+
+class IntrinsicMemoryLocation;
+// This should be added in the Target, but once in IntrinsicsAArch64.td
+// It complains error: "Variable not defined: 'AArch64_FPMR'"
+def AArch64_FPMR : IntrinsicMemoryLocation;
+def AArch64_ZA:   IntrinsicMemoryLocation;
+// IntrInaccessible{Read|Write}MemOnly needs to set Location
+class IntrInaccessibleReadMemOnly<IntrinsicMemoryLocation idx> : IntrinsicProperty{IntrinsicMemoryLocation Loc=idx;}
+class IntrInaccessibleWriteMemOnly<IntrinsicMemoryLocation idx> : IntrinsicProperty{IntrinsicMemoryLocation Loc=idx;}
+
 // IntrInaccessibleMemOrArgMemOnly -- This intrinsic only accesses memory that
 // its pointer-typed arguments point to or memory that is not accessible
 // by the module being compiled. This is a weaker form of IntrArgMemOnly.
diff --git a/llvm/include/llvm/IR/IntrinsicsAArch64.td b/llvm/include/llvm/IR/IntrinsicsAArch64.td
index 0ec5f5163118e..865b71d59de81 100644
--- a/llvm/include/llvm/IR/IntrinsicsAArch64.td
+++ b/llvm/include/llvm/IR/IntrinsicsAArch64.td
@@ -9,7 +9,6 @@
 // This file defines all of the AARCH64-specific intrinsics.
 //
 //===----------------------------------------------------------------------===//
-
 let TargetPrefix = "aarch64" in {
 
 def int_aarch64_ldxr : Intrinsic<[llvm_i64_ty], [llvm_anyptr_ty],
@@ -761,7 +760,7 @@ let TargetPrefix = "aarch64" in {
   class RNDR_Intrinsic
     : DefaultAttrsIntrinsic<[llvm_i64_ty, llvm_i1_ty], [], [IntrNoMem, IntrHasSideEffects]>;
   class FPMR_Set_Intrinsic
-    : DefaultAttrsIntrinsic<[], [llvm_i64_ty], [IntrInaccessibleMemOnly]>; 
+    : DefaultAttrsIntrinsic<[], [llvm_i64_ty], [IntrInaccessibleMemOnly]>;
 }
 
 // FP environment registers.
diff --git a/llvm/include/llvm/Support/ModRef.h b/llvm/include/llvm/Support/ModRef.h
index 71f3b5bcb9c2b..8459876bf34a6 100644
--- a/llvm/include/llvm/Support/ModRef.h
+++ b/llvm/include/llvm/Support/ModRef.h
@@ -56,6 +56,11 @@ enum class ModRefInfo : uint8_t {
 /// Debug print ModRefInfo.
 LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, ModRefInfo MR);
 
+enum class InaccessibleTargetMemLocation {
+  AARCH64_FPMR = 3,
+  AARCH64_ZA = 4,
+};
+
 /// The locations at which a function might access memory.
 enum class IRMemLocation {
   /// Access to memory via argument pointers.
@@ -65,7 +70,7 @@ enum class IRMemLocation {
   /// Errno memory.
   ErrnoMem = 2,
   /// Any other memory.
-  Other = 3,
+  Other = 5,
 
   /// Helpers to iterate all locations in the MemoryEffectsBase class.
   First = ArgMem,
@@ -142,6 +147,18 @@ template <typename LocationEnum> class MemoryEffectsBase {
     return MemoryEffectsBase(Location::InaccessibleMem, MR);
   }
 
+  /// Create MemoryEffectsBase that can only read inaccessible memory.
+  static MemoryEffectsBase
+  inaccessibleReadMemOnly(Location Loc = Location::InaccessibleMem) {
+    return MemoryEffectsBase(Loc, ModRefInfo::Ref);
+  }
+
+  /// Create MemoryEffectsBase that can only write inaccessible memory.
+  static MemoryEffectsBase
+  inaccessibleWriteMemOnly(Location Loc = Location::InaccessibleMem) {
+    return MemoryEffectsBase(Loc, ModRefInfo::Mod);
+  }
+
   /// Create MemoryEffectsBase that can only access errno memory.
   static MemoryEffectsBase errnoMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
     return MemoryEffectsBase(Location::ErrnoMem, MR);
@@ -178,6 +195,11 @@ template <typename LocationEnum> class MemoryEffectsBase {
     return MemoryEffectsBase(Data);
   }
 
+  bool isTargetMemLoc(IRMemLocation Loc) {
+    return static_cast<unsigned>(Loc) >
+           static_cast<unsigned>(Location::ErrnoMem);
+  }
+
   /// Convert MemoryEffectsBase into an encoded integer value (used by memory
   /// attribute).
   uint32_t toIntValue() const {
diff --git a/llvm/include/llvm/TableGen/Record.h b/llvm/include/llvm/TableGen/Record.h
index 5849344bcb0b5..a43429ed2d7e5 100644
--- a/llvm/include/llvm/TableGen/Record.h
+++ b/llvm/include/llvm/TableGen/Record.h
@@ -25,6 +25,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ModRef.h"
 #include "llvm/Support/SMLoc.h"
 #include "llvm/Support/Timer.h"
 #include "llvm/Support/TrailingObjects.h"
@@ -1961,6 +1962,8 @@ class Record {
   /// value is not the right type.
   int64_t getValueAsInt(StringRef FieldName) const;
 
+  llvm::IRMemLocation getLocationTypeAsInt(StringRef FieldName) const;
+
   /// This method looks up the specified field and returns its value as an Dag,
   /// throwing an exception if the field does not exist or if the value is not
   /// the right type.
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index ce813e1d7b1c4..d7ac109d3a7bf 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -701,10 +701,14 @@ lltok::Kind LLLexer::LexIdentifier() {
   KEYWORD(write);
   KEYWORD(readwrite);
   KEYWORD(argmem);
+  KEYWORD(fpmr);
+  KEYWORD(za);
   KEYWORD(inaccessiblemem);
   KEYWORD(errnomem);
   KEYWORD(argmemonly);
   KEYWORD(inaccessiblememonly);
+  KEYWORD(inaccessiblewritememonly);
+  KEYWORD(inaccessiblereadmemonly);
   KEYWORD(inaccessiblemem_or_argmemonly);
   KEYWORD(nocapture);
   KEYWORD(address_is_null);
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 7e488b96764a5..5d800b651c721 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -1668,6 +1668,48 @@ static bool upgradeMemoryAttr(MemoryEffects &ME, lltok::Kind Kind) {
   }
 }
 
+static std::optional<MemoryEffects::Location> keywordToLoc(lltok::Kind Tok) {
+  switch (Tok) {
+  case lltok::kw_argmem:
+    return IRMemLocation::ArgMem;
+  case lltok::kw_inaccessiblemem:
+    return IRMemLocation::InaccessibleMem;
+  case lltok::kw_errnomem:
+    return IRMemLocation::ErrnoMem;
+  case lltok::kw_fpmr:
+    return static_cast<IRMemLocation>(
+        llvm::InaccessibleTargetMemLocation::AARCH64_FPMR);
+  case lltok::kw_za:
+    return static_cast<IRMemLocation>(
+        llvm::InaccessibleTargetMemLocation::AARCH64_ZA);
+  default:
+    return std::nullopt;
+  }
+}
+
+bool LLParser::parseInaccessibleMemLocation(IRMemLocation &MemLoc) {
+  // It does not have location
+  if (Lex.getKind() != llvm::lltok::lparen)
+    return false;
+
+  Lex.Lex(); // eat '('
+
+  std::optional<IRMemLocation> LocOpt = keywordToLoc(Lex.getKind());
+  if (!LocOpt)
+    return tokError("invalid memory location keyword");
+
+  MemLoc = *LocOpt;
+
+  Lex.Lex(); // eat the keyword (e.g., 'fpmr', 'za')
+
+  if (Lex.getKind() != llvm::lltok::rparen)
+    return tokError("expected ')' after memory location");
+
+  Lex.Lex(); // eat ')'
+
+  return true; // success
+}
+
 /// parseFnAttributeValuePairs
 ///   ::= <attr> | <attr> '=' <value>
 bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B,
@@ -1678,6 +1720,11 @@ bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B,
   B.clear();
 
   MemoryEffects ME = MemoryEffects::unknown();
+  // Memory effects can span multiple locations, so we initialize a base
+  // MemoryEffects object once with default state, and then incrementally
+  // populate or combine effects for individual locations. This avoids
+  // rebuilding the full Data structure on each addition.
+  bool FirstME = true;
   while (true) {
     lltok::Kind Token = Lex.getKind();
     if (Token == lltok::rbrace)
@@ -1714,6 +1761,36 @@ bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B,
       continue;
     }
 
+    if (Token == lltok::kw_inaccessiblereadmemonly) {
+      Lex.Lex(); // eat the keyword
+
+      IRMemLocation MemLoc;
+      if (parseInaccessibleMemLocation(MemLoc)) {
+        if (!FirstME)
+          ME = ME.getWithModRef(MemLoc, ModRefInfo::Ref);
+        else
+          ME &= MemoryEffects::inaccessibleReadMemOnly(MemLoc);
+      } else
+        ME = MemoryEffects::inaccessibleReadMemOnly();
+      FirstME = false;
+      continue;
+    }
+
+    if (Token == lltok::kw_inaccessiblewritememonly) {
+      Lex.Lex(); // eat the keyword
+
+      IRMemLocation MemLoc;
+      if (parseInaccessibleMemLocation(MemLoc)) {
+        if (!FirstME)
+          ME = ME.getWithModRef(MemLoc, ModRefInfo::Mod);
+        else
+          ME &= MemoryEffects::inaccessibleWriteMemOnly(MemLoc);
+      } else
+        ME &= MemoryEffects::inaccessibleWriteMemOnly();
+      FirstME = false;
+      continue;
+    }
+
     Attribute::AttrKind Attr = tokenToAttribute(Token);
     if (Attr == Attribute::None) {
       if (!InAttrGrp)
@@ -2512,19 +2589,6 @@ bool LLParser::parseAllocKind(AllocFnKind &Kind) {
   return false;
 }
 
-static std::optional<MemoryEffects::Location> keywordToLoc(lltok::Kind Tok) {
-  switch (Tok) {
-  case lltok::kw_argmem:
-    return IRMemLocation::ArgMem;
-  case lltok::kw_inaccessiblemem:
-    return IRMemLocation::InaccessibleMem;
-  case lltok::kw_errnomem:
-    return IRMemLocation::ErrnoMem;
-  default:
-    return std::nullopt;
-  }
-}
-
 static std::optional<ModRefInfo> keywordToModRef(lltok::Kind Tok) {
   switch (Tok) {
   case lltok::kw_none:
@@ -2535,6 +2599,10 @@ static std::optional<ModRefInfo> keywordToModRef(lltok::Kind Tok) {
     return ModRefInfo::Mod;
   case lltok::kw_readwrite:
     return ModRefInfo::ModRef;
+  case lltok::kw_inaccessiblewritememonly:
+    return ModRefInfo::Mod;
+  case lltok::kw_inaccessiblereadmemonly:
+    return ModRefInfo::Ref;
   default:
     return std::nullopt;
   }
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index bfb32ff9995d1..af936eff3834b 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -640,6 +640,10 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
       if (MR == OtherMR)
         continue;
 
+      // Dont want to print Target Location if NoModRef
+      if (ME.isTargetMemLoc(Loc) && (MR == ModRefInfo::NoModRef))
+        continue;
+
       if (!First)
         OS << ", ";
       First = false;
@@ -656,6 +660,15 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
         break;
       case IRMemLocation::Other:
         llvm_unreachable("This is represented as the default access kind");
+      default: {
+        InaccessibleTargetMemLocation TargetLoc =
+            static_cast<InaccessibleTargetMemLocation>(Loc);
+        if (TargetLoc == InaccessibleTargetMemLocation::AARCH64_FPMR)
+          OS << "fpmr: ";
+        if (TargetLoc == InaccessibleTargetMemLocation::AARCH64_ZA)
+          OS << "za: ";
+        break;
+      }
       }
       OS << getModRefStr(MR);
     }
diff --git a/llvm/lib/Support/ModRef.cpp b/llvm/lib/Support/ModRef.cpp
index 2bb9bc945bd2e..82ae2b3acf831 100644
--- a/llvm/lib/Support/ModRef.cpp
+++ b/llvm/lib/Support/ModRef.cpp
@@ -49,6 +49,15 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, MemoryEffects ME) {
     case IRMemLocation::Other:
       OS << "Other: ";
       break;
+    default: {
+      InaccessibleTargetMemLocation TargetLoc =
+          static_cast<InaccessibleTargetMemLocation>(Loc);
+      if (TargetLoc == InaccessibleTargetMemLocation::AARCH64_FPMR)
+        OS << "FPMR: ";
+      if (TargetLoc == InaccessibleTargetMemLocation::AARCH64_ZA)
+        OS << "ZA: ";
+      break;
+    }
     }
     OS << ME.getModRef(Loc);
   });
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index 7f2ed77a74099..df5086efd65df 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -3102,6 +3102,21 @@ Record::getValueAsListOfDefs(StringRef FieldName) const {
   return Defs;
 }
 
+llvm::IRMemLocation Record::getLocationTypeAsInt(StringRef FieldName) const {
+  const Record *LocRec = getValueAsDef(FieldName);
+  StringRef Name = LocRec->getName();
+  if (Name == "AArch64_FPMR")
+    return static_cast<IRMemLocation>(
+        llvm::InaccessibleTargetMemLocation::AARCH64_FPMR);
+  else if (Name == "ZA")
+    return static_cast<IRMemLocation>(
+        llvm::InaccessibleTargetMemLocation::AARCH64_ZA);
+  else if (Name == "InaccessibleMem")
+    return llvm::IRMemLocation::InaccessibleMem;
+  else
+    PrintFatalError(getLoc(), "unknown IRMemLocation: " + Name);
+}
+
 int64_t Record::getValueAsInt(StringRef FieldName) const {
   const RecordVal *R = getValue(FieldName);
   if (!R || !R->getValue())
diff --git a/llvm/test/Assembler/memory-attribute.ll b/llvm/test/Assembler/memory-attribute.ll
index effd4ce7c4548..473468810768b 100644
--- a/llvm/test/Assembler/memory-attribute.ll
+++ b/llvm/test/Assembler/memory-attribute.ll
@@ -78,3 +78,24 @@ declare void @fn_argmem_read_inaccessiblemem_write()
 ; CHECK: @fn_argmem_read_inaccessiblemem_write_reordered()
 declare void @fn_argmem_read_inaccessiblemem_write_reordered()
     memory(inaccessiblemem: write, argmem: read)
+
+; CHECK: Function Attrs: memory(za: write)
+; CHECK: @fn_argmem_read_inaccessiblemem_write_za()
+declare void @fn_argmem_read_inaccessiblemem_write_za()
+    memory(za: inaccessiblewritememonly)
+
+; CHECK: Function Attrs: memory(za: read)
+; CHECK: @fn_argmem_read_inaccessiblemem_read_za()
+declare void @fn_argmem_read_inaccessiblemem_read_za()
+    memory(za: inaccessiblereadmemonly)
+
+; CHECK: Function Attrs: memory(fpmr: write)
+; CHECK: @fn_argmem_read_inaccessiblemem_write_fpmr()
+declare void @fn_argmem_read_inaccessiblemem_write_fpmr()
+    memory(fpmr: inaccessiblewritememonly)
+
+; CHECK: Function Attrs: memory(fpmr: read)
+; CHECK: @fn_argmem_read_inaccessiblemem_read_fpmr()
+declare void @fn_argmem_read_inaccessiblemem_read_fpmr()
+    memory(fpmr: inaccessiblereadmemonly)
+
diff --git a/llvm/test/Bitcode/Inputs/memory-attribute-upgrade.ll b/llvm/test/Bitcode/Inputs/memory-attribute-upgrade.ll
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/llvm/test/Bitcode/attributes.ll b/llvm/test/Bitcode/attributes.ll
index 7dd86a8c0eb16..7d2003fc73111 100644
--- a/llvm/test/Bitcode/attributes.ll
+++ b/llvm/test/Bitcode/attributes.ll
@@ -286,6 +286,7 @@ define void @f48() inaccessiblememonly {
 define void @f49() inaccessiblemem_or_argmemonly {
   ret void
 }
+
 ; CHECK: define void @f50(ptr swiftself %0)
 define void @f50(ptr swiftself %0)
 {
@@ -567,6 +568,42 @@ define void @captures(ptr captures(address) %p) {
   ret void
 }
 
+; CHECK: define void @fpmr_write() [[ATTR59:#.*]] {
+define void @fpmr_write() inaccessiblewritememonly(fpmr) {
+  ret void
+}
+
+; CHECK: define void @fpmr_read()  [[ATTR60:#.*]] {
+define void @fpmr_read() inaccessiblereadmemonly(fpmr) {
+  ret void
+}
+
+; CHECK: define void @za_write()  [[ATTR61:#.*]] {
+define void @za_write() inaccessiblewritememonly(za) {
+  ret void
+}
+
+; CHECK: define void @za_read()  [[ATTR62:#.*]] {
+define void @za_read() inaccessiblereadmemonly(za) {
+  ret void
+}
+
+; CHECK: define void @read_inaccessible()  [[ATTR63:#.*]] {
+define void @read_inaccessible() inaccessiblereadmemonly {
+  ret void
+}
+
+; CHECK: define void @write_inaccessible()  [[ATTR64:#.*]] {
+define void @write_inaccessible() inaccessiblewritememonly {
+  ret void
+}
+
+; CHECK: define void @za_read_write_fpmr()  [[ATTR65:#.*]] {
+define void @za_read_write_fpmr() inaccessiblereadmemonly(za) inaccessiblewritememonly(fpmr) {
+  ret void
+}
+
+
 ; CHECK: attributes #0 = { noreturn }
 ; CHECK: attributes #1 = { nounwind }
 ; CHECK: attributes #2 = { memory(none) }
@@ -626,4 +663,11 @@ define void @captures(ptr captures(address) %p) {
 ; CHECK: attributes [[SKIPPROFILE]] = { skipprofile }
 ; CHECK: attributes [[OPTDEBUG]] = { optdebug }
 ; CHECK: attributes [[NODIVERGENCESOURCE]] = { nodivergencesource }
+; CHECK: attributes [[ATTR59]] = { memory(fpmr: write) }
+; CHECK: attributes [[ATTR60]] = { memory(fpmr: read) }
+; CHECK: attributes [[ATTR61]] = { memory(za: write) }
+; CHECK: attributes [[ATTR62]] = { memory(za: read) }
+; CHECK: attributes [[ATTR63]] = { memory(inaccessiblemem: read) }
+; CHECK: attributes [[ATTR64]] = { memory(inaccessiblemem: write) }
+; CHECK: attributes [[ATTR65]] = { memory(fpmr: write, za: read) }
 ; CHECK: attributes #[[NOBUILTIN]] = { nobuiltin }
diff --git a/llvm/test/TableGen/intrinsic-attrs-fp8.td b/llvm/test/TableGen/intrinsic-attrs-fp8.td
new file mode 100644
index 0000000000000..53ff1dfe2b807
--- /dev/null
+++ b/llvm/test/TableGen/intrinsic-attrs-fp8.td
@@ -0,0 +1,24 @@
+// RUN: llvm-tblgen -gen-intrinsic-impl -I %p/../../include -DTEST_INTRINSICS_SUPPRESS_DEFS %s | FileCheck %s
+
+include "llvm/IR/Intrinsics.td"
+
+def int_aarch64_set_fpmr_2   : DefaultAttrsIntrinsic<[], [llvm_i64_ty], [IntrInaccessibleWriteMemOnly<AArch64_FPMR>]>;
+
+// CHECK:      static constexpr unsigned IntrinsicNameOffsetTable[] = {
+// CHECK-NEXT: 1, // not_intrinsic
+// CHECK-NEXT: 15, // llvm.aarch64.set.fpmr.2
+
+
+// CHECK: static AttributeSet getIntrinsicFnAttributeSet(LLVMContext &C, unsigned ID) {
+// CHECK-NEXT: switch (ID) {
+// CHECK-NEXT:  default: llvm_unreachable("Invalid attribute set number");
+// CHECK-NEXT:  case 0:
+// CHECK-NEXT:    return AttributeSet::get(C, {
+// CHECK-NEXT:      Attribute::get(C, Attribute::NoUnwind),
+// CHECK-NEXT:      Attribute::get(C, Attribute::NoCallback),
+// CHECK-NEXT:      Attribute::get(C, Attribute::NoSync),
+// CHECK-NEXT:      Attribute::get(C, Attribute::NoFree),
+// CHECK-NEXT:      Attribute::get(C, Attribute::WillReturn),
+// CHECK-NEXT:      // ArgMem: NoModRef, InaccessibleMem: NoModRef, ErrnoMem: NoModRef, FPMR: Mod, ZA: NoModRef, Other: NoModRef
+// CHECK-NEXT:      Attribute::getWithMemoryEffects(C, MemoryEffects::createFromIntValue(128)),
+// CHECK-NEXT:    });
diff --git a/llvm/unittests/Support/ModRefTest.cpp b/llvm/unittests/Support/ModRefTest.cpp
index 9c13908da44bb..cbdf752978555 100644
--- a/llvm/unittests/Support/ModRefTest.cpp
+++ b/llvm/unittests/Support/ModRefTest.cpp
@@ -21,7 +21,7 @@ TEST(ModRefTest, PrintMemoryEffects) {
   raw_string_ostream OS(S);
   OS << MemoryEffects::none();
   EXPECT_EQ(S, "ArgMem: NoModRef, InaccessibleMem: NoModRef, ErrnoMem: "
-               "NoModRef, Other: NoModRef");
+               "NoModRef, FPMR: NoModRef, ZA: NoModRef, Other: NoModRef");
 }
 
 } // namespace
diff --git a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
index bc42efa3b2e9c..f53915642ac6d 100644
--- a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
+++ b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
@@ -374,7 +374,13 @@ void CodeGenIntrinsic::setProperty(const Record *R) {
     ME &= MemoryEffects::argMemOnly();
   else if (R->getName() == "IntrInaccessibleMemOnly")
     ME &= MemoryEffects::inaccessibleMemOnly();
-  else if (R->getName() == "IntrInaccessibleMemOrArgMemOnly")
+  else if (R->isSubClassOf("IntrInaccessibleReadMemOnly")) {
+    llvm::IRMemLocation Loc = R->getLocationTypeAsInt("Loc");
+    ME &= MemoryEffects::inaccessibleWriteMemOnly(Loc);
+  } else if (R->isSubClassOf("IntrInaccessibleWriteMemOnly")) {
+    llvm::IRMemLocation Loc = R->getLocationTypeAsInt("Loc");
+    ME &= MemoryEffects::inaccessibleWriteMemOnly(Loc);
+  } else if (R->getName() == "IntrInaccessibleMemOrArgMemOnly")
     ME &= MemoryEffects::inaccessibleOrArgMemOnly();
   else if (R->getName() == "Commutative")
     isCommutative = true;

>From 81e03ebc977e4ebffe214fe0240994941ca9b440 Mon Sep 17 00:00:00 2001
From: CarolineConcatto <caroline.concatto at arm.com>
Date: Tue, 15 Jul 2025 10:56:25 +0000
Subject: [PATCH 2/2] Address review comments about tests and names

This patch is removing the keyworkd and token inaccessibleWrite and
inaccessibleRead. It is using Read and Write to set the Target Memory
Location.

Adding "aarch64" in front of the target specific memory locations
---
 llvm/include/llvm/AsmParser/LLToken.h         |  6 +-
 llvm/include/llvm/Support/ModRef.h            | 12 ----
 llvm/lib/AsmParser/LLLexer.cpp                |  6 +-
 llvm/lib/AsmParser/LLParser.cpp               | 66 +------------------
 llvm/lib/IR/Attributes.cpp                    |  4 +-
 llvm/lib/Support/ModRef.cpp                   |  4 +-
 llvm/lib/TableGen/Record.cpp                  |  2 +-
 llvm/test/Assembler/memory-attribute.ll       | 44 +++++++------
 llvm/test/Bitcode/attributes.ll               | 43 ------------
 llvm/test/TableGen/intrinsic-attrs-fp8.td     | 46 ++++++++++---
 llvm/unittests/Support/ModRefTest.cpp         |  3 +-
 .../TableGen/Basic/CodeGenIntrinsics.cpp      |  4 +-
 12 files changed, 77 insertions(+), 163 deletions(-)

diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h
index 68920af75c667..c08eb99c1f5b2 100644
--- a/llvm/include/llvm/AsmParser/LLToken.h
+++ b/llvm/include/llvm/AsmParser/LLToken.h
@@ -202,15 +202,13 @@ enum Kind {
   kw_readwrite,
   kw_argmem,
   kw_inaccessiblemem,
-  kw_fpmr,
-  kw_za,
+  kw_aarch64_fpmr,
+  kw_aarch64_za,
   kw_errnomem,
 
   // Legacy attributes:
   kw_argmemonly,
   kw_inaccessiblememonly,
-  kw_inaccessiblereadmemonly,
-  kw_inaccessiblewritememonly,
   kw_inaccessiblemem_or_argmemonly,
   kw_nocapture,
 
diff --git a/llvm/include/llvm/Support/ModRef.h b/llvm/include/llvm/Support/ModRef.h
index 8459876bf34a6..329218900f8ca 100644
--- a/llvm/include/llvm/Support/ModRef.h
+++ b/llvm/include/llvm/Support/ModRef.h
@@ -147,18 +147,6 @@ template <typename LocationEnum> class MemoryEffectsBase {
     return MemoryEffectsBase(Location::InaccessibleMem, MR);
   }
 
-  /// Create MemoryEffectsBase that can only read inaccessible memory.
-  static MemoryEffectsBase
-  inaccessibleReadMemOnly(Location Loc = Location::InaccessibleMem) {
-    return MemoryEffectsBase(Loc, ModRefInfo::Ref);
-  }
-
-  /// Create MemoryEffectsBase that can only write inaccessible memory.
-  static MemoryEffectsBase
-  inaccessibleWriteMemOnly(Location Loc = Location::InaccessibleMem) {
-    return MemoryEffectsBase(Loc, ModRefInfo::Mod);
-  }
-
   /// Create MemoryEffectsBase that can only access errno memory.
   static MemoryEffectsBase errnoMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
     return MemoryEffectsBase(Location::ErrnoMem, MR);
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index d7ac109d3a7bf..c086f9f9585a2 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -701,14 +701,12 @@ lltok::Kind LLLexer::LexIdentifier() {
   KEYWORD(write);
   KEYWORD(readwrite);
   KEYWORD(argmem);
-  KEYWORD(fpmr);
-  KEYWORD(za);
+  KEYWORD(aarch64_fpmr);
+  KEYWORD(aarch64_za);
   KEYWORD(inaccessiblemem);
   KEYWORD(errnomem);
   KEYWORD(argmemonly);
   KEYWORD(inaccessiblememonly);
-  KEYWORD(inaccessiblewritememonly);
-  KEYWORD(inaccessiblereadmemonly);
   KEYWORD(inaccessiblemem_or_argmemonly);
   KEYWORD(nocapture);
   KEYWORD(address_is_null);
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 5d800b651c721..2c625bebe1416 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -1676,10 +1676,10 @@ static std::optional<MemoryEffects::Location> keywordToLoc(lltok::Kind Tok) {
     return IRMemLocation::InaccessibleMem;
   case lltok::kw_errnomem:
     return IRMemLocation::ErrnoMem;
-  case lltok::kw_fpmr:
+  case lltok::kw_aarch64_fpmr:
     return static_cast<IRMemLocation>(
         llvm::InaccessibleTargetMemLocation::AARCH64_FPMR);
-  case lltok::kw_za:
+  case lltok::kw_aarch64_za:
     return static_cast<IRMemLocation>(
         llvm::InaccessibleTargetMemLocation::AARCH64_ZA);
   default:
@@ -1687,29 +1687,6 @@ static std::optional<MemoryEffects::Location> keywordToLoc(lltok::Kind Tok) {
   }
 }
 
-bool LLParser::parseInaccessibleMemLocation(IRMemLocation &MemLoc) {
-  // It does not have location
-  if (Lex.getKind() != llvm::lltok::lparen)
-    return false;
-
-  Lex.Lex(); // eat '('
-
-  std::optional<IRMemLocation> LocOpt = keywordToLoc(Lex.getKind());
-  if (!LocOpt)
-    return tokError("invalid memory location keyword");
-
-  MemLoc = *LocOpt;
-
-  Lex.Lex(); // eat the keyword (e.g., 'fpmr', 'za')
-
-  if (Lex.getKind() != llvm::lltok::rparen)
-    return tokError("expected ')' after memory location");
-
-  Lex.Lex(); // eat ')'
-
-  return true; // success
-}
-
 /// parseFnAttributeValuePairs
 ///   ::= <attr> | <attr> '=' <value>
 bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B,
@@ -1720,11 +1697,6 @@ bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B,
   B.clear();
 
   MemoryEffects ME = MemoryEffects::unknown();
-  // Memory effects can span multiple locations, so we initialize a base
-  // MemoryEffects object once with default state, and then incrementally
-  // populate or combine effects for individual locations. This avoids
-  // rebuilding the full Data structure on each addition.
-  bool FirstME = true;
   while (true) {
     lltok::Kind Token = Lex.getKind();
     if (Token == lltok::rbrace)
@@ -1761,36 +1733,6 @@ bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B,
       continue;
     }
 
-    if (Token == lltok::kw_inaccessiblereadmemonly) {
-      Lex.Lex(); // eat the keyword
-
-      IRMemLocation MemLoc;
-      if (parseInaccessibleMemLocation(MemLoc)) {
-        if (!FirstME)
-          ME = ME.getWithModRef(MemLoc, ModRefInfo::Ref);
-        else
-          ME &= MemoryEffects::inaccessibleReadMemOnly(MemLoc);
-      } else
-        ME = MemoryEffects::inaccessibleReadMemOnly();
-      FirstME = false;
-      continue;
-    }
-
-    if (Token == lltok::kw_inaccessiblewritememonly) {
-      Lex.Lex(); // eat the keyword
-
-      IRMemLocation MemLoc;
-      if (parseInaccessibleMemLocation(MemLoc)) {
-        if (!FirstME)
-          ME = ME.getWithModRef(MemLoc, ModRefInfo::Mod);
-        else
-          ME &= MemoryEffects::inaccessibleWriteMemOnly(MemLoc);
-      } else
-        ME &= MemoryEffects::inaccessibleWriteMemOnly();
-      FirstME = false;
-      continue;
-    }
-
     Attribute::AttrKind Attr = tokenToAttribute(Token);
     if (Attr == Attribute::None) {
       if (!InAttrGrp)
@@ -2599,10 +2541,6 @@ static std::optional<ModRefInfo> keywordToModRef(lltok::Kind Tok) {
     return ModRefInfo::Mod;
   case lltok::kw_readwrite:
     return ModRefInfo::ModRef;
-  case lltok::kw_inaccessiblewritememonly:
-    return ModRefInfo::Mod;
-  case lltok::kw_inaccessiblereadmemonly:
-    return ModRefInfo::Ref;
   default:
     return std::nullopt;
   }
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index af936eff3834b..ec4281e2dc8a3 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -664,9 +664,9 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
         InaccessibleTargetMemLocation TargetLoc =
             static_cast<InaccessibleTargetMemLocation>(Loc);
         if (TargetLoc == InaccessibleTargetMemLocation::AARCH64_FPMR)
-          OS << "fpmr: ";
+          OS << "aarch64_fpmr: ";
         if (TargetLoc == InaccessibleTargetMemLocation::AARCH64_ZA)
-          OS << "za: ";
+          OS << "aarch64_za: ";
         break;
       }
       }
diff --git a/llvm/lib/Support/ModRef.cpp b/llvm/lib/Support/ModRef.cpp
index 82ae2b3acf831..dc0dafdbe7e49 100644
--- a/llvm/lib/Support/ModRef.cpp
+++ b/llvm/lib/Support/ModRef.cpp
@@ -53,9 +53,9 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, MemoryEffects ME) {
       InaccessibleTargetMemLocation TargetLoc =
           static_cast<InaccessibleTargetMemLocation>(Loc);
       if (TargetLoc == InaccessibleTargetMemLocation::AARCH64_FPMR)
-        OS << "FPMR: ";
+        OS << "AARCH64_FPMR: ";
       if (TargetLoc == InaccessibleTargetMemLocation::AARCH64_ZA)
-        OS << "ZA: ";
+        OS << "AARCH64_ZA: ";
       break;
     }
     }
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index df5086efd65df..66c91959065ba 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -3108,7 +3108,7 @@ llvm::IRMemLocation Record::getLocationTypeAsInt(StringRef FieldName) const {
   if (Name == "AArch64_FPMR")
     return static_cast<IRMemLocation>(
         llvm::InaccessibleTargetMemLocation::AARCH64_FPMR);
-  else if (Name == "ZA")
+  else if (Name == "AArch64_ZA")
     return static_cast<IRMemLocation>(
         llvm::InaccessibleTargetMemLocation::AARCH64_ZA);
   else if (Name == "InaccessibleMem")
diff --git a/llvm/test/Assembler/memory-attribute.ll b/llvm/test/Assembler/memory-attribute.ll
index 473468810768b..42f9b9f87e8b0 100644
--- a/llvm/test/Assembler/memory-attribute.ll
+++ b/llvm/test/Assembler/memory-attribute.ll
@@ -79,23 +79,27 @@ declare void @fn_argmem_read_inaccessiblemem_write()
 declare void @fn_argmem_read_inaccessiblemem_write_reordered()
     memory(inaccessiblemem: write, argmem: read)
 
-; CHECK: Function Attrs: memory(za: write)
-; CHECK: @fn_argmem_read_inaccessiblemem_write_za()
-declare void @fn_argmem_read_inaccessiblemem_write_za()
-    memory(za: inaccessiblewritememonly)
-
-; CHECK: Function Attrs: memory(za: read)
-; CHECK: @fn_argmem_read_inaccessiblemem_read_za()
-declare void @fn_argmem_read_inaccessiblemem_read_za()
-    memory(za: inaccessiblereadmemonly)
-
-; CHECK: Function Attrs: memory(fpmr: write)
-; CHECK: @fn_argmem_read_inaccessiblemem_write_fpmr()
-declare void @fn_argmem_read_inaccessiblemem_write_fpmr()
-    memory(fpmr: inaccessiblewritememonly)
-
-; CHECK: Function Attrs: memory(fpmr: read)
-; CHECK: @fn_argmem_read_inaccessiblemem_read_fpmr()
-declare void @fn_argmem_read_inaccessiblemem_read_fpmr()
-    memory(fpmr: inaccessiblereadmemonly)
-
+; CHECK: Function Attrs: memory(aarch64_za: write)
+; CHECK: @fn_inaccessiblemem_write_aarch64_za()
+declare void @fn_inaccessiblemem_write_aarch64_za()
+    memory(aarch64_za: write)
+
+; CHECK: Function Attrs: memory(aarch64_za: read)
+; CHECK: @fn_inaccessiblemem_read_aarch64_za()
+declare void @fn_inaccessiblemem_read_aarch64_za()
+    memory(aarch64_za: read)
+
+; CHECK: Function Attrs: memory(aarch64_fpmr: write)
+; CHECK: @fn_inaccessiblemem_write_aarch64_fpmr()
+declare void @fn_inaccessiblemem_write_aarch64_fpmr()
+    memory(aarch64_fpmr: write)
+
+; CHECK: Function Attrs: memory(aarch64_fpmr: read)
+; CHECK: @fn_inaccessiblemem_read_aarch64_fpmr()
+declare void @fn_inaccessiblemem_read_aarch64_fpmr()
+    memory(aarch64_fpmr: read)
+
+; CHECK: Function Attrs: memory(aarch64_fpmr: read, aarch64_za: write)
+; CHECK: @fn_inaccessiblemem_read_aarch64_fpmr_write_aarch64_za()
+declare void @fn_inaccessiblemem_read_aarch64_fpmr_write_aarch64_za()
+    memory(aarch64_fpmr: read, aarch64_za: write)
diff --git a/llvm/test/Bitcode/attributes.ll b/llvm/test/Bitcode/attributes.ll
index 7d2003fc73111..c8d39220fa91d 100644
--- a/llvm/test/Bitcode/attributes.ll
+++ b/llvm/test/Bitcode/attributes.ll
@@ -568,42 +568,6 @@ define void @captures(ptr captures(address) %p) {
   ret void
 }
 
-; CHECK: define void @fpmr_write() [[ATTR59:#.*]] {
-define void @fpmr_write() inaccessiblewritememonly(fpmr) {
-  ret void
-}
-
-; CHECK: define void @fpmr_read()  [[ATTR60:#.*]] {
-define void @fpmr_read() inaccessiblereadmemonly(fpmr) {
-  ret void
-}
-
-; CHECK: define void @za_write()  [[ATTR61:#.*]] {
-define void @za_write() inaccessiblewritememonly(za) {
-  ret void
-}
-
-; CHECK: define void @za_read()  [[ATTR62:#.*]] {
-define void @za_read() inaccessiblereadmemonly(za) {
-  ret void
-}
-
-; CHECK: define void @read_inaccessible()  [[ATTR63:#.*]] {
-define void @read_inaccessible() inaccessiblereadmemonly {
-  ret void
-}
-
-; CHECK: define void @write_inaccessible()  [[ATTR64:#.*]] {
-define void @write_inaccessible() inaccessiblewritememonly {
-  ret void
-}
-
-; CHECK: define void @za_read_write_fpmr()  [[ATTR65:#.*]] {
-define void @za_read_write_fpmr() inaccessiblereadmemonly(za) inaccessiblewritememonly(fpmr) {
-  ret void
-}
-
-
 ; CHECK: attributes #0 = { noreturn }
 ; CHECK: attributes #1 = { nounwind }
 ; CHECK: attributes #2 = { memory(none) }
@@ -663,11 +627,4 @@ define void @za_read_write_fpmr() inaccessiblereadmemonly(za) inaccessiblewritem
 ; CHECK: attributes [[SKIPPROFILE]] = { skipprofile }
 ; CHECK: attributes [[OPTDEBUG]] = { optdebug }
 ; CHECK: attributes [[NODIVERGENCESOURCE]] = { nodivergencesource }
-; CHECK: attributes [[ATTR59]] = { memory(fpmr: write) }
-; CHECK: attributes [[ATTR60]] = { memory(fpmr: read) }
-; CHECK: attributes [[ATTR61]] = { memory(za: write) }
-; CHECK: attributes [[ATTR62]] = { memory(za: read) }
-; CHECK: attributes [[ATTR63]] = { memory(inaccessiblemem: read) }
-; CHECK: attributes [[ATTR64]] = { memory(inaccessiblemem: write) }
-; CHECK: attributes [[ATTR65]] = { memory(fpmr: write, za: read) }
 ; CHECK: attributes #[[NOBUILTIN]] = { nobuiltin }
diff --git a/llvm/test/TableGen/intrinsic-attrs-fp8.td b/llvm/test/TableGen/intrinsic-attrs-fp8.td
index 53ff1dfe2b807..76d4ec6058f87 100644
--- a/llvm/test/TableGen/intrinsic-attrs-fp8.td
+++ b/llvm/test/TableGen/intrinsic-attrs-fp8.td
@@ -4,14 +4,19 @@ include "llvm/IR/Intrinsics.td"
 
 def int_aarch64_set_fpmr_2   : DefaultAttrsIntrinsic<[], [llvm_i64_ty], [IntrInaccessibleWriteMemOnly<AArch64_FPMR>]>;
 
-// CHECK:      static constexpr unsigned IntrinsicNameOffsetTable[] = {
-// CHECK-NEXT: 1, // not_intrinsic
-// CHECK-NEXT: 15, // llvm.aarch64.set.fpmr.2
+def int_aarch64_get_za_2   : DefaultAttrsIntrinsic<[], [llvm_i64_ty], [IntrInaccessibleReadMemOnly<AArch64_ZA>]>;
 
+def int_aarch64_get_fpmr_set_za   : DefaultAttrsIntrinsic<[], [llvm_i64_ty], [IntrInaccessibleReadMemOnly<AArch64_FPMR>, IntrInaccessibleWriteMemOnly<AArch64_ZA>]>;
 
-// CHECK: static AttributeSet getIntrinsicFnAttributeSet(LLVMContext &C, unsigned ID) {
-// CHECK-NEXT: switch (ID) {
-// CHECK-NEXT:  default: llvm_unreachable("Invalid attribute set number");
+// CHECK:    static constexpr unsigned IntrinsicNameOffsetTable[] = {
+// CHECK-NEXT:  1, // not_intrinsic
+// CHECK-NEXT:  15, // llvm.aarch64.get.fpmr.set.za
+// CHECK-NEXT:  44, // llvm.aarch64.get.za.2
+// CHECK-NEXT:  66, // llvm.aarch64.set.fpmr.2
+
+// CHECK:   static AttributeSet getIntrinsicFnAttributeSet(LLVMContext &C, unsigned ID) {
+// CHECK-NEXT:  switch (ID) {
+// CHECK-NEXT:    default: llvm_unreachable("Invalid attribute set number");
 // CHECK-NEXT:  case 0:
 // CHECK-NEXT:    return AttributeSet::get(C, {
 // CHECK-NEXT:      Attribute::get(C, Attribute::NoUnwind),
@@ -19,6 +24,31 @@ def int_aarch64_set_fpmr_2   : DefaultAttrsIntrinsic<[], [llvm_i64_ty], [IntrIna
 // CHECK-NEXT:      Attribute::get(C, Attribute::NoSync),
 // CHECK-NEXT:      Attribute::get(C, Attribute::NoFree),
 // CHECK-NEXT:      Attribute::get(C, Attribute::WillReturn),
-// CHECK-NEXT:      // ArgMem: NoModRef, InaccessibleMem: NoModRef, ErrnoMem: NoModRef, FPMR: Mod, ZA: NoModRef, Other: NoModRef
-// CHECK-NEXT:      Attribute::getWithMemoryEffects(C, MemoryEffects::createFromIntValue(128)),
+// CHECK-NEXT:      // ArgMem: ModRef, InaccessibleMem: ModRef, ErrnoMem: ModRef, AARCH64_FPMR: Ref, AARCH64_ZA: Mod, Other: ModRef
+// CHECK-NEXT:      Attribute::getWithMemoryEffects(C, MemoryEffects::createFromIntValue(3711)),
+// CHECK-NEXT:    });
+// CHECK-NEXT:  case 1:
+// CHECK-NEXT:    return AttributeSet::get(C, {
+// CHECK-NEXT:      Attribute::get(C, Attribute::NoUnwind),
+// CHECK-NEXT:      Attribute::get(C, Attribute::NoCallback),
+// CHECK-NEXT:      Attribute::get(C, Attribute::NoSync),
+// CHECK-NEXT:      Attribute::get(C, Attribute::NoFree),
+// CHECK-NEXT:      Attribute::get(C, Attribute::WillReturn),
+// CHECK-NEXT:      // ArgMem: ModRef, InaccessibleMem: ModRef, ErrnoMem: ModRef, AARCH64_FPMR: ModRef, AARCH64_ZA: Ref, Other: ModRef
+// CHECK-NEXT:      Attribute::getWithMemoryEffects(C, MemoryEffects::createFromIntValue(3583)),
 // CHECK-NEXT:    });
+// CHECK-NEXT:  case 2:
+// CHECK-NEXT:    return AttributeSet::get(C, {
+// CHECK-NEXT:      Attribute::get(C, Attribute::NoUnwind),
+// CHECK-NEXT:      Attribute::get(C, Attribute::NoCallback),
+// CHECK-NEXT:      Attribute::get(C, Attribute::NoSync),
+// CHECK-NEXT:      Attribute::get(C, Attribute::NoFree),
+// CHECK-NEXT:      Attribute::get(C, Attribute::WillReturn),
+// CHECK-NEXT:      // ArgMem: ModRef, InaccessibleMem: ModRef, ErrnoMem: ModRef, AARCH64_FPMR: Mod, AARCH64_ZA: ModRef, Other: ModRef
+// CHECK-NEXT:      Attribute::getWithMemoryEffects(C, MemoryEffects::createFromIntValue(4031)),
+
+// CHECK: static constexpr uint16_t IntrinsicsToAttributesMap[] = {
+// CHECK-NEXT:    0 << 8 | 0, // llvm.aarch64.get.fpmr.set.za
+// CHECK-NEXT:    1 << 8 | 0, // llvm.aarch64.get.za.2
+// CHECK-NEXT:    2 << 8 | 0, // llvm.aarch64.set.fpmr.2
+// CHECK-NEXT:};
diff --git a/llvm/unittests/Support/ModRefTest.cpp b/llvm/unittests/Support/ModRefTest.cpp
index cbdf752978555..7aa473ad20336 100644
--- a/llvm/unittests/Support/ModRefTest.cpp
+++ b/llvm/unittests/Support/ModRefTest.cpp
@@ -21,7 +21,8 @@ TEST(ModRefTest, PrintMemoryEffects) {
   raw_string_ostream OS(S);
   OS << MemoryEffects::none();
   EXPECT_EQ(S, "ArgMem: NoModRef, InaccessibleMem: NoModRef, ErrnoMem: "
-               "NoModRef, FPMR: NoModRef, ZA: NoModRef, Other: NoModRef");
+               "NoModRef, AARCH64_FPMR: NoModRef, AARCH64_ZA: NoModRef, Other: "
+               "NoModRef");
 }
 
 } // namespace
diff --git a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
index f53915642ac6d..ad6a5344e4b7c 100644
--- a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
+++ b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
@@ -376,10 +376,10 @@ void CodeGenIntrinsic::setProperty(const Record *R) {
     ME &= MemoryEffects::inaccessibleMemOnly();
   else if (R->isSubClassOf("IntrInaccessibleReadMemOnly")) {
     llvm::IRMemLocation Loc = R->getLocationTypeAsInt("Loc");
-    ME &= MemoryEffects::inaccessibleWriteMemOnly(Loc);
+    ME = ME.getWithModRef(Loc, ModRefInfo::Ref);
   } else if (R->isSubClassOf("IntrInaccessibleWriteMemOnly")) {
     llvm::IRMemLocation Loc = R->getLocationTypeAsInt("Loc");
-    ME &= MemoryEffects::inaccessibleWriteMemOnly(Loc);
+    ME = ME.getWithModRef(Loc, ModRefInfo::Mod);
   } else if (R->getName() == "IntrInaccessibleMemOrArgMemOnly")
     ME &= MemoryEffects::inaccessibleOrArgMemOnly();
   else if (R->getName() == "Commutative")



More information about the llvm-commits mailing list