Author: CarolineConcatto
Date: 2025-11-18T11:10:58Z
New Revision: 200793ac218735e2186e9f2850f8e74a28c36a27

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

LOG: Extend MemoryEffects to Support Target-Specific Memory Locations (#148650)

This patch introduces preliminary support for additional memory
locations.
They are: target_mem0 and target_mem1 and they model memory locations
that cannot be represented with existing memory locations.

It was a solution suggested in :
https://discourse.llvm.org/t/rfc-improving-fpmr-handling-for-fp8-intrinsics-in-llvm/86868/6

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

Added: 
    llvm/test/TableGen/target-mem-intrinsic-attrs.td

Modified: 
    clang/test/CodeGen/sanitize-metadata-nosanitize.c
    clang/test/CodeGenOpenCL/convergent.cl
    llvm/docs/LangRef.rst
    llvm/include/llvm/AsmParser/LLToken.h
    llvm/include/llvm/IR/Intrinsics.td
    llvm/include/llvm/Support/ModRef.h
    llvm/lib/AsmParser/LLLexer.cpp
    llvm/lib/AsmParser/LLParser.cpp
    llvm/lib/IR/Attributes.cpp
    llvm/lib/Support/ModRef.cpp
    llvm/test/Assembler/memory-attribute.ll
    llvm/test/Bitcode/memory-attribute-upgrade.ll
    llvm/test/Transforms/FunctionAttrs/argmemonly.ll
    llvm/test/Transforms/FunctionAttrs/nocapture.ll
    llvm/test/Transforms/FunctionAttrs/read-write-scc.ll
    llvm/test/Transforms/FunctionAttrs/readattrs.ll
    llvm/test/Transforms/FunctionAttrs/writeonly.ll
    llvm/test/Transforms/InferFunctionAttrs/norecurse_debug.ll
    llvm/test/Transforms/LowerTypeTests/cfi-nounwind-direct-call.ll
    llvm/test/Transforms/SCCP/ipscp-drop-argmemonly.ll
    llvm/unittests/Support/ModRefTest.cpp
    llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
    llvm/utils/TableGen/Basic/CodeGenIntrinsics.h
    llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp
    mlir/test/Target/LLVMIR/llvmir.mlir

Removed: 
    


################################################################################
diff  --git a/clang/test/CodeGen/sanitize-metadata-nosanitize.c 
b/clang/test/CodeGen/sanitize-metadata-nosanitize.c
index f2672d7f89157..74b5c9b03754f 100644
--- a/clang/test/CodeGen/sanitize-metadata-nosanitize.c
+++ b/clang/test/CodeGen/sanitize-metadata-nosanitize.c
@@ -10,7 +10,7 @@
 // CHECK: @llvm.global_ctors = appending global [2 x { i32, ptr, ptr }] [{ 
i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_covered2.module_ctor, ptr 
@__sanitizer_metadata_covered2.module_ctor }, { i32, ptr, ptr } { i32 2, ptr 
@__sanitizer_metadata_atomics2.module_ctor, ptr 
@__sanitizer_metadata_atomics2.module_ctor }]
 // CHECK: @llvm.global_dtors = appending global [2 x { i32, ptr, ptr }] [{ 
i32, ptr, ptr } { i32 2, ptr @__sanitizer_metadata_covered2.module_dtor, ptr 
@__sanitizer_metadata_covered2.module_dtor }, { i32, ptr, ptr } { i32 2, ptr 
@__sanitizer_metadata_atomics2.module_dtor, ptr 
@__sanitizer_metadata_atomics2.module_dtor }]
 //.
-// CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync 
nounwind willreturn memory(write, argmem: none, inaccessiblemem: none)
+// CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync 
nounwind willreturn memory(write, argmem: none, inaccessiblemem: none, 
target_mem0: none, target_mem1: none)
 // CHECK-LABEL: define dso_local void @escape(
 // CHECK-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] 
!pcsections [[META6:![0-9]+]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
@@ -21,7 +21,7 @@ __attribute__((noinline, not_tail_called)) void escape(const 
volatile void *p) {
   sink = p;
 }
 
-// CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn 
memory(write, argmem: readwrite, inaccessiblemem: none)
+// CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn 
memory(write, argmem: readwrite, inaccessiblemem: none, target_mem0: none, 
target_mem1: none)
 // CHECK-LABEL: define dso_local i32 @normal_function(
 // CHECK-SAME: ptr noundef [[X:%.*]], ptr noundef readonly captures(none) 
[[Y:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] !pcsections [[META8:![0-9]+]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
@@ -38,7 +38,7 @@ int normal_function(int *x, int *y) {
   return *y;
 }
 
-// CHECK: Function Attrs: disable_sanitizer_instrumentation mustprogress 
nofree norecurse nounwind willreturn memory(write, argmem: readwrite, 
inaccessiblemem: none)
+// CHECK: Function Attrs: disable_sanitizer_instrumentation mustprogress 
nofree norecurse nounwind willreturn memory(write, argmem: readwrite, 
inaccessiblemem: none, target_mem0: none, target_mem1: none)
 // CHECK-LABEL: define dso_local i32 @test_disable_sanitize_instrumentation(
 // CHECK-SAME: ptr noundef [[X:%.*]], ptr noundef readonly captures(none) 
[[Y:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
@@ -55,7 +55,7 @@ __attribute__((disable_sanitizer_instrumentation)) int 
test_disable_sanitize_ins
   return *y;
 }
 
-// CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn 
memory(write, argmem: readwrite, inaccessiblemem: none)
+// CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn 
memory(write, argmem: readwrite, inaccessiblemem: none, target_mem0: none, 
target_mem1: none)
 // CHECK-LABEL: define dso_local i32 @test_no_sanitize_thread(
 // CHECK-SAME: ptr noundef [[X:%.*]], ptr noundef readonly captures(none) 
[[Y:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] !pcsections [[META14:![0-9]+]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
@@ -72,7 +72,7 @@ __attribute__((no_sanitize("thread"))) int 
test_no_sanitize_thread(int *x, int *
   return *y;
 }
 
-// CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn 
memory(write, argmem: readwrite, inaccessiblemem: none)
+// CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn 
memory(write, argmem: readwrite, inaccessiblemem: none, target_mem0: none, 
target_mem1: none)
 // CHECK-LABEL: define dso_local i32 @test_no_sanitize_all(
 // CHECK-SAME: ptr noundef [[X:%.*]], ptr noundef readonly captures(none) 
[[Y:%.*]]) local_unnamed_addr #[[ATTR3]] !pcsections [[META14]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
@@ -89,10 +89,10 @@ __attribute__((no_sanitize("all"))) int 
test_no_sanitize_all(int *x, int *y) {
   return *y;
 }
 //.
-// CHECK: attributes #[[ATTR0]] = { mustprogress nofree noinline norecurse 
nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: none) 
"min-legal-vector-width"="0" "no-trapping-math"="true" 
"stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" 
}
-// CHECK: attributes #[[ATTR1]] = { mustprogress nofree norecurse nounwind 
willreturn memory(write, argmem: readwrite, inaccessiblemem: none) 
"min-legal-vector-width"="0" "no-trapping-math"="true" 
"stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" 
}
-// CHECK: attributes #[[ATTR2]] = { disable_sanitizer_instrumentation 
mustprogress nofree norecurse nounwind willreturn memory(write, argmem: 
readwrite, inaccessiblemem: none) "min-legal-vector-width"="0" 
"no-trapping-math"="true" "stack-protector-buffer-size"="8" 
"target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
-// CHECK: attributes #[[ATTR3]] = { mustprogress nofree norecurse nounwind 
willreturn memory(write, argmem: readwrite, inaccessiblemem: none) 
"min-legal-vector-width"="0" "no-trapping-math"="true" "no_sanitize_thread" 
"stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" 
}
+// CHECK: attributes #[[ATTR0]] = { mustprogress nofree noinline norecurse 
nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: none, 
target_mem0: none, target_mem1: none) "min-legal-vector-width"="0" 
"no-trapping-math"="true" "stack-protector-buffer-size"="8" 
"target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
+// CHECK: attributes #[[ATTR1]] = { mustprogress nofree norecurse nounwind 
willreturn memory(write, argmem: readwrite, inaccessiblemem: none, target_mem0: 
none, target_mem1: none) "min-legal-vector-width"="0" "no-trapping-math"="true" 
"stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" 
}
+// CHECK: attributes #[[ATTR2]] = { disable_sanitizer_instrumentation 
mustprogress nofree norecurse nounwind willreturn memory(write, argmem: 
readwrite, inaccessiblemem: none, target_mem0: none, target_mem1: none) 
"min-legal-vector-width"="0" "no-trapping-math"="true" 
"stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" 
}
+// CHECK: attributes #[[ATTR3]] = { mustprogress nofree norecurse nounwind 
willreturn memory(write, argmem: readwrite, inaccessiblemem: none, target_mem0: 
none, target_mem1: none) "min-legal-vector-width"="0" "no-trapping-math"="true" 
"no_sanitize_thread" "stack-protector-buffer-size"="8" 
"target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
 // CHECK: attributes #[[ATTR4:[0-9]+]] = { nounwind 
