Skip to content

Commit 200793a

Browse files
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.
1 parent fb829bf commit 200793a

File tree

26 files changed

+279
-65
lines changed

26 files changed

+279
-65
lines changed

clang/test/CodeGen/sanitize-metadata-nosanitize.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
// 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 }]
1111
// 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 }]
1212
//.
13-
// CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: none)
13+
// CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(write, argmem: none, inaccessiblemem: none, target_mem0: none, target_mem1: none)
1414
// CHECK-LABEL: define dso_local void @escape(
1515
// CHECK-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] !pcsections [[META6:![0-9]+]] {
1616
// CHECK-NEXT: [[ENTRY:.*:]]
@@ -21,7 +21,7 @@ __attribute__((noinline, not_tail_called)) void escape(const volatile void *p) {
2121
sink = p;
2222
}
2323

24-
// CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none)
24+
// CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none, target_mem0: none, target_mem1: none)
2525
// CHECK-LABEL: define dso_local i32 @normal_function(
2626
// CHECK-SAME: ptr noundef [[X:%.*]], ptr noundef readonly captures(none) [[Y:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] !pcsections [[META8:![0-9]+]] {
2727
// CHECK-NEXT: [[ENTRY:.*:]]
@@ -38,7 +38,7 @@ int normal_function(int *x, int *y) {
3838
return *y;
3939
}
4040

41-
// CHECK: Function Attrs: disable_sanitizer_instrumentation mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none)
41+
// CHECK: Function Attrs: disable_sanitizer_instrumentation mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none, target_mem0: none, target_mem1: none)
4242
// CHECK-LABEL: define dso_local i32 @test_disable_sanitize_instrumentation(
4343
// CHECK-SAME: ptr noundef [[X:%.*]], ptr noundef readonly captures(none) [[Y:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
4444
// CHECK-NEXT: [[ENTRY:.*:]]
@@ -55,7 +55,7 @@ __attribute__((disable_sanitizer_instrumentation)) int test_disable_sanitize_ins
5555
return *y;
5656
}
5757

58-
// CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none)
58+
// CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none, target_mem0: none, target_mem1: none)
5959
// CHECK-LABEL: define dso_local i32 @test_no_sanitize_thread(
6060
// CHECK-SAME: ptr noundef [[X:%.*]], ptr noundef readonly captures(none) [[Y:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] !pcsections [[META14:![0-9]+]] {
6161
// CHECK-NEXT: [[ENTRY:.*:]]
@@ -72,7 +72,7 @@ __attribute__((no_sanitize("thread"))) int test_no_sanitize_thread(int *x, int *
7272
return *y;
7373
}
7474

75-
// CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none)
75+
// CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none, target_mem0: none, target_mem1: none)
7676
// CHECK-LABEL: define dso_local i32 @test_no_sanitize_all(
7777
// CHECK-SAME: ptr noundef [[X:%.*]], ptr noundef readonly captures(none) [[Y:%.*]]) local_unnamed_addr #[[ATTR3]] !pcsections [[META14]] {
7878
// CHECK-NEXT: [[ENTRY:.*:]]
@@ -89,10 +89,10 @@ __attribute__((no_sanitize("all"))) int test_no_sanitize_all(int *x, int *y) {
8989
return *y;
9090
}
9191
//.
92-
// 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" }
93-
// 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" }
94-
// 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" }
95-
// 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" }
92+
// 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" }
93+
// 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" }
94+
// 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" }
95+
// 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" }
9696
// CHECK: attributes #[[ATTR4:[0-9]+]] = { nounwind "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
9797
//.
9898
// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}

clang/test/CodeGenOpenCL/convergent.cl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ kernel void assume_convergent_asm()
133133
__asm__ volatile("s_barrier");
134134
}
135135

136-
// CHECK: attributes #0 = { nofree noinline norecurse nounwind "
136+
// CHECK: attributes #0 = { nofree noinline norecurse nounwind memory(readwrite, target_mem0: none, target_mem1: none) "
137137
// CHECK: attributes #1 = { {{[^}]*}}convergent{{[^}]*}} }
138138
// CHECK: attributes #2 = { {{[^}]*}}convergent{{[^}]*}} }
139139
// CHECK: attributes #3 = { {{[^}]*}}convergent noduplicate{{[^}]*}} }

llvm/docs/LangRef.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2178,7 +2178,8 @@ For example:
21782178
This attribute specifies the possible memory effects of the call-site or
21792179
function. It allows specifying the possible access kinds (``none``,
21802180
``read``, ``write``, or ``readwrite``) for the possible memory location
2181-
kinds (``argmem``, ``inaccessiblemem``, ``errnomem``, as well as a default).
2181+
kinds (``argmem``, ``inaccessiblemem``, ``errnomem``, ``target_mem0``,
2182+
``target_mem1``, as well as a default).
21822183
It is best understood by example:
21832184

