[Clang/AMDGPU] Zero sized arrays not allowed in HIP device code. (#113470)
[llvm-project.git] / llvm / lib / IR / MemoryModelRelaxationAnnotations.cpp
blob819cad3366787e2b592fb5a799e475da93e9d1a9
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 //===----------------------------------------------------------------------===//
9 #include "llvm/IR/MemoryModelRelaxationAnnotations.h"
10 #include "llvm/IR/Instructions.h"
11 #include "llvm/IR/Metadata.h"
12 #include "llvm/Support/Debug.h"
13 #include "llvm/Support/raw_ostream.h"
15 using namespace llvm;
17 //===- MMRAMetadata -------------------------------------------------------===//
19 MMRAMetadata::MMRAMetadata(const Instruction &I)
20 : MMRAMetadata(I.getMetadata(LLVMContext::MD_mmra)) {}
22 MMRAMetadata::MMRAMetadata(MDNode *MD) {
23 if (!MD)
24 return;
26 // TODO: Split this into a "tryParse" function that can return an err.
27 // CTor can use the tryParse & just fatal on err.
29 MDTuple *Tuple = dyn_cast<MDTuple>(MD);
30 assert(Tuple && "Invalid MMRA structure");
32 const auto HandleTagMD = [this](MDNode *TagMD) {
33 Tags.insert({cast<MDString>(TagMD->getOperand(0))->getString(),
34 cast<MDString>(TagMD->getOperand(1))->getString()});
37 if (isTagMD(Tuple)) {
38 HandleTagMD(Tuple);
39 return;
42 for (const MDOperand &Op : Tuple->operands()) {
43 MDNode *MDOp = cast<MDNode>(Op.get());
44 assert(isTagMD(MDOp));
45 HandleTagMD(MDOp);
49 bool MMRAMetadata::isTagMD(const Metadata *MD) {
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));
55 return false;
58 MDTuple *MMRAMetadata::getTagMD(LLVMContext &Ctx, StringRef Prefix,
59 StringRef Suffix) {
60 return MDTuple::get(Ctx,
61 {MDString::get(Ctx, Prefix), MDString::get(Ctx, Suffix)});
64 MDTuple *MMRAMetadata::getMD(LLVMContext &Ctx,
65 ArrayRef<MMRAMetadata::TagT> Tags) {
66 if (Tags.empty())
67 return nullptr;
69 if (Tags.size() == 1)
70 return getTagMD(Ctx, Tags.front());
72 SmallVector<Metadata *> MMRAs;
73 for (const auto &Tag : Tags)
74 MMRAs.push_back(getTagMD(Ctx, Tag));
75 return MDTuple::get(Ctx, MMRAs);
78 MDNode *MMRAMetadata::combine(LLVMContext &Ctx, const MMRAMetadata &A,
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.
87 SmallVector<Metadata *> Result;
89 for (const auto &[P, S] : A) {
90 if (B.hasTagWithPrefix(P))
91 Result.push_back(getTagMD(Ctx, P, S));
93 for (const auto &[P, S] : B) {
94 if (A.hasTagWithPrefix(P))
95 Result.push_back(getTagMD(Ctx, P, S));
98 return MDTuple::get(Ctx, Result);
101 bool MMRAMetadata::hasTag(StringRef Prefix, StringRef Suffix) const {
102 return Tags.count({Prefix, Suffix});
105 bool MMRAMetadata::isCompatibleWith(const MMRAMetadata &Other) const {
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.
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));
117 for (auto &[Prefix, Status] : PrefixStatuses) {
118 if (!Status)
119 return false;
122 return true;
125 bool MMRAMetadata::hasTagWithPrefix(StringRef Prefix) const {
126 for (const auto &[P, S] : Tags)
127 if (P == Prefix)
128 return true;
129 return false;
132 MMRAMetadata::const_iterator MMRAMetadata::begin() const {
133 return Tags.begin();
136 MMRAMetadata::const_iterator MMRAMetadata::end() const { return Tags.end(); }
138 bool MMRAMetadata::empty() const { return Tags.empty(); }
140 unsigned MMRAMetadata::size() const { return Tags.size(); }
142 void MMRAMetadata::print(raw_ostream &OS) const {
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;
154 LLVM_DUMP_METHOD
155 void MMRAMetadata::dump() const { print(dbgs()); }
157 //===- Helpers ------------------------------------------------------------===//
159 static 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;
166 bool llvm::canInstructionHaveMMRAs(const Instruction &I) {
167 return isa<LoadInst>(I) || isa<StoreInst>(I) || isa<AtomicCmpXchgInst>(I) ||
168 isa<AtomicRMWInst>(I) || isa<FenceInst>(I) || isReadWriteMemCall(I);