"target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
 //.
 // CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}

diff  --git a/clang/test/CodeGenOpenCL/convergent.cl 
b/clang/test/CodeGenOpenCL/convergent.cl
index 53a35a4f73119..99d9ee74e669b 100644
--- a/clang/test/CodeGenOpenCL/convergent.cl
+++ b/clang/test/CodeGenOpenCL/convergent.cl
@@ -133,7 +133,7 @@ kernel void assume_convergent_asm()
   __asm__ volatile("s_barrier");
 }
 
-// CHECK: attributes #0 = { nofree noinline norecurse nounwind "
+// CHECK: attributes #0 = { nofree noinline norecurse nounwind 
memory(readwrite, target_mem0: none, target_mem1: none) "
 // CHECK: attributes #1 = { {{[^}]*}}convergent{{[^}]*}} }
 // CHECK: attributes #2 = { {{[^}]*}}convergent{{[^}]*}} }
 // CHECK: attributes #3 = { {{[^}]*}}convergent noduplicate{{[^}]*}} }

diff  --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 1a8886dd79c9c..734778f73af5f 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -2178,7 +2178,8 @@ For example:
     This attribute specifies the possible memory effects of the call-site or
     function. It allows specifying the possible access kinds (``none``,
     ``read``, ``write``, or ``readwrite``) for the possible memory location
-    kinds (``argmem``, ``inaccessiblemem``, ``errnomem``, as well as a 
default).
+    kinds (``argmem``, ``inaccessiblemem``, ``errnomem``, ``target_mem0``,
+    ``target_mem1``, as well as a default).
     It is best understood by example:
 
     - ``memory(none)``: Does not access any memory.
@@ -2220,6 +2221,11 @@ For example:
       accessing inaccessible memory itself). Inaccessible memory is often used
       to model control dependencies of intrinsics.
     - ``errnomem``: This refers to accesses to the ``errno`` variable.
+    - ``target_mem#`` : These refer to target specific state that cannot be
+      accessed by any other means. # is a number between 0 and 1 inclusive.
+      Note: The target_mem locations are experimental and intended for internal
+      testing only. They must not be used in production code.
+
     - The default access kind (specified without a location prefix) applies to
       all locations that haven't been specified explicitly, including those 
that
       don't currently have a dedicated location kind (e.g., accesses to globals

diff  --git a/llvm/include/llvm/AsmParser/LLToken.h 
b/llvm/include/llvm/AsmParser/LLToken.h
index 6de99fe182ad9..24f84cfa09e34 100644
--- a/llvm/include/llvm/AsmParser/LLToken.h
+++ b/llvm/include/llvm/AsmParser/LLToken.h
@@ -206,6 +206,8 @@ enum Kind {
   kw_readwrite,
   kw_argmem,
   kw_inaccessiblemem,
+  kw_target_mem0,
+  kw_target_mem1,
   kw_errnomem,
 
   // Legacy attributes:

diff  --git a/llvm/include/llvm/IR/Intrinsics.td 
b/llvm/include/llvm/IR/Intrinsics.td
index 27f404a1be65c..8f3cc54747074 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -54,6 +54,25 @@ def IntrInaccessibleMemOnly : IntrinsicProperty;
 // by the module being compiled. This is a weaker form of IntrArgMemOnly.
 def IntrInaccessibleMemOrArgMemOnly : IntrinsicProperty;
 
+// Tablegen representation of IRMemLocation.
+class IntrinsicMemoryLocation;
+
+// TODO: Populate with all IRMemLocation enum values and update
+// getValueAsIRMemLocation accordingly.
+def InaccessibleMem : IntrinsicMemoryLocation;
+def TargetMem0 : IntrinsicMemoryLocation;
+def TargetMem1 : IntrinsicMemoryLocation;
+
+// The list of IRMemoryLocations that are read from.
+class IntrRead<list<IntrinsicMemoryLocation> idx> : IntrinsicProperty {
+   list<IntrinsicMemoryLocation>  MemLoc=idx;
+}
+
+//  The list of IRMemoryLocations that are write to.
+class IntrWrite<list<IntrinsicMemoryLocation> idx> : IntrinsicProperty {
+   list<IntrinsicMemoryLocation> MemLoc=idx;
+}
+
 // Commutative - This intrinsic is commutative: X op Y == Y op X.
 def Commutative : IntrinsicProperty;
 

diff  --git a/llvm/include/llvm/Support/ModRef.h 
b/llvm/include/llvm/Support/ModRef.h
index 71f3b5bcb9c2b..34f116e478966 100644
--- a/llvm/include/llvm/Support/ModRef.h
+++ b/llvm/include/llvm/Support/ModRef.h
@@ -66,10 +66,15 @@ enum class IRMemLocation {
   ErrnoMem = 2,
   /// Any other memory.
   Other = 3,
+  /// Represents target specific state.
+  TargetMem0 = 4,
+  TargetMem1 = 5,
 
   /// Helpers to iterate all locations in the MemoryEffectsBase class.
   First = ArgMem,
-  Last = Other,
+  FirstTarget = TargetMem0,
+  // TargetMem IDs must be at the end of the list.
+  Last = TargetMem1,
 };
 
 template <typename LocationEnum> class MemoryEffectsBase {

diff  --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index 7a6c19ece92ac..ebca344ae7b93 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -707,6 +707,8 @@ lltok::Kind LLLexer::LexIdentifier() {
   KEYWORD(write);
   KEYWORD(readwrite);
   KEYWORD(argmem);
+  KEYWORD(target_mem0);
+  KEYWORD(target_mem1);
   KEYWORD(inaccessiblemem);
   KEYWORD(errnomem);
   KEYWORD(argmemonly);

diff  --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 8e3ce4990f437..921462e28a467 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -2552,6 +2552,10 @@ static std::optional<MemoryEffects::Location> 
keywordToLoc(lltok::Kind Tok) {
     return IRMemLocation::InaccessibleMem;
   case lltok::kw_errnomem:
     return IRMemLocation::ErrnoMem;
+  case lltok::kw_target_mem0:
+    return IRMemLocation::TargetMem0;
+  case lltok::kw_target_mem1:
+    return IRMemLocation::TargetMem1;
   default:
     return std::nullopt;
   }

diff  --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index 4ac2ebd55dcac..fe6d3e5edeb09 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -656,6 +656,12 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
         break;
       case IRMemLocation::Other:
         llvm_unreachable("This is represented as the default access kind");
+      case IRMemLocation::TargetMem0:
+        OS << "target_mem0: ";
+        break;
+      case IRMemLocation::TargetMem1:
+        OS << "target_mem1: ";
+        break;
       }
       OS << getModRefStr(MR);
     }

diff  --git a/llvm/lib/Support/ModRef.cpp b/llvm/lib/Support/ModRef.cpp
index 2bb9bc945bd2e..1083c72902c0b 100644
--- a/llvm/lib/Support/ModRef.cpp
+++ b/llvm/lib/Support/ModRef.cpp
@@ -49,6 +49,12 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, MemoryEffects 
ME) {
     case IRMemLocation::Other:
       OS << "Other: ";
       break;
+    case IRMemLocation::TargetMem0:
+      OS << "TargetMem0: ";
+      break;
+    case IRMemLocation::TargetMem1:
+      OS << "TargetMem1: ";
+      break;
     }
     OS << ME.getModRef(Loc);
   });

