Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/IR/MemoryModelRelaxationAnnotations.cpp
35233 views
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
9
#include "llvm/IR/MemoryModelRelaxationAnnotations.h"
10
#include "llvm/ADT/StringSet.h"
11
#include "llvm/IR/Instructions.h"
12
#include "llvm/IR/Metadata.h"
13
#include "llvm/Support/Debug.h"
14
#include "llvm/Support/raw_ostream.h"
15
16
using namespace llvm;
17
18
//===- MMRAMetadata -------------------------------------------------------===//
19
20
MMRAMetadata::MMRAMetadata(const Instruction &I)
21
: MMRAMetadata(I.getMetadata(LLVMContext::MD_mmra)) {}
22
23
MMRAMetadata::MMRAMetadata(MDNode *MD) {
24
if (!MD)
25
return;
26
27
// TODO: Split this into a "tryParse" function that can return an err.
28
// CTor can use the tryParse & just fatal on err.
29
30
MDTuple *Tuple = dyn_cast<MDTuple>(MD);
31
assert(Tuple && "Invalid MMRA structure");
32
33
const auto HandleTagMD = [this](MDNode *TagMD) {
34
Tags.insert({cast<MDString>(TagMD->getOperand(0))->getString(),
35
cast<MDString>(TagMD->getOperand(1))->getString()});
36
};
37
38
if (isTagMD(Tuple)) {
39
HandleTagMD(Tuple);
40
return;
41
}
42
43
for (const MDOperand &Op : Tuple->operands()) {
44
MDNode *MDOp = cast<MDNode>(Op.get());
45
assert(isTagMD(MDOp));
46
HandleTagMD(MDOp);
47
}
48
}
49
50
bool MMRAMetadata::isTagMD(const Metadata *MD) {
51
if (auto *Tuple = dyn_cast<MDTuple>(MD)) {
52
return Tuple->getNumOperands() == 2 &&
53
isa<MDString>(Tuple->getOperand(0)) &&
54
isa<MDString>(Tuple->getOperand(1));
55
}
56
return false;
57
}
58
59
MDTuple *MMRAMetadata::getTagMD(LLVMContext &Ctx, StringRef Prefix,
60
StringRef Suffix) {
61
return MDTuple::get(Ctx,
62
{MDString::get(Ctx, Prefix), MDString::get(Ctx, Suffix)});
63
}
64
65
MDTuple *MMRAMetadata::getMD(LLVMContext &Ctx,
66
ArrayRef<MMRAMetadata::TagT> Tags) {
67
if (Tags.empty())
68
return nullptr;
69
70
if (Tags.size() == 1)
71
return getTagMD(Ctx, Tags.front());
72
73
SmallVector<Metadata *> MMRAs;
74
for (const auto &Tag : Tags)
75
MMRAs.push_back(getTagMD(Ctx, Tag));
76
return MDTuple::get(Ctx, MMRAs);
77
}
78
79
MDNode *MMRAMetadata::combine(LLVMContext &Ctx, const MMRAMetadata &A,
80
const MMRAMetadata &B) {
81
// Let A and B be two tags set, and U be the prefix-wise union of A and B.
82
// For every unique tag prefix P present in A or B:
83
// * If either A or B has no tags with prefix P, no tags with prefix
84
// P are added to U.
85
// * If both A and B have at least one tag with prefix P, all tags with prefix
86
// P from both sets are added to U.
87
88
SmallVector<Metadata *> Result;
89
90
for (const auto &[P, S] : A) {
91
if (B.hasTagWithPrefix(P))
92
Result.push_back(getTagMD(Ctx, P, S));
93
}
94
for (const auto &[P, S] : B) {
95
if (A.hasTagWithPrefix(P))
96
Result.push_back(getTagMD(Ctx, P, S));
97
}
98
99
return MDTuple::get(Ctx, Result);
100
}
101
102
bool MMRAMetadata::hasTag(StringRef Prefix, StringRef Suffix) const {
103
return Tags.count({Prefix, Suffix});
104
}
105
106
bool MMRAMetadata::isCompatibleWith(const MMRAMetadata &Other) const {
107
// Two sets of tags are compatible iff, for every unique tag prefix P
108
// present in at least one set:
109
// - the other set contains no tag with prefix P, or
110
// - at least one tag with prefix P is common to both sets.
111
112
StringMap<bool> PrefixStatuses;
113
for (const auto &[P, S] : Tags)
114
PrefixStatuses[P] |= (Other.hasTag(P, S) || !Other.hasTagWithPrefix(P));
115
for (const auto &[P, S] : Other)
116
PrefixStatuses[P] |= (hasTag(P, S) || !hasTagWithPrefix(P));
117
118
for (auto &[Prefix, Status] : PrefixStatuses) {
119
if (!Status)
120
return false;
121
}
122
123
return true;
124
}
125
126
bool MMRAMetadata::hasTagWithPrefix(StringRef Prefix) const {
127
for (const auto &[P, S] : Tags)
128
if (P == Prefix)
129
return true;
130
return false;
131
}
132
133
MMRAMetadata::const_iterator MMRAMetadata::begin() const {
134
return Tags.begin();
135
}
136
137
MMRAMetadata::const_iterator MMRAMetadata::end() const { return Tags.end(); }
138
139
bool MMRAMetadata::empty() const { return Tags.empty(); }
140
141
unsigned MMRAMetadata::size() const { return Tags.size(); }
142
143
void MMRAMetadata::print(raw_ostream &OS) const {
144
bool IsFirst = true;
145
// TODO: use map_iter + join
146
for (const auto &[P, S] : Tags) {
147
if (IsFirst)
148
IsFirst = false;
149
else
150
OS << ", ";
151
OS << P << ":" << S;
152
}
153
}
154
155
LLVM_DUMP_METHOD
156
void MMRAMetadata::dump() const { print(dbgs()); }
157
158
//===- Helpers ------------------------------------------------------------===//
159
160
static bool isReadWriteMemCall(const Instruction &I) {
161
if (const auto *C = dyn_cast<CallBase>(&I))
162
return C->mayReadOrWriteMemory() ||
163
!C->getMemoryEffects().doesNotAccessMemory();
164
return false;
165
}
166
167
bool llvm::canInstructionHaveMMRAs(const Instruction &I) {
168
return isa<LoadInst>(I) || isa<StoreInst>(I) || isa<AtomicCmpXchgInst>(I) ||
169
isa<AtomicRMWInst>(I) || isa<FenceInst>(I) || isReadWriteMemCall(I);
170
}
171
172