21842185
- ``memory(none)``: Does not access any memory.
@@ -2220,6 +2221,11 @@ For example:
22202221
accessing inaccessible memory itself). Inaccessible memory is often used
22212222
to model control dependencies of intrinsics.
22222223
- ``errnomem``: This refers to accesses to the ``errno`` variable.
2224+
- ``target_mem#`` : These refer to target specific state that cannot be
2225+
accessed by any other means. # is a number between 0 and 1 inclusive.
2226+
Note: The target_mem locations are experimental and intended for internal
2227+
testing only. They must not be used in production code.
2228+
22232229
- The default access kind (specified without a location prefix) applies to
22242230
all locations that haven't been specified explicitly, including those that
22252231
don't currently have a dedicated location kind (e.g., accesses to globals

llvm/include/llvm/AsmParser/LLToken.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ enum Kind {
206206
kw_readwrite,
207207
kw_argmem,
208208
kw_inaccessiblemem,
209+
kw_target_mem0,
210+
kw_target_mem1,
209211
kw_errnomem,
210212

211213
// Legacy attributes:

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,25 @@ def IntrInaccessibleMemOnly : IntrinsicProperty;
5454
// by the module being compiled. This is a weaker form of IntrArgMemOnly.
5555
def IntrInaccessibleMemOrArgMemOnly : IntrinsicProperty;
5656

57+
// Tablegen representation of IRMemLocation.
58+
class IntrinsicMemoryLocation;
59+
60+
// TODO: Populate with all IRMemLocation enum values and update
61+
// getValueAsIRMemLocation accordingly.
62+
def InaccessibleMem : IntrinsicMemoryLocation;
63+
def TargetMem0 : IntrinsicMemoryLocation;
64+
def TargetMem1 : IntrinsicMemoryLocation;
65+
66+
// The list of IRMemoryLocations that are read from.
67+
class IntrRead<list<IntrinsicMemoryLocation> idx> : IntrinsicProperty {
68+
list<IntrinsicMemoryLocation> MemLoc=idx;
69+
}
70+
71+
// The list of IRMemoryLocations that are write to.
72+
class IntrWrite<list<IntrinsicMemoryLocation> idx> : IntrinsicProperty {
73+
list<IntrinsicMemoryLocation> MemLoc=idx;
74+
}
75+
5776
// Commutative - This intrinsic is commutative: X op Y == Y op X.
5877
def Commutative : IntrinsicProperty;
5978

llvm/include/llvm/Support/ModRef.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,15 @@ enum class IRMemLocation {
6666
ErrnoMem = 2,
6767
/// Any other memory.
6868
Other = 3,
69+
/// Represents target specific state.
70+
TargetMem0 = 4,
71+
TargetMem1 = 5,
6972

7073
/// Helpers to iterate all locations in the MemoryEffectsBase class.
7174
First = ArgMem,
72-
Last = Other,
75+
FirstTarget = TargetMem0,
76+
// TargetMem IDs must be at the end of the list.
77+
Last = TargetMem1,
7378
};
7479

7580
template <typename LocationEnum> class MemoryEffectsBase {

llvm/lib/AsmParser/LLLexer.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,8 @@ lltok::Kind LLLexer::LexIdentifier() {
707707
KEYWORD(write);
708708
KEYWORD(readwrite);
709709
KEYWORD(argmem);
710+
KEYWORD(target_mem0);
711+
KEYWORD(target_mem1);
710712
KEYWORD(inaccessiblemem);
711713
KEYWORD(errnomem);
712714
KEYWORD(argmemonly);

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2552,6 +2552,10 @@ static std::optional<MemoryEffects::Location> keywordToLoc(lltok::Kind Tok) {
25522552
return IRMemLocation::InaccessibleMem;
25532553
case lltok::kw_errnomem:
25542554
return IRMemLocation::ErrnoMem;
2555+
case lltok::kw_target_mem0:
2556+
return IRMemLocation::TargetMem0;
2557+
case lltok::kw_target_mem1:
2558+
return IRMemLocation::TargetMem1;
25552559
default:
25562560
return std::nullopt;
25572561
}

llvm/lib/IR/Attributes.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,12 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
656656
break;
657657
case IRMemLocation::Other:
658658
llvm_unreachable("This is represented as the default access kind");
659+
case IRMemLocation::TargetMem0:
660+
OS << "target_mem0: ";
661+
break;
662+
case IRMemLocation::TargetMem1:
663+
OS << "target_mem1: ";
664+
break;
659665
}
660666
OS << getModRefStr(MR);
661667
}

llvm/lib/Support/ModRef.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, MemoryEffects ME) {
4949
case IRMemLocation::Other:
5050
OS << "Other: ";
5151
break;
52+
case IRMemLocation::TargetMem0:
53+
OS << "TargetMem0: ";
54+
break;
55+
case IRMemLocation::TargetMem1:
56+
OS << "TargetMem1: ";
57+
break;
5258
}
5359
OS << ME.getModRef(Loc);
5460
});

0 commit comments

Comments
 (0)