diff  --git a/llvm/test/Assembler/memory-attribute.ll 
b/llvm/test/Assembler/memory-attribute.ll
index effd4ce7c4548..4c86f8df0e6c1 100644
--- a/llvm/test/Assembler/memory-attribute.ll
+++ b/llvm/test/Assembler/memory-attribute.ll
@@ -78,3 +78,58 @@ 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(target_mem0: write)
+; CHECK: @fn_write_mem_target0()
+declare void @fn_write_mem_target0()
+    memory(target_mem0: write)
+
+; CHECK: Function Attrs: memory(target_mem0: read)
+; CHECK: @fn_read_mem_target0()
+declare void @fn_read_mem_target0()
+    memory(target_mem0: read)
+
+; CHECK: Function Attrs: memory(target_mem1: write)
+; CHECK: @fn_write_target_mem1()
+declare void @fn_write_target_mem1()
+    memory(target_mem1: write)
+
+; CHECK: Function Attrs: memory(target_mem1: read)
+; CHECK: @fn_read_target_mem1()
+declare void @fn_read_target_mem1()
+    memory(target_mem1: read)
+
+; CHECK: Function Attrs: memory(target_mem0: read, target_mem1: write)
+; CHECK: @fn_read_target_mem0_write_mem_target1()
+declare void @fn_read_target_mem0_write_mem_target1()
+    memory(target_mem0: read, target_mem1: write)
+
+; CHECK: Function Attrs: memory(inaccessiblemem: write)
+; CHECK: @fn_inaccessiblemem_write_new()
+declare void @fn_inaccessiblemem_write_new()
+    memory(inaccessiblemem: write)
+
+; CHECK: Function Attrs: memory(inaccessiblemem: read, target_mem0: read, 
target_mem1: read)
+; CHECK: @fn_inaccessiblemem_target_mem0_1read()
+declare void @fn_inaccessiblemem_target_mem0_1read()
+    memory(inaccessiblemem: read, target_mem0: read, target_mem1: read)
+
+; CHECK: Function Attrs: memory(target_mem0: read)
+; CHECK: @fn_inaccessiblemem_none_target_mem0_read()
+declare void @fn_inaccessiblemem_none_target_mem0_read()
+    memory(inaccessiblemem: none, target_mem0: read)
+
+; CHECK: Function Attrs: memory(write, inaccessiblemem: read)
+; CHECK: @fn_write_inaccessiblemem_read_target_mem0_write
+declare void @fn_write_inaccessiblemem_read_target_mem0_write()
+    memory(write, inaccessiblemem: read, target_mem0: write)
+
+; CHECK: Function Attrs: memory(write, target_mem0: read)
+; CHECK: @fn_write_inaccessiblemem_write_target_mem0_read()
+declare void @fn_write_inaccessiblemem_write_target_mem0_read()
+    memory(write, inaccessiblemem: write, target_mem0: read)
+
+; CHECK: Function Attrs: memory(write, target_mem0: read)
+; CHECK: @fn_write_target_mem0_readwrite()
+declare void @fn_write_target_mem0_readwrite()
+    memory(write, target_mem0: read)

diff  --git a/llvm/test/Bitcode/memory-attribute-upgrade.ll 
b/llvm/test/Bitcode/memory-attribute-upgrade.ll
index 915b62a88935d..334a344b96f7f 100644
--- a/llvm/test/Bitcode/memory-attribute-upgrade.ll
+++ b/llvm/test/Bitcode/memory-attribute-upgrade.ll
@@ -1,7 +1,7 @@
 ; RUN: llvm-dis < %S/Inputs/memory-attribute-upgrade.bc | FileCheck %s
 
-; CHECK: ; Function Attrs: memory(write, argmem: read)
+; CHECK: ; Function Attrs: memory(write, argmem: read, target_mem0: none, 
target_mem1: none)
 ; CHECK-NEXT: define void @test_any_write_argmem_read(ptr %p)
 
-; CHECK: ; Function Attrs: memory(read, argmem: readwrite, inaccessiblemem: 
none)
+; CHECK: ; Function Attrs: memory(read, argmem: readwrite, inaccessiblemem: 
none, target_mem0: none, target_mem1: none)
 ; CHECK-NEXT: define void @test_any_read_argmem_readwrite(ptr %p)

diff  --git a/llvm/test/TableGen/target-mem-intrinsic-attrs.td 
b/llvm/test/TableGen/target-mem-intrinsic-attrs.td
new file mode 100644
index 0000000000000..fc9c3321ad9e9
--- /dev/null
+++ b/llvm/test/TableGen/target-mem-intrinsic-attrs.td
@@ -0,0 +1,78 @@
+// RUN: llvm-tblgen -gen-intrinsic-impl -I %p/../../include 
-DTEST_INTRINSICS_SUPPRESS_DEFS %s | FileCheck %s
+
+include "llvm/IR/Intrinsics.td"
+
+def int_aarch64_get_target_mem0_mem1   : DefaultAttrsIntrinsic<[], 
[llvm_i64_ty], [IntrReadMem, IntrRead<[TargetMem0, TargetMem1]>]>;
+
+def int_aarch64_get_target_mem0_set_target_mem1   : DefaultAttrsIntrinsic<[], 
[llvm_i64_ty], [IntrRead<[TargetMem0]>, IntrWrite<[TargetMem1]>]>;
+
+def int_aarch64_get_target_mem1   : DefaultAttrsIntrinsic<[], [llvm_i64_ty], 
[IntrReadMem,  IntrRead<[TargetMem1]>]>;
+
+def int_aarch64_get_target_mem1_set_target_mem1   : DefaultAttrsIntrinsic<[], 
[llvm_i64_ty], [IntrRead<[TargetMem1]>, IntrWrite<[TargetMem1]>]>;
+
+def int_aarch64_set_inaccessible_mem   : DefaultAttrsIntrinsic<[], 
[llvm_i64_ty], [IntrWriteMem, IntrWrite<[InaccessibleMem]>]>;
+
+def int_aarch64_set_target_mem0   : DefaultAttrsIntrinsic<[], [llvm_i64_ty], 
[IntrWriteMem, IntrWrite<[TargetMem0]>]>;
+
+// 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: // llvm.aarch64.get.target.mem0.mem1
+// 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, Other: NoModRef, TargetMem0: Ref, TargetMem1: Ref
+// CHECK-NEXT:      Attribute::getWithMemoryEffects(C, 
MemoryEffects::createFromIntValue(1280)),
+// CHECK-NEXT:    });
+// CHECK-NEXT:  case 1: // llvm.aarch64.get.target.mem0.set.target.mem1
+// 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, Other: NoModRef, TargetMem0: Ref, TargetMem1: Mod
+// CHECK-NEXT:      Attribute::getWithMemoryEffects(C, 
MemoryEffects::createFromIntValue(2304)),
+// CHECK-NEXT:    });
+// CHECK-NEXT:  case 2: // llvm.aarch64.get.target.mem1
+// 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, Other: NoModRef, TargetMem0: NoModRef, TargetMem1: Ref
+// CHECK-NEXT:      Attribute::getWithMemoryEffects(C, 
MemoryEffects::createFromIntValue(1024)),
+// CHECK-NEXT:    });
+// CHECK-NEXT:  case 3: // llvm.aarch64.get.target.mem1.set.target.mem1
+// 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, Other: NoModRef, TargetMem0: NoModRef, TargetMem1: ModRef
+// CHECK-NEXT:      Attribute::getWithMemoryEffects(C, 
MemoryEffects::createFromIntValue(3072)),
+// CHECK-NEXT:    });
+// CHECK-NEXT:  case 4: // llvm.aarch64.set.inaccessible.mem
+// 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: Mod, ErrnoMem: 
NoModRef, Other: NoModRef, TargetMem0: NoModRef, TargetMem1: NoModRef
+// CHECK-NEXT:      Attribute::getWithMemoryEffects(C, 
MemoryEffects::createFromIntValue(8)),
+// CHECK-NEXT:    });
+// CHECK-NEXT:  case 5: // llvm.aarch64.set.target.mem0
+// 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, Other: NoModRef, TargetMem0: Mod, TargetMem1: NoModRef
+// CHECK-NEXT:      Attribute::getWithMemoryEffects(C, 
MemoryEffects::createFromIntValue(512)),

