[Mlir-commits] [mlir] 200793a - Extend MemoryEffects to Support Target-Specific Memory Locations (#148650)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Tue Nov 18 03:11:02 PST 2025
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)
// -----
More information about the Mlir-commits
mailing list