LLVM 23.0.0git
NVVMProperties.cpp
Go to the documentation of this file.
1//===- NVVMProperties.cpp - NVVM annotation utilities ---------------------===//
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// This file contains NVVM attribute and metadata query utilities.
10//
11//===----------------------------------------------------------------------===//
12
13#include "NVVMProperties.h"
14#include "llvm/ADT/ArrayRef.h"
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/StringRef.h"
17#include "llvm/IR/Argument.h"
18#include "llvm/IR/Constants.h"
19#include "llvm/IR/Function.h"
20#include "llvm/IR/GlobalValue.h"
23#include "llvm/IR/Metadata.h"
24#include "llvm/IR/Module.h"
25#include "llvm/Support/ModRef.h"
26#include "llvm/Support/Mutex.h"
28#include <functional>
29#include <map>
30#include <mutex>
31#include <numeric>
32#include <string>
33#include <vector>
34
35using namespace llvm;
36
37namespace {
38using AnnotationValues = std::map<std::string, std::vector<unsigned>>;
39using AnnotationMap = std::map<const GlobalValue *, AnnotationValues>;
40
41struct AnnotationCache {
42 sys::Mutex Lock;
43 std::map<const Module *, AnnotationMap> Cache;
44};
45
46} // namespace
47
48static AnnotationCache &getAnnotationCache() {
49 static AnnotationCache AC;
50 return AC;
51}
52
53// TODO: Replace these legacy nvvm.annotations metadata names with proper
54// function/parameter attributes (like the NVVMAttr:: constants).
55namespace NVVMMetadata {
56constexpr StringLiteral Texture("texture");
57constexpr StringLiteral Surface("surface");
58constexpr StringLiteral Sampler("sampler");
59constexpr StringLiteral ReadOnlyImage("rdoimage");
60constexpr StringLiteral WriteOnlyImage("wroimage");
61constexpr StringLiteral ReadWriteImage("rdwrimage");
62constexpr StringLiteral Managed("managed");
63} // namespace NVVMMetadata
64
66 auto &AC = getAnnotationCache();
67 std::lock_guard<sys::Mutex> Guard(AC.Lock);
68 AC.Cache.erase(Mod);
69}
70
71static void cacheAnnotationFromMD(const MDNode *MetadataNode,
72 AnnotationValues &RetVal) {
73 auto &AC = getAnnotationCache();
74 std::lock_guard<sys::Mutex> Guard(AC.Lock);
75 assert(MetadataNode && "Invalid mdnode for annotation");
76 assert((MetadataNode->getNumOperands() % 2) == 1 &&
77 "Invalid number of operands");
78 // start index = 1, to skip the global variable key
79 // increment = 2, to skip the value for each property-value pairs
80 for (unsigned I = 1, E = MetadataNode->getNumOperands(); I != E; I += 2) {
81 const MDString *Prop = dyn_cast<MDString>(MetadataNode->getOperand(I));
82 assert(Prop && "Annotation property not a string");
83 std::string Key = Prop->getString().str();
84
86 MetadataNode->getOperand(I + 1))) {
87 RetVal[Key].push_back(Val->getZExtValue());
88 } else {
89 llvm_unreachable("Value operand not a constant int");
90 }
91 }
92}
93
94static void cacheAnnotationFromMD(const Module *M, const GlobalValue *GV) {
95 auto &AC = getAnnotationCache();
96 std::lock_guard<sys::Mutex> Guard(AC.Lock);
97 NamedMDNode *NMD = M->getNamedMetadata("nvvm.annotations");
98 if (!NMD)
99 return;
100
101 AnnotationValues Tmp;
102 for (unsigned I = 0, E = NMD->getNumOperands(); I != E; ++I) {
103 const MDNode *Elem = NMD->getOperand(I);
104 GlobalValue *Entity =
106 // entity may be null due to DCE
107 if (!Entity || Entity != GV)
108 continue;
109
110 cacheAnnotationFromMD(Elem, Tmp);
111 }
112
113 if (Tmp.empty())
114 return;
115
116 AC.Cache[M][GV] = std::move(Tmp);
117}
118
119static std::optional<unsigned> findOneNVVMAnnotation(const GlobalValue *GV,
120 StringRef Prop) {
121 auto &AC = getAnnotationCache();
122 std::lock_guard<sys::Mutex> Guard(AC.Lock);
123 const Module *M = GV->getParent();
124 auto ACIt = AC.Cache.find(M);
125 if (ACIt == AC.Cache.end())
127 else if (ACIt->second.find(GV) == ACIt->second.end())
129
130 auto &KVP = AC.Cache[M][GV];
131 auto It = KVP.find(Prop.str());
132 if (It == KVP.end())
133 return std::nullopt;
134 return It->second[0];
135}
136
137static bool findAllNVVMAnnotation(const GlobalValue *GV, StringRef Prop,
138 std::vector<unsigned> &RetVal) {
139 auto &AC = getAnnotationCache();
140 std::lock_guard<sys::Mutex> Guard(AC.Lock);
141 const Module *M = GV->getParent();
142 auto ACIt = AC.Cache.find(M);
143 if (ACIt == AC.Cache.end())
145 else if (ACIt->second.find(GV) == ACIt->second.end())
147
148 auto &KVP = AC.Cache[M][GV];
149 auto It = KVP.find(Prop.str());
150 if (It == KVP.end())
151 return false;
152 RetVal = It->second;
153 return true;
154}
155
156static bool globalHasNVVMAnnotation(const Value &V, StringRef Prop) {
157 if (const auto *GV = dyn_cast<GlobalValue>(&V))
158 if (const auto Annot = findOneNVVMAnnotation(GV, Prop)) {
159 assert((*Annot == 1) && "Unexpected annotation on a symbol");
160 return true;
161 }
162
163 return false;
164}
165
166static bool argHasNVVMAnnotation(const Value &Val, StringRef Annotation) {
167 if (const auto *Arg = dyn_cast<Argument>(&Val)) {
168 std::vector<unsigned> Annot;
169 if (findAllNVVMAnnotation(Arg->getParent(), Annotation, Annot) &&
170 is_contained(Annot, Arg->getArgNo()))
171 return true;
172 }
173 return false;
174}
175
176static std::optional<unsigned> getFnAttrParsedInt(const Function &F,
177 StringRef Attr) {
178 return F.hasFnAttribute(Attr)
179 ? std::optional(F.getFnAttributeAsParsedInteger(Attr))
180 : std::nullopt;
181}
182
184 StringRef Attr) {
186 auto &Ctx = F.getContext();
187
188 if (F.hasFnAttribute(Attr)) {
189 // We expect the attribute value to be of the form "x[,y[,z]]", where x, y,
190 // and z are unsigned values.
191 StringRef S = F.getFnAttribute(Attr).getValueAsString();
192 for (unsigned I = 0; I < 3 && !S.empty(); I++) {
193 auto [First, Rest] = S.split(",");
194 unsigned IntVal;
195 if (First.trim().getAsInteger(0, IntVal))
196 Ctx.emitError("can't parse integer attribute " + First + " in " + Attr);
197
198 V.push_back(IntVal);
199 S = Rest;
200 }
201 }
202 return V;
203}
204
205static std::optional<uint64_t> getVectorProduct(ArrayRef<unsigned> V) {
206 if (V.empty())
207 return std::nullopt;
208
209 return std::accumulate(V.begin(), V.end(), uint64_t(1),
210 std::multiplies<uint64_t>{});
211}
212
222
233
235 if (const auto *GV = dyn_cast<GlobalVariable>(&V))
236 return getPTXOpaqueType(*GV);
237 if (const auto *Arg = dyn_cast<Argument>(&V))
238 return getPTXOpaqueType(*Arg);
239 return PTXOpaqueType::None;
240}
241
245
249
253
257
258std::optional<uint64_t> llvm::getOverallMaxNTID(const Function &F) {
259 // Note: The semantics here are a bit strange. The PTX ISA states the
260 // following (11.4.2. Performance-Tuning Directives: .maxntid):
261 //
262 // Note that this directive guarantees that the total number of threads does
263 // not exceed the maximum, but does not guarantee that the limit in any
264 // particular dimension is not exceeded.
266}
267
268std::optional<uint64_t> llvm::getOverallReqNTID(const Function &F) {
269 // Note: The semantics here are a bit strange. See getOverallMaxNTID.
271}
272
273std::optional<uint64_t> llvm::getOverallClusterRank(const Function &F) {
274 // maxclusterrank and cluster_dim are mutually exclusive.
275 if (const auto ClusterRank = getMaxClusterRank(F))
276 return ClusterRank;
277
278 // Note: The semantics here are a bit strange. See getOverallMaxNTID.
280}
281
282std::optional<unsigned> llvm::getMaxClusterRank(const Function &F) {
284}
285
286std::optional<unsigned> llvm::getMinCTASm(const Function &F) {
288}
289
290std::optional<unsigned> llvm::getMaxNReg(const Function &F) {
292}
293
295 return F.hasFnAttribute(NVVMAttr::BlocksAreClusters);
296}
297
300 "only kernel arguments can be grid_constant");
301
302 if (!Arg.hasByValAttr())
303 return false;
304
305 // Lowering an argument as a grid_constant violates the byval semantics (and
306 // the C++ API) by reusing the same memory location for the argument across
307 // multiple threads. If an argument doesn't read memory and its address is not
308 // captured (its address is not compared with any value), then the tweak of
309 // the C++ API and byval semantics is unobservable by the program and we can
310 // lower the arg as a grid_constant.
311 if (Arg.onlyReadsMemory()) {
312 const auto CI = Arg.getAttributes().getCaptureInfo();
314 return true;
315 }
316
317 // "grid_constant" counts argument indices starting from 1
319}
320
321MaybeAlign llvm::getStackAlign(const CallBase &I, unsigned Index) {
322 // First check the alignstack metadata.
323 if (MaybeAlign StackAlign =
324 I.getAttributes().getAttributes(Index).getStackAlignment())
325 return StackAlign;
326
327 // If that is missing, check the legacy nvvm metadata.
328 if (MDNode *AlignNode = I.getMetadata("callalign")) {
329 for (int I = 0, N = AlignNode->getNumOperands(); I < N; I++) {
330 if (const auto *CI =
331 mdconst::dyn_extract<ConstantInt>(AlignNode->getOperand(I))) {
332 unsigned V = CI->getZExtValue();
333 if ((V >> 16) == Index)
334 return Align(V & 0xFFFF);
335 if ((V >> 16) > Index)
336 return std::nullopt;
337 }
338 }
339 }
340 return std::nullopt;
341}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
This file contains the declarations for metadata subclasses.
static void cacheAnnotationFromMD(const MDNode *MetadataNode, AnnotationValues &RetVal)
static AnnotationCache & getAnnotationCache()
static bool findAllNVVMAnnotation(const GlobalValue *GV, StringRef Prop, std::vector< unsigned > &RetVal)
static std::optional< unsigned > getFnAttrParsedInt(const Function &F, StringRef Attr)
static std::optional< unsigned > findOneNVVMAnnotation(const GlobalValue *GV, StringRef Prop)
static bool globalHasNVVMAnnotation(const Value &V, StringRef Prop)
static bool argHasNVVMAnnotation(const Value &Val, StringRef Annotation)
static std::optional< uint64_t > getVectorProduct(ArrayRef< unsigned > V)
static SmallVector< unsigned, 3 > getFnAttrParsedVector(const Function &F, StringRef Attr)
This file contains some templates that are useful if you are working with the STL at all.
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
LLVM_ABI bool onlyReadsMemory() const
Return true if this argument has the readonly or readnone attribute.
Definition Function.cpp:303
LLVM_ABI bool hasAttribute(Attribute::AttrKind Kind) const
Check if an argument has a given attribute.
Definition Function.cpp:333
LLVM_ABI bool hasByValAttr() const
Return true if this argument has the byval attribute.
Definition Function.cpp:127
const Function * getParent() const
Definition Argument.h:44
LLVM_ABI AttributeSet getAttributes() const
Definition Function.cpp:345
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
LLVM_ABI CaptureInfo getCaptureInfo() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
This is the shared class of boolean and integer constants.
Definition Constants.h:87
Module * getParent()
Get the module that this global value is contained inside of...
Metadata node.
Definition Metadata.h:1069
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1426
unsigned getNumOperands() const
Return number of MDNode operands.
Definition Metadata.h:1432
A single uniqued string.
Definition Metadata.h:722
LLVM_ABI StringRef getString() const
Definition Metadata.cpp:632
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
A tuple of MDNodes.
Definition Metadata.h:1753
LLVM_ABI MDNode * getOperand(unsigned i) const
LLVM_ABI unsigned getNumOperands() const
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
Definition StringRef.h:888
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:736
std::string str() const
Get the contents as an std::string.
Definition StringRef.h:222
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
LLVM Value Representation.
Definition Value.h:75
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr StringLiteral Surface("surface")
constexpr StringLiteral ReadOnlyImage("rdoimage")
constexpr StringLiteral WriteOnlyImage("wroimage")
constexpr StringLiteral Texture("texture")
constexpr StringLiteral ReadWriteImage("rdwrimage")
constexpr StringLiteral Sampler("sampler")
constexpr StringLiteral Managed("managed")
constexpr StringLiteral GridConstant("nvvm.grid_constant")
constexpr StringLiteral MaxNTID("nvvm.maxntid")
constexpr StringLiteral MaxNReg("nvvm.maxnreg")
constexpr StringLiteral MinCTASm("nvvm.minctasm")
constexpr StringLiteral ReqNTID("nvvm.reqntid")
constexpr StringLiteral MaxClusterRank("nvvm.maxclusterrank")
constexpr StringLiteral ClusterDim("nvvm.cluster_dim")
constexpr StringLiteral BlocksAreClusters("nvvm.blocksareclusters")
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract_or_null(Y &&MD)
Extract a Value from Metadata, if any, allowing null.
Definition Metadata.h:709
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract(Y &&MD)
Extract a Value from Metadata, if any.
Definition Metadata.h:696
SmartMutex< false > Mutex
Mutex - A standard, always enforced mutex.
Definition Mutex.h:66
This is an optimization pass for GlobalISel generic memory operations.
bool isManaged(const Value &)
SmallVector< unsigned, 3 > getReqNTID(const Function &)
bool hasBlocksAreClusters(const Function &)
SmallVector< unsigned, 3 > getClusterDim(const Function &)
bool capturesAddress(CaptureComponents CC)
Definition ModRef.h:387
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
std::optional< unsigned > getMaxNReg(const Function &)
PTXOpaqueType getPTXOpaqueType(const GlobalVariable &)
std::optional< uint64_t > getOverallClusterRank(const Function &)
std::optional< unsigned > getMinCTASm(const Function &)
bool capturesFullProvenance(CaptureComponents CC)
Definition ModRef.h:396
SmallVector< unsigned, 3 > getMaxNTID(const Function &)
std::optional< unsigned > getMaxClusterRank(const Function &)
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
@ Mod
The access may modify the value stored in memory.
Definition ModRef.h:34
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
std::optional< uint64_t > getOverallReqNTID(const Function &)
bool isKernelFunction(const Function &F)
std::optional< uint64_t > getOverallMaxNTID(const Function &)
MaybeAlign getStackAlign(const Function &F, unsigned Index)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
bool isParamGridConstant(const Argument &)
void clearAnnotationCache(const Module *)
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition Alignment.h:106