diff  --git a/llvm/test/Transforms/FunctionAttrs/argmemonly.ll 
b/llvm/test/Transforms/FunctionAttrs/argmemonly.ll
index 42e0e94c1cee3..4ff36c0dbdc3f 100644
--- a/llvm/test/Transforms/FunctionAttrs/argmemonly.ll
+++ b/llvm/test/Transforms/FunctionAttrs/argmemonly.ll
@@ -56,7 +56,7 @@ entry:
 }
 
 define i32 @test_read_global() {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(read, argmem: none, inaccessiblemem: none)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(read, argmem: none, inaccessiblemem: none, target_mem0: none, 
target_mem1: none)
 ; FNATTRS-LABEL: define i32 @test_read_global
 ; FNATTRS-SAME: () #[[ATTR2:[0-9]+]] {
 ; FNATTRS-NEXT:  entry:
@@ -76,7 +76,7 @@ entry:
 }
 
 define i32 @test_read_loaded_ptr(ptr %ptr) {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(read, inaccessiblemem: none)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(read, inaccessiblemem: none, target_mem0: none, target_mem1: 
none)
 ; FNATTRS-LABEL: define i32 @test_read_loaded_ptr
 ; FNATTRS-SAME: (ptr readonly captures(none) [[PTR:%.*]]) #[[ATTR3:[0-9]+]] {
 ; FNATTRS-NEXT:  entry:
@@ -119,7 +119,7 @@ entry:
 }
 
 define void @test_write_global() {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(write, argmem: none, inaccessiblemem: none)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(write, argmem: none, inaccessiblemem: none, target_mem0: 
none, target_mem1: none)
 ; FNATTRS-LABEL: define void @test_write_global
 ; FNATTRS-SAME: () #[[ATTR5:[0-9]+]] {
 ; FNATTRS-NEXT:  entry:
@@ -243,7 +243,7 @@ declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)
 @arr = global [32 x i8] zeroinitializer
 
 define void @test_memcpy_src_global(ptr %dst) {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(readwrite, inaccessiblemem: none)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(readwrite, inaccessiblemem: none, target_mem0: none, 
target_mem1: none)
 ; FNATTRS-LABEL: define void @test_memcpy_src_global
 ; FNATTRS-SAME: (ptr writeonly captures(none) initializes((0, 32)) 
[[DST:%.*]]) #[[ATTR11:[0-9]+]] {
 ; FNATTRS-NEXT:  entry:
@@ -263,7 +263,7 @@ entry:
 }
 
 define void @test_memcpy_dst_global(ptr %src) {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(readwrite, inaccessiblemem: none)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(readwrite, inaccessiblemem: none, target_mem0: none, 
target_mem1: none)
 ; FNATTRS-LABEL: define void @test_memcpy_dst_global
 ; FNATTRS-SAME: (ptr readonly captures(none) [[SRC:%.*]]) #[[ATTR11]] {
 ; FNATTRS-NEXT:  entry:
@@ -388,7 +388,7 @@ define void @test_inaccessibleorargmemonly_readwrite(ptr 
%arg) {
 }
 
 define void @test_recursive_argmem_read(ptr %p) {
-; FNATTRS: Function Attrs: nofree nosync nounwind memory(read, 
inaccessiblemem: none)
+; FNATTRS: Function Attrs: nofree nosync nounwind memory(read, 
inaccessiblemem: none, target_mem0: none, target_mem1: none)
 ; FNATTRS-LABEL: define void @test_recursive_argmem_read
 ; FNATTRS-SAME: (ptr readonly captures(none) [[P:%.*]]) #[[ATTR16:[0-9]+]] {
 ; FNATTRS-NEXT:    [[PVAL:%.*]] = load ptr, ptr [[P]], align 8
@@ -408,7 +408,7 @@ define void @test_recursive_argmem_read(ptr %p) {
 }
 
 define void @test_recursive_argmem_readwrite(ptr %p) {
-; FNATTRS: Function Attrs: nofree nosync nounwind memory(readwrite, 
inaccessiblemem: none)
+; FNATTRS: Function Attrs: nofree nosync nounwind memory(readwrite, 
inaccessiblemem: none, target_mem0: none, target_mem1: none)
 ; FNATTRS-LABEL: define void @test_recursive_argmem_readwrite
 ; FNATTRS-SAME: (ptr captures(none) [[P:%.*]]) #[[ATTR17:[0-9]+]] {
 ; FNATTRS-NEXT:    [[PVAL:%.*]] = load ptr, ptr [[P]], align 8
@@ -454,7 +454,7 @@ define void @test_recursive_argmem_read_alloca(ptr %p) {
 }
 
 define void @test_scc_argmem_read_1(ptr %p) {
-; FNATTRS: Function Attrs: nofree nosync nounwind memory(read, 
inaccessiblemem: none)
+; FNATTRS: Function Attrs: nofree nosync nounwind memory(read, 
inaccessiblemem: none, target_mem0: none, target_mem1: none)
 ; FNATTRS-LABEL: define void @test_scc_argmem_read_1
 ; FNATTRS-SAME: (ptr readonly captures(none) [[P:%.*]]) #[[ATTR16]] {
 ; FNATTRS-NEXT:    [[PVAL:%.*]] = load ptr, ptr [[P]], align 8
@@ -474,7 +474,7 @@ define void @test_scc_argmem_read_1(ptr %p) {
 }
 
 define void @test_scc_argmem_read_2(ptr %p) {
-; FNATTRS: Function Attrs: nofree nosync nounwind memory(read, 
inaccessiblemem: none)
+; FNATTRS: Function Attrs: nofree nosync nounwind memory(read, 
inaccessiblemem: none, target_mem0: none, target_mem1: none)
 ; FNATTRS-LABEL: define void @test_scc_argmem_read_2
 ; FNATTRS-SAME: (ptr readonly captures(none) [[P:%.*]]) #[[ATTR16]] {
 ; FNATTRS-NEXT:    call void @test_scc_argmem_read_1(ptr [[P]])
@@ -518,7 +518,7 @@ entry:
 
 ; FIXME: This could be `memory(argmem: read)`.
 define i64 @select_
diff erent_obj(i1 %c, ptr %p, ptr %p2) {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(read, inaccessiblemem: none)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(read, inaccessiblemem: none, target_mem0: none, target_mem1: 
none)
 ; FNATTRS-LABEL: define i64 @select_
diff erent_obj
 ; FNATTRS-SAME: (i1 [[C:%.*]], ptr readonly captures(none) [[P:%.*]], ptr 
readonly captures(none) [[P2:%.*]]) #[[ATTR3]] {
 ; FNATTRS-NEXT:  entry:
@@ -580,7 +580,7 @@ join:
 
 ; FIXME: This could be `memory(argmem: read)`.
 define i64 @phi_
diff erent_obj(i1 %c, ptr %p, ptr %p2) {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(read, inaccessiblemem: none)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(read, inaccessiblemem: none, target_mem0: none, target_mem1: 
none)
 ; FNATTRS-LABEL: define i64 @phi_
diff erent_obj
 ; FNATTRS-SAME: (i1 [[C:%.*]], ptr readonly captures(none) [[P:%.*]], ptr 
readonly captures(none) [[P2:%.*]]) #[[ATTR3]] {
 ; FNATTRS-NEXT:  entry:

diff  --git a/llvm/test/Transforms/FunctionAttrs/nocapture.ll 
b/llvm/test/Transforms/FunctionAttrs/nocapture.ll
index 8113ba65fe422..b5b14f571d47d 100644
--- a/llvm/test/Transforms/FunctionAttrs/nocapture.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nocapture.ll
@@ -20,7 +20,7 @@ define ptr @c1(ptr %q) {
 
 ; It would also be acceptable to mark %q as readnone. Update @c3 too.
 define void @c2(ptr %q) {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(write, argmem: none, inaccessiblemem: none)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(write, argmem: none, inaccessiblemem: none, target_mem0: 
none, target_mem1: none)
 ; FNATTRS-LABEL: define void @c2
 ; FNATTRS-SAME: (ptr [[Q:%.*]]) #[[ATTR1:[0-9]+]] {
 ; FNATTRS-NEXT:    store ptr [[Q]], ptr @g, align 8
@@ -37,7 +37,7 @@ define void @c2(ptr %q) {
 }
 
 define void @c3(ptr %q) {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(write, inaccessiblemem: none)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(write, inaccessiblemem: none, target_mem0: none, target_mem1: 
none)
 ; FNATTRS-LABEL: define void @c3
 ; FNATTRS-SAME: (ptr [[Q:%.*]]) #[[ATTR2:[0-9]+]] {
 ; FNATTRS-NEXT:    call void @c2(ptr [[Q]])
@@ -127,7 +127,7 @@ l1:
 @lookup_table = global [2 x i1] [ i1 0, i1 1 ]
 
 define i1 @c5(ptr %q, i32 %bitno) {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(read, argmem: none, inaccessiblemem: none)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(read, argmem: none, inaccessiblemem: none, target_mem0: none, 
target_mem1: none)
 ; FNATTRS-LABEL: define i1 @c5
 ; FNATTRS-SAME: (ptr [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR3:[0-9]+]] {
 ; FNATTRS-NEXT:    [[TMP:%.*]] = ptrtoint ptr [[Q]] to i32
@@ -222,7 +222,7 @@ define ptr @lookup_bit(ptr %q, i32 %bitno) readnone 
nounwind {
 }
 
 define i1 @c7(ptr %q, i32 %bitno) {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(read, inaccessiblemem: none)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(read, inaccessiblemem: none, target_mem0: none, target_mem1: 
none)
 ; FNATTRS-LABEL: define i1 @c7
 ; FNATTRS-SAME: (ptr readonly [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR6:[0-9]+]] {
 ; FNATTRS-NEXT:    [[PTR:%.*]] = call ptr @lookup_bit(ptr [[Q]], i32 [[BITNO]])
@@ -243,7 +243,7 @@ define i1 @c7(ptr %q, i32 %bitno) {
 
 
 define i32 @nc1(ptr %q, ptr %p, i1 %b) {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(readwrite, inaccessiblemem: none)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(readwrite, inaccessiblemem: none, target_mem0: none, 
target_mem1: none)
 ; FNATTRS-LABEL: define i32 @nc1
 ; FNATTRS-SAME: (ptr [[Q:%.*]], ptr captures(none) [[P:%.*]], i1 [[B:%.*]]) 
#[[ATTR7:[0-9]+]] {
 ; FNATTRS-NEXT:  e:
@@ -284,7 +284,7 @@ l:
 }
 
 define i32 @nc1_addrspace(ptr %q, ptr addrspace(1) %p, i1 %b) {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(readwrite, inaccessiblemem: none)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(readwrite, inaccessiblemem: none, target_mem0: none, 
target_mem1: none)
 ; FNATTRS-LABEL: define i32 @nc1_addrspace
 ; FNATTRS-SAME: (ptr [[Q:%.*]], ptr addrspace(1) captures(none) [[P:%.*]], i1 
[[B:%.*]]) #[[ATTR7]] {
 ; FNATTRS-NEXT:  e:
@@ -328,7 +328,7 @@ l:
 }
 
 define void @nc2(ptr %p, ptr %q) {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(readwrite, inaccessiblemem: none)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(readwrite, inaccessiblemem: none, target_mem0: none, 
target_mem1: none)
 ; FNATTRS-LABEL: define void @nc2
 ; FNATTRS-SAME: (ptr captures(none) [[P:%.*]], ptr [[Q:%.*]]) #[[ATTR7]] {
 ; FNATTRS-NEXT:    [[TMP1:%.*]] = call i32 @nc1(ptr [[Q]], ptr [[P]], i1 false)
@@ -468,7 +468,7 @@ define void @self_readonly_nounwind_willreturn(ptr %p) 
readonly nounwind willret
 
 ; It would be acceptable to add readnone to %y1_1 and %y1_2.
 define void @test1_1(ptr %x1_1, ptr %y1_1, i1 %c) {
-; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: none, 
inaccessiblemem: none)
+; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: none, 
inaccessiblemem: none, target_mem0: none, target_mem1: none)
 ; FNATTRS-LABEL: define void @test1_1
 ; FNATTRS-SAME: (ptr readnone captures(none) [[X1_1:%.*]], ptr [[Y1_1:%.*]], 
i1 [[C:%.*]]) #[[ATTR12:[0-9]+]] {
 ; FNATTRS-NEXT:    [[TMP1:%.*]] = call ptr @test1_2(ptr [[X1_1]], ptr 
[[Y1_1]], i1 [[C]])
@@ -488,7 +488,7 @@ define void @test1_1(ptr %x1_1, ptr %y1_1, i1 %c) {
 }
 
 define ptr @test1_2(ptr %x1_2, ptr %y1_2, i1 %c) {
-; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: none, 
inaccessiblemem: none)
+; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: none, 
inaccessiblemem: none, target_mem0: none, target_mem1: none)
 ; FNATTRS-LABEL: define ptr @test1_2
 ; FNATTRS-SAME: (ptr readnone captures(none) [[X1_2:%.*]], ptr returned 
[[Y1_2:%.*]], i1 [[C:%.*]]) #[[ATTR12]] {
 ; FNATTRS-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
@@ -520,7 +520,7 @@ f:
 }
 
 define void @test2(ptr %x2) {
-; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: none, 
inaccessiblemem: none)
+; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: none, 
inaccessiblemem: none, target_mem0: none, target_mem1: none)
 ; FNATTRS-LABEL: define void @test2
 ; FNATTRS-SAME: (ptr readnone captures(none) [[X2:%.*]]) #[[ATTR12]] {
 ; FNATTRS-NEXT:    call void @test2(ptr [[X2]])
@@ -540,7 +540,7 @@ define void @test2(ptr %x2) {
 }
 
 define void @test3(ptr %x3, ptr %y3, ptr %z3) {
-; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: none, 
inaccessiblemem: none)
+; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: none, 
inaccessiblemem: none, target_mem0: none, target_mem1: none)
 ; FNATTRS-LABEL: define void @test3
 ; FNATTRS-SAME: (ptr readnone captures(none) [[X3:%.*]], ptr readnone 
captures(none) [[Y3:%.*]], ptr readnone captures(none) [[Z3:%.*]]) #[[ATTR12]] {
 ; FNATTRS-NEXT:    call void @test3(ptr [[Z3]], ptr [[Y3]], ptr [[X3]])
@@ -560,7 +560,7 @@ define void @test3(ptr %x3, ptr %y3, ptr %z3) {
 }
 
 define void @test4_1(ptr %x4_1, i1 %c) {
-; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: none, 
inaccessiblemem: none)
+; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: none, 
inaccessiblemem: none, target_mem0: none, target_mem1: none)
 ; FNATTRS-LABEL: define void @test4_1
 ; FNATTRS-SAME: (ptr [[X4_1:%.*]], i1 [[C:%.*]]) #[[ATTR12]] {
 ; FNATTRS-NEXT:    [[TMP1:%.*]] = call ptr @test4_2(ptr [[X4_1]], ptr 
[[X4_1]], ptr [[X4_1]], i1 [[C]])
@@ -580,7 +580,7 @@ define void @test4_1(ptr %x4_1, i1 %c) {
 }
 
 define ptr @test4_2(ptr %x4_2, ptr %y4_2, ptr %z4_2, i1 %c) {
-; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: none, 
inaccessiblemem: none)
+; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: none, 
inaccessiblemem: none, target_mem0: none, target_mem1: none)
 ; FNATTRS-LABEL: define ptr @test4_2
 ; FNATTRS-SAME: (ptr readnone captures(none) [[X4_2:%.*]], ptr readnone 
returned captures(ret: address, provenance) [[Y4_2:%.*]], ptr readnone 
captures(none) [[Z4_2:%.*]], i1 [[C:%.*]]) #[[ATTR12]] {
 ; FNATTRS-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
@@ -744,7 +744,7 @@ entry:
 
 @g2 = global ptr null
 define void @captureLaunder(ptr %p) {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(write, argmem: none, inaccessiblemem: readwrite)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(write, argmem: none, inaccessiblemem: readwrite, target_mem0: 
none, target_mem1: none)
 ; FNATTRS-LABEL: define void @captureLaunder
 ; FNATTRS-SAME: (ptr [[P:%.*]]) #[[ATTR16:[0-9]+]] {
 ; FNATTRS-NEXT:    [[B:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr 
[[P]])
@@ -788,7 +788,7 @@ entry:
 
 @g3 = global ptr null
 define void @captureStrip(ptr %p) {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(write, argmem: none, inaccessiblemem: none)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(write, argmem: none, inaccessiblemem: none, target_mem0: 
none, target_mem1: none)
 ; FNATTRS-LABEL: define void @captureStrip
 ; FNATTRS-SAME: (ptr [[P:%.*]]) #[[ATTR1]] {
 ; FNATTRS-NEXT:    [[B:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr 
[[P]])
@@ -1086,7 +1086,7 @@ define i64 @captures_not_ret_only(ptr %p) {
 
 ;; Unlike ptrtoint, ptrtoaddr only captures the address
 define i64 @captures_ptrtoaddr_stored(ptr %p) {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(write, argmem: none, inaccessiblemem: none)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(write, argmem: none, inaccessiblemem: none, target_mem0: 
none, target_mem1: none)
 ; FNATTRS-LABEL: define noundef i64 @captures_ptrtoaddr_stored
 ; FNATTRS-SAME: (ptr captures(address) [[P:%.*]]) #[[ATTR1]] {
 ; FNATTRS-NEXT:    [[INT:%.*]] = ptrtoaddr ptr [[P]] to i64
@@ -1189,7 +1189,7 @@ define ptr @captures_used_ret(ptr %p) {
 ; Make sure this is does not produce captures(ret: ...). We need to take the
 ; return capture components into account when handling argument SCCs.
 define ptr @scc_capture_via_ret(i1 %c, ptr %p) {
-; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: none, 
inaccessiblemem: none)
+; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: none, 
inaccessiblemem: none, target_mem0: none, target_mem1: none)
 ; FNATTRS-LABEL: define ptr @scc_capture_via_ret
 ; FNATTRS-SAME: (i1 [[C:%.*]], ptr [[P:%.*]]) #[[ATTR12]] {
 ; FNATTRS-NEXT:    br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
@@ -1291,7 +1291,7 @@ define void @dont_increase_existing_captures_scc2(ptr %p) 
{
 }
 
 define void @addr_only_scc(ptr %p) {
-; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: read, 
inaccessiblemem: none)
+; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: read, 
inaccessiblemem: none, target_mem0: none, target_mem1: none)
 ; FNATTRS-LABEL: define void @addr_only_scc
 ; FNATTRS-SAME: (ptr readonly captures(address_is_null) [[P:%.*]]) 
#[[ATTR20:[0-9]+]] {
 ; FNATTRS-NEXT:    [[V:%.*]] = load i8, ptr [[P]], align 1
@@ -1314,7 +1314,7 @@ define void @addr_only_scc(ptr %p) {
 }
 
 define void @addr_only_scc2(ptr %p) {
-; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: read, 
inaccessiblemem: none)
+; FNATTRS: Function Attrs: nofree nosync nounwind memory(write, argmem: read, 
inaccessiblemem: none, target_mem0: none, target_mem1: none)
 ; FNATTRS-LABEL: define void @addr_only_scc2
 ; FNATTRS-SAME: (ptr readonly captures(address_is_null) [[P:%.*]]) #[[ATTR20]] 
{
 ; FNATTRS-NEXT:    [[CMP:%.*]] = icmp ne ptr [[P]], null

diff  --git a/llvm/test/Transforms/FunctionAttrs/read-write-scc.ll 
b/llvm/test/Transforms/FunctionAttrs/read-write-scc.ll
index be61990fd6278..1fc0084203fca 100644
--- a/llvm/test/Transforms/FunctionAttrs/read-write-scc.ll
+++ b/llvm/test/Transforms/FunctionAttrs/read-write-scc.ll
@@ -4,7 +4,7 @@
 @i = global i32 0
 
 define void @foo() {
-; CHECK: Function Attrs: nofree nosync nounwind memory(readwrite, argmem: 
none, inaccessiblemem: none)
+; CHECK: Function Attrs: nofree nosync nounwind memory(readwrite, argmem: 
none, inaccessiblemem: none, target_mem0: none, target_mem1: none)
 ; CHECK-LABEL: define {{[^@]+}}@foo
 ; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:    store i32 1, ptr @i, align 4
@@ -17,7 +17,7 @@ define void @foo() {
 }
 
 define void @bar() {
-; CHECK: Function Attrs: nofree nosync nounwind memory(readwrite, argmem: 
none, inaccessiblemem: none)
+; CHECK: Function Attrs: nofree nosync nounwind memory(readwrite, argmem: 
none, inaccessiblemem: none, target_mem0: none, target_mem1: none)
 ; CHECK-LABEL: define {{[^@]+}}@bar
 ; CHECK-SAME: () #[[ATTR0]] {
 ; CHECK-NEXT:    [[I:%.*]] = load i32, ptr @i, align 4

diff  --git a/llvm/test/Transforms/FunctionAttrs/readattrs.ll 
b/llvm/test/Transforms/FunctionAttrs/readattrs.ll
index 87f64ed3c63bc..8fc72a1ab90b9 100644
--- a/llvm/test/Transforms/FunctionAttrs/readattrs.ll
+++ b/llvm/test/Transforms/FunctionAttrs/readattrs.ll
@@ -33,7 +33,7 @@ define void @test1_2(ptr %x1_2, ptr %y1_2, ptr %z1_2) {
 
 ; TODO: Missing with attributor-light: argmem: none, inaccessiblemem: none
 define ptr @test2(ptr %p) {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(write, argmem: none, inaccessiblemem: none)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(write, argmem: none, inaccessiblemem: none, target_mem0: 
none, target_mem1: none)
 ; FNATTRS-LABEL: define {{[^@]+}}@test2
 ; FNATTRS-SAME: (ptr readnone returned captures(ret: address, provenance) 
[[P:%.*]]) #[[ATTR0:[0-9]+]] {
 ; FNATTRS-NEXT:    store i32 0, ptr @x, align 4

diff  --git a/llvm/test/Transforms/FunctionAttrs/writeonly.ll 
b/llvm/test/Transforms/FunctionAttrs/writeonly.ll
index 88c6031613697..05ecb12c710ee 100644
--- a/llvm/test/Transforms/FunctionAttrs/writeonly.ll
+++ b/llvm/test/Transforms/FunctionAttrs/writeonly.ll
@@ -44,7 +44,7 @@ nouses-argworn-funro_entry:
 @d-ccc = internal global %_type_of_d-ccc <{ ptr null, i8 1, i8 13, i8 0, i8 
-127 }>, align 8
 
 define void @nouses-argworn-funwo(ptr writeonly %.aaa) {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(write, argmem: none, inaccessiblemem: none)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(write, argmem: none, inaccessiblemem: none, target_mem0: 
none, target_mem1: none)
 ; FNATTRS-LABEL: define {{[^@]+}}@nouses-argworn-funwo
 ; FNATTRS-SAME: (ptr readnone captures(none) [[DOTAAA:%.*]]) #[[ATTR2:[0-9]+]] 
{
 ; FNATTRS-NEXT:  nouses-argworn-funwo_entry:
@@ -82,7 +82,7 @@ define void @test_store(ptr %p) {
 
 @G = external global ptr
 define i8 @test_store_capture(ptr %p) {
-; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(readwrite, argmem: read, inaccessiblemem: none)
+; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(readwrite, argmem: read, inaccessiblemem: none, target_mem0: 
none, target_mem1: none)
 ; FNATTRS-LABEL: define {{[^@]+}}@test_store_capture
 ; FNATTRS-SAME: (ptr [[P:%.*]]) #[[ATTR4:[0-9]+]] {
 ; FNATTRS-NEXT:    store ptr [[P]], ptr @G, align 8

diff  --git a/llvm/test/Transforms/InferFunctionAttrs/norecurse_debug.ll 
b/llvm/test/Transforms/InferFunctionAttrs/norecurse_debug.ll
index c8568272d320f..89a09406e5f1d 100644
--- a/llvm/test/Transforms/InferFunctionAttrs/norecurse_debug.ll
+++ b/llvm/test/Transforms/InferFunctionAttrs/norecurse_debug.ll
@@ -52,5 +52,5 @@ attributes #1 = { nounwind readnone speculatable }
 !28 = !DILocation(line: 9, column: 18, scope: !2)
 !29 = !DILocation(line: 10, column: 1, scope: !2)
 
-; CHECK: attributes #0 = { mustprogress nofree norecurse nosync nounwind 
willreturn memory(readwrite, argmem: write, inaccessiblemem: none) }
+; CHECK: attributes #0 = { mustprogress nofree norecurse nosync nounwind 
willreturn memory(readwrite, argmem: write, inaccessiblemem: none, target_mem0: 
none, target_mem1: none) }
 ; CHECK-NOT: foo.coefficient1

diff  --git a/llvm/test/Transforms/LowerTypeTests/cfi-nounwind-direct-call.ll 
b/llvm/test/Transforms/LowerTypeTests/cfi-nounwind-direct-call.ll
index 2795333effd76..89c32fab54a4c 100644
--- a/llvm/test/Transforms/LowerTypeTests/cfi-nounwind-direct-call.ll
+++ b/llvm/test/Transforms/LowerTypeTests/cfi-nounwind-direct-call.ll
@@ -117,7 +117,7 @@ attributes #6 = { noreturn nounwind }
 ; CHECK-NEXT:    ret i32 [[DOT]]
 ;
 ;
-; CHECK: Function Attrs: minsize mustprogress nofree norecurse nosync nounwind 
optsize willreturn memory(write, argmem: none, inaccessiblemem: none)
+; CHECK: Function Attrs: minsize mustprogress nofree norecurse nosync nounwind 
optsize willreturn memory(write, argmem: none, inaccessiblemem: none, 
target_mem0: none, target_mem1: none)
 ; CHECK-LABEL: define dso_local noundef range(i32 0, 2) i32 @_Z10call_catchi
 ; CHECK-SAME: (i32 noundef [[NUM:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] 
!type [[META4]] !type [[META5]] !type [[META6]] {
 ; CHECK-NEXT:  entry:

diff  --git a/llvm/test/Transforms/SCCP/ipscp-drop-argmemonly.ll 
b/llvm/test/Transforms/SCCP/ipscp-drop-argmemonly.ll
index 22726e0cac1f1..6a64dc3cddd39 100644
--- a/llvm/test/Transforms/SCCP/ipscp-drop-argmemonly.ll
+++ b/llvm/test/Transforms/SCCP/ipscp-drop-argmemonly.ll
@@ -14,7 +14,7 @@
 ; CHECK: @[[G:[a-zA-Z0-9_$"\\.-]+]] = internal global i32 0
 ;.
 define internal void @ptrarg.1(ptr %arg, i32 %val) argmemonly nounwind {
-; CHECK: Function Attrs: nounwind memory(readwrite, inaccessiblemem: none)
+; CHECK: Function Attrs: nounwind memory(readwrite, inaccessiblemem: none, 
target_mem0: none, target_mem1: none)
 ; CHECK-LABEL: @ptrarg.1(
 ; CHECK-NEXT:    store i32 10, ptr @g, align 4
 ; CHECK-NEXT:    ret void
@@ -62,7 +62,7 @@ define void @caller.2(ptr %ptr) {
 ; Here the pointer argument %arg will be replaced by a constant. We need to
 ; drop inaccessiblemem_or_argmemonly.
 define internal void @ptrarg.3(ptr %arg, i32 %val) 
inaccessiblemem_or_argmemonly nounwind {
-; CHECK: Function Attrs: nounwind memory(readwrite)
+; CHECK: Function Attrs: nounwind memory(readwrite, target_mem0: none, 
target_mem1: none)
 ; CHECK-LABEL: @ptrarg.3(
 ; CHECK-NEXT:    store i32 10, ptr @g, align 4
 ; CHECK-NEXT:    ret void
@@ -110,7 +110,7 @@ define void @caller.4(ptr %ptr) {
 ; Here the pointer argument %arg will be replaced by a constant. We need to
 ; drop inaccessiblemem_or_argmemonly.
 define internal void @ptrarg.5(ptr %arg, i32 %val) argmemonly 
inaccessiblemem_or_argmemonly nounwind {
-; CHECK: Function Attrs: nounwind memory(readwrite, inaccessiblemem: none)
+; CHECK: Function Attrs: nounwind memory(readwrite, inaccessiblemem: none, 
target_mem0: none, target_mem1: none)
 ; CHECK-LABEL: @ptrarg.5(
 ; CHECK-NEXT:    store i32 10, ptr @g, align 4
 ; CHECK-NEXT:    ret void
@@ -163,9 +163,9 @@ define i32 @caller.6.cs.attributes(i32 %n) {
 }
 
 ;.
-; CHECK: attributes #[[ATTR0]] = { nounwind memory(readwrite, inaccessiblemem: 
none) }
+; CHECK: attributes #[[ATTR0]] = { nounwind memory(readwrite, inaccessiblemem: 
none, target_mem0: none, target_mem1: none) }
 ; CHECK: attributes #[[ATTR1:[0-9]+]] = { nounwind memory(argmem: readwrite) }
-; CHECK: attributes #[[ATTR2]] = { nounwind memory(readwrite) }
+; CHECK: attributes #[[ATTR2]] = { nounwind memory(readwrite, target_mem0: 
none, target_mem1: none) }
 ; CHECK: attributes #[[ATTR3:[0-9]+]] = { nounwind memory(argmem: readwrite, 
inaccessiblemem: readwrite) }
 ; CHECK: attributes #[[ATTR4]] = { nounwind }
 ;.

diff  --git a/llvm/unittests/Support/ModRefTest.cpp 
b/llvm/unittests/Support/ModRefTest.cpp
index 9c13908da44bb..128501bf2d957 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, Other: NoModRef, TargetMem0: NoModRef, TargetMem1: 
NoModRef");
 }
 
 } // namespace

diff  --git a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp 
b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
index 228969ab37f85..d90fcc25502e2 100644
--- a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
+++ b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
@@ -13,6 +13,7 @@
 #include "CodeGenIntrinsics.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSwitch.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/TableGen/Error.h"
@@ -377,7 +378,19 @@ 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("IntrRead")) {
+    MemoryEffects ReadMask = MemoryEffects::writeOnly();
+    for (const Record *RLoc : R->getValueAsListOfDefs("MemLoc"))
+      ReadMask = ReadMask.getWithModRef(getValueAsIRMemLocation(RLoc),
+                                        ModRefInfo::ModRef);
+    ME &= ReadMask;
+  } else if (R->isSubClassOf("IntrWrite")) {
+    MemoryEffects WriteMask = MemoryEffects::readOnly();
+    for (const Record *WLoc : R->getValueAsListOfDefs("MemLoc"))
+      WriteMask = WriteMask.getWithModRef(getValueAsIRMemLocation(WLoc),
+                                          ModRefInfo::ModRef);
+    ME &= WriteMask;
+  } else if (R->getName() == "IntrInaccessibleMemOrArgMemOnly")
     ME &= MemoryEffects::inaccessibleOrArgMemOnly();
   else if (R->getName() == "Commutative")
     isCommutative = true;
@@ -477,6 +490,22 @@ void CodeGenIntrinsic::setProperty(const Record *R) {
   }
 }
 
+llvm::IRMemLocation
+CodeGenIntrinsic::getValueAsIRMemLocation(const Record *R) const {
+  StringRef Name = R->getName();
+  IRMemLocation Loc =
+      StringSwitch<IRMemLocation>(Name)
+          .Case("TargetMem0", IRMemLocation::TargetMem0)
+          .Case("TargetMem1", IRMemLocation::TargetMem1)
+          .Case("InaccessibleMem", IRMemLocation::InaccessibleMem)
+          .Default(IRMemLocation::Other); // fallback enum
+
+  if (Loc == IRMemLocation::Other)
+    PrintFatalError(R->getLoc(), "unknown IRMemLocation: " + Name);
+
+  return Loc;
+}
+
 bool CodeGenIntrinsic::isParamAPointer(unsigned ParamIdx) const {
   if (ParamIdx >= IS.ParamTys.size())
     return false;

diff  --git a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h 
b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h
index 6ac6f734326d8..305260a7ef4a9 100644
--- a/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h
+++ b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h
@@ -186,6 +186,8 @@ struct CodeGenIntrinsic {
 
   bool isParamImmArg(unsigned ParamIdx) const;
 
+  llvm::IRMemLocation getValueAsIRMemLocation(const Record *R) const;
+
   CodeGenIntrinsic(const Record *R, const CodeGenIntrinsicContext &Ctx);
 };
 

diff  --git a/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp 
b/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp
index 3ac23185ef91c..9fed5920a019f 100644
--- a/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp
@@ -599,10 +599,10 @@ static AttributeSet 
getIntrinsicFnAttributeSet(LLVMContext &C, unsigned ID) {
     if (!UniqFnAttributes.try_emplace(&Int, ID).second)
       continue;
     OS << formatv(R"(
-  case {}:
+  case {}: // {}
     return AttributeSet::get(C, {{
 )",
-                  ID);
+                  ID, Int.Name);
     auto addAttribute = [&OS](StringRef Attr) {
       OS << formatv("      Attribute::get(C, Attribute::{}),\n", Attr);
     };

diff  --git a/mlir/test/Target/LLVMIR/llvmir.mlir 
b/mlir/test/Target/LLVMIR/llvmir.mlir
index cc243c86ca902..0e087200b1116 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -2373,7 +2373,7 @@ llvm.func @readonly_function(%arg0: !llvm.ptr 
{llvm.readonly})
 llvm.func @arg_mem_none_func() attributes {
   memory_effects = #llvm.memory_effects<other = readwrite, argMem = none, 
inaccessibleMem = readwrite>}
 
-// CHECK: attributes #[[ATTR]] = { memory(readwrite, argmem: none, errnomem: 
none) }
+// CHECK: attributes #[[ATTR]] = { memory(readwrite, argmem: none, errnomem: 
none, target_mem0: none, target_mem1: none) }
 
 // -----
 
@@ -2381,7 +2381,7 @@ llvm.func @arg_mem_none_func() attributes {
 llvm.func @readwrite_func() attributes {
   memory_effects = #llvm.memory_effects<other = readwrite, argMem = readwrite, 
inaccessibleMem = readwrite>}
 
-// CHECK: attributes #[[ATTR]] = { memory(readwrite, errnomem: none) }
+// CHECK: attributes #[[ATTR]] = { memory(readwrite, errnomem: none, 
target_mem0: none, target_mem1: none) }
 
 // -----
 
@@ -2734,11 +2734,11 @@ llvm.func @mem_effects_call() {
 // CHECK: #[[ATTRS_0]]
 // CHECK-SAME: memory(none)
 // CHECK: #[[ATTRS_1]]
-// CHECK-SAME: memory(read, argmem: none, inaccessiblemem: write, errnomem: 
none)
+// CHECK-SAME: memory(read, argmem: none, inaccessiblemem: write, errnomem: 
none, target_mem0: none, target_mem1: none)
 // CHECK: #[[ATTRS_2]]
-// CHECK-SAME: memory(read, inaccessiblemem: write, errnomem: none)
+// CHECK-SAME: memory(read, inaccessiblemem: write, errnomem: none, 
target_mem0: none, target_mem1: none)
 // CHECK: #[[ATTRS_3]]
-// CHECK-SAME: memory(readwrite, argmem: read, errnomem: none)
+// CHECK-SAME: memory(readwrite, argmem: read, errnomem: none, target_mem0: 
none, target_mem1: none)
 
 // -----
 


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to