LLVM 20.0.0git
MemoryModelRelaxationAnnotations.cpp
Go to the documentation of this file.
1//===- MemoryModelRelaxationAnnotations.cpp ---------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
11#include "llvm/IR/Metadata.h"
12#include "llvm/Support/Debug.h"
14
15using namespace llvm;
16
17//===- MMRAMetadata -------------------------------------------------------===//
18
20 : MMRAMetadata(I.getMetadata(LLVMContext::MD_mmra)) {}
21
23 if (!MD)
24 return;
25
26 // TODO: Split this into a "tryParse" function that can return an err.
27 // CTor can use the tryParse & just fatal on err.
28
29 MDTuple *Tuple = dyn_cast<MDTuple>(MD);
30 assert(Tuple && "Invalid MMRA structure");
31
32 const auto HandleTagMD = [this](MDNode *TagMD) {
33 Tags.insert({cast<MDString>(TagMD->getOperand(0))->getString(),
34 cast<MDString>(TagMD->getOperand(1))->getString()});
35 };
36
37 if (isTagMD(Tuple)) {
38 HandleTagMD(Tuple);
39 return;
40 }
41
42 for (const MDOperand &Op : Tuple->operands()) {
43 MDNode *MDOp = cast<MDNode>(Op.get());
44 assert(isTagMD(MDOp));
45 HandleTagMD(MDOp);
46 }
47}
48
50 if (auto *Tuple = dyn_cast<MDTuple>(MD)) {
51 return Tuple->getNumOperands() == 2 &&
52 isa<MDString>(Tuple->getOperand(0)) &&
53 isa<MDString>(Tuple->getOperand(1));
54 }
55 return false;
56}
57
59 StringRef Suffix) {
60 return MDTuple::get(Ctx,
61 {MDString::get(Ctx, Prefix), MDString::get(Ctx, Suffix)});
62}
63
66 if (Tags.empty())
67 return nullptr;
68
69 if (Tags.size() == 1)
70 return getTagMD(Ctx, Tags.front());
71
73 for (const auto &Tag : Tags)
74 MMRAs.push_back(getTagMD(Ctx, Tag));
75 return MDTuple::get(Ctx, MMRAs);
76}
77
79 const MMRAMetadata &B) {
80 // Let A and B be two tags set, and U be the prefix-wise union of A and B.
81 // For every unique tag prefix P present in A or B:
82 // * If either A or B has no tags with prefix P, no tags with prefix
83 // P are added to U.
84 // * If both A and B have at least one tag with prefix P, all tags with prefix
85 // P from both sets are added to U.
86
88
89 for (const auto &[P, S] : A) {
90 if (B.hasTagWithPrefix(P))
91 Result.push_back(getTagMD(Ctx, P, S));
92 }
93 for (const auto &[P, S] : B) {
94 if (A.hasTagWithPrefix(P))
95 Result.push_back(getTagMD(Ctx, P, S));
96 }
97
98 return MDTuple::get(Ctx, Result);
99}
100
101bool MMRAMetadata::hasTag(StringRef Prefix, StringRef Suffix) const {
102 return Tags.count({Prefix, Suffix});
103}
104
106 // Two sets of tags are compatible iff, for every unique tag prefix P
107 // present in at least one set:
108 // - the other set contains no tag with prefix P, or
109 // - at least one tag with prefix P is common to both sets.
110
111 StringMap<bool> PrefixStatuses;
112 for (const auto &[P, S] : Tags)
113 PrefixStatuses[P] |= (Other.hasTag(P, S) || !Other.hasTagWithPrefix(P));
114 for (const auto &[P, S] : Other)
115 PrefixStatuses[P] |= (hasTag(P, S) || !hasTagWithPrefix(P));
116
117 for (auto &[Prefix, Status] : PrefixStatuses) {
118 if (!Status)
119 return false;
120 }
121
122 return true;
123}
124
126 for (const auto &[P, S] : Tags)
127 if (P == Prefix)
128 return true;
129 return false;
130}
131
133 return Tags.begin();
134}
135
137
138bool MMRAMetadata::empty() const { return Tags.empty(); }
139
140unsigned MMRAMetadata::size() const { return Tags.size(); }
141
143 bool IsFirst = true;
144 // TODO: use map_iter + join
145 for (const auto &[P, S] : Tags) {
146 if (IsFirst)
147 IsFirst = false;
148 else
149 OS << ", ";
150 OS << P << ":" << S;
151 }
152}
153
155void MMRAMetadata::dump() const { print(dbgs()); }
156
157//===- Helpers ------------------------------------------------------------===//
158
159static bool isReadWriteMemCall(const Instruction &I) {
160 if (const auto *C = dyn_cast<CallBase>(&I))
161 return C->mayReadOrWriteMemory() ||
162 !C->getMemoryEffects().doesNotAccessMemory();
163 return false;
164}
165
167 return isa<LoadInst>(I) || isa<StoreInst>(I) || isa<AtomicCmpXchgInst>(I) ||
168 isa<AtomicRMWInst>(I) || isa<FenceInst>(I) || isReadWriteMemCall(I);
169}
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:622
#define I(x, y, z)
Definition: MD5.cpp:58
static bool isReadWriteMemCall(const Instruction &I)
This file provides utility for Memory Model Relaxation Annotations (MMRAs).
This file contains the declarations for metadata subclasses.
#define P(N)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
const T & front() const
front - Get the first element.
Definition: ArrayRef.h:171
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:168
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:163
This class represents an Operation in the Expression.
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
Metadata node.
Definition: Metadata.h:1069
ArrayRef< MDOperand > operands() const
Definition: Metadata.h:1428
Tracking metadata reference owned by Metadata.
Definition: Metadata.h:891
static MDString * get(LLVMContext &Context, StringRef Str)
Definition: Metadata.cpp:606
Tuple of metadata.
Definition: Metadata.h:1473
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition: Metadata.h:1500
Helper class to manipulate !mmra metadata nodes.
static MDTuple * getTagMD(LLVMContext &Ctx, StringRef Prefix, StringRef Suffix)
Creates !mmra metadata for a single tag.
void print(raw_ostream &OS) const
static MDNode * combine(LLVMContext &Ctx, const MMRAMetadata &A, const MMRAMetadata &B)
Combines A and B according to MMRA semantics.
static MDTuple * getMD(LLVMContext &Ctx, ArrayRef< TagT > Tags)
Creates !mmra metadata from Tags.
bool hasTag(StringRef Prefix, StringRef Suffix) const
MMRAMetadata()=default
bool isCompatibleWith(const MMRAMetadata &Other) const
bool hasTagWithPrefix(StringRef Prefix) const
static bool isTagMD(const Metadata *MD)
Root of the metadata hierarchy.
Definition: Metadata.h:62
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:128
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:213
size_type size() const
Definition: DenseSet.h:81
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
Definition: DenseSet.h:95
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool canInstructionHaveMMRAs(const Instruction &I)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
@ Other
Any other memory.