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
35namespace 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
46AnnotationCache &getAnnotationCache() {
47 static AnnotationCache AC;
48 return AC;
49}
50} // namespace
51
52// TODO: Replace these legacy nvvm.annotations metadata names with proper
53// function/parameter attributes (like the NVVMAttr:: constants).
54namespace NVVMMetadata {
55constexpr StringLiteral Texture("texture");
56constexpr StringLiteral Surface("surface");
57constexpr StringLiteral Sampler("sampler");
58constexpr StringLiteral ReadOnlyImage("rdoimage");
59constexpr StringLiteral WriteOnlyImage("wroimage");
60constexpr StringLiteral ReadWriteImage("rdwrimage");
61constexpr StringLiteral Managed("managed");
62} // namespace NVVMMetadata
63
65 auto &AC = getAnnotationCache();
66 std::lock_guard<sys::Mutex> Guard(AC.Lock);
67 AC.Cache.erase(Mod);
68}
69
70static void cacheAnnotationFromMD(const MDNode *MetadataNode,
71 AnnotationValues &RetVal) {
72 auto &AC = getAnnotationCache();
73 std::lock_guard<sys::Mutex> Guard(AC.Lock);
74 assert(MetadataNode && "Invalid mdnode for annotation");
75 assert((MetadataNode->getNumOperands() % 2) == 1 &&
76 "Invalid number of operands");
77 // start index = 1, to skip the global variable key
78 // increment = 2, to skip the value for each property-value pairs
79 for (unsigned I = 1, E = MetadataNode->getNumOperands(); I != E; I += 2) {
80 const MDString *Prop = dyn_cast<MDString>(MetadataNode->getOperand(I));
81 assert(Prop && "Annotation property not a string");
82 std::string Key = Prop->getString().str();
83
85 MetadataNode->getOperand(I + 1))) {
86 RetVal[Key].push_back(Val->getZExtValue());
87 } else {
88 llvm_unreachable("Value operand not a constant int");
89 }
90 }
91}
92
93static void cacheAnnotationFromMD(const Module *M, const GlobalValue *GV) {
94 auto &AC = getAnnotationCache();
95 std::lock_guard<sys::Mutex> Guard(AC.Lock);
96 NamedMDNode *NMD = M->getNamedMetadata("nvvm.annotations");
97 if (!NMD)
98 return;
99
100 AnnotationValues Tmp;
101 for (unsigned I = 0, E = NMD->getNumOperands(); I != E; ++I) {
102 const MDNode *Elem = NMD->getOperand(I);
103 GlobalValue *Entity =
105 // entity may be null due to DCE
106 if (!Entity || Entity != GV)
107 continue;
108
109 cacheAnnotationFromMD(Elem, Tmp);
110 }
111
112 if (Tmp.empty())
113 return;
114
115 AC.Cache[M][GV] = std::move(Tmp);
116}
117
118static std::optional<unsigned> findOneNVVMAnnotation(const GlobalValue *GV,
119 StringRef Prop) {
120 auto &AC = getAnnotationCache();
121 std::lock_guard<sys::Mutex> Guard(AC.Lock);
122 const Module *M = GV->getParent();
123 auto ACIt = AC.Cache.find(M);
124 if (ACIt == AC.Cache.end())
126 else if (ACIt->second.find(GV) == ACIt->second.end())
128
129 auto &KVP = AC.Cache[M][GV];
130 auto It = KVP.find(Prop.str());
131 if (It == KVP.end())
132 return std::nullopt;
133 return It->second[0];
134}
135
136static bool findAllNVVMAnnotation(const GlobalValue *GV, StringRef Prop,
137 std::vector<unsigned> &RetVal) {
138 auto &AC = getAnnotationCache();
139 std::lock_guard<sys::Mutex> Guard(AC.Lock);
140 const Module *M = GV->getParent();
141 auto ACIt = AC.Cache.find(M);
142 if (ACIt == AC.Cache.end())
144 else if (ACIt->second.find(GV) == ACIt->second.end())
146
147 auto &KVP = AC.Cache[M][GV];
148 auto It = KVP.find(Prop.str());
149 if (It == KVP.end())
150 return false;
151 RetVal = It->second;
152 return true;
153}
154
155static bool globalHasNVVMAnnotation(const Value &V, StringRef Prop) {
156 if (const auto *GV = dyn_cast<GlobalValue>(&V))
157 if (const auto Annot = findOneNVVMAnnotation(GV, Prop)) {
158 assert((*Annot == 1) && "Unexpected annotation on a symbol");
159 return true;
160 }
161
162 return false;
163}
164
165static bool argHasNVVMAnnotation(const Value &Val, StringRef Annotation) {
166 if (const auto *Arg = dyn_cast<Argument>(&Val)) {
167 std::vector<unsigned> Annot;
168 if (findAllNVVMAnnotation(Arg->getParent(), Annotation, Annot) &&
169 is_contained(Annot, Arg->getArgNo()))
170 return true;
171 }
172 return false;
173}
174
175static std::optional<unsigned> getFnAttrParsedInt(const Function &F,
176 StringRef Attr) {
177 return F.hasFnAttribute(Attr)
178 ? std::optional(F.getFnAttributeAsParsedInteger(Attr))
179 : std::nullopt;
180}
181
183 StringRef Attr) {
185 auto &Ctx = F.getContext();
186
187 if (F.hasFnAttribute(Attr)) {
188 // We expect the attribute value to be of the form "x[,y[,z]]", where x, y,
189 // and z are unsigned values.
190 StringRef S = F.getFnAttribute(Attr).getValueAsString();
191 for (unsigned I = 0; I < 3 && !S.empty(); I++) {
192 auto [First, Rest] = S.split(",");
193 unsigned IntVal;
194 if (First.trim().getAsInteger(0, IntVal))
195 Ctx.emitError("can't parse integer attribute " + First + " in " + Attr);
196
197 V.push_back(IntVal);
198 S = Rest;
199 }
200 }
201 return V;
202}
203
204static std::optional<uint64_t> getVectorProduct(ArrayRef<unsigned> V) {
205 if (V.empty())
206 return std::nullopt;
207
208 return std::accumulate(V.begin(), V.end(), uint64_t(1),
209 std::multiplies<uint64_t>{});
210}
211
221
232
234 if (const auto *GV = dyn_cast<GlobalVariable>(&V))
235 return getPTXOpaqueType(*GV);
236 if (const auto *Arg = dyn_cast<Argument>(&V))
237 return getPTXOpaqueType(*Arg);
238 return PTXOpaqueType::None;
239}
240
241bool isManaged(const Value &V) {
243}
244
248
252
256
257std::optional<uint64_t> getOverallMaxNTID(const Function &F) {
258 // Note: The semantics here are a bit strange. The PTX ISA states the
259 // following (11.4.2. Performance-Tuning Directives: .maxntid):
260 //
261 // Note that this directive guarantees that the total number of threads does
262 // not exceed the maximum, but does not guarantee that the limit in any
263 // particular dimension is not exceeded.
265}
266
267std::optional<uint64_t> getOverallReqNTID(const Function &F) {
268 // Note: The semantics here are a bit strange. See getOverallMaxNTID.
270}
271
272std::optional<uint64_t> getOverallClusterRank(const Function &F) {
273 // maxclusterrank and cluster_dim are mutually exclusive.
274 if (const auto ClusterRank = getMaxClusterRank(F))
275 return ClusterRank;
276
277 // Note: The semantics here are a bit strange. See getOverallMaxNTID.
279}
280
281std::optional<unsigned> getMaxClusterRank(const Function &F) {
283}
284
285std::optional<unsigned> getMinCTASm(const Function &F) {
287}
288
289std::optional<unsigned> getMaxNReg(const Function &F) {
291}
292
294 return F.hasFnAttribute(NVVMAttr::BlocksAreClusters);
295}
296
299 "only kernel arguments can be grid_constant");
300
301 if (!Arg.hasByValAttr())
302 return false;
303
304 // Lowering an argument as a grid_constant violates the byval semantics (and
305 // the C++ API) by reusing the same memory location for the argument across
306 // multiple threads. If an argument doesn't read memory and its address is not
307 // captured (its address is not compared with any value), then the tweak of
308 // the C++ API and byval semantics is unobservable by the program and we can
309 // lower the arg as a grid_constant.
310 if (Arg.onlyReadsMemory()) {
311 const auto CI = Arg.getAttributes().getCaptureInfo();
313 return true;
314 }
315
316 // "grid_constant" counts argument indices starting from 1
318}
319
320MaybeAlign getAlign(const CallInst &I, unsigned Index) {
321 // First check the alignstack metadata.
322 if (MaybeAlign StackAlign =
323 I.getAttributes().getAttributes(Index).getStackAlignment())
324 return StackAlign;
325
326 // If that is missing, check the legacy nvvm metadata.
327 if (MDNode *AlignNode = I.getMetadata("callalign")) {
328 for (int I = 0, N = AlignNode->getNumOperands(); I < N; I++) {
329 if (const auto *CI =
330 mdconst::dyn_extract<ConstantInt>(AlignNode->getOperand(I))) {
331 unsigned V = CI->getZExtValue();
332 if ((V >> 16) == Index)
333 return Align(V & 0xFFFF);
334 if ((V >> 16) > Index)
335 return std::nullopt;
336 }
337 }
338 }
339 return std::nullopt;
340}
341
342} // namespace llvm
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.
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:308
LLVM_ABI bool hasAttribute(Attribute::AttrKind Kind) const
Check if an argument has a given attribute.
Definition Function.cpp:338
LLVM_ABI bool hasByValAttr() const
Return true if this argument has the byval attribute.
Definition Function.cpp:128
const Function * getParent() const
Definition Argument.h:44
LLVM_ABI AttributeSet getAttributes() const
Definition Function.cpp:350
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
LLVM_ABI CaptureInfo getCaptureInfo() const
This class represents a function call, abstracting a target machine's calling convention.
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:1080
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1444
unsigned getNumOperands() const
Return number of MDNode operands.
Definition Metadata.h:1450
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:1760
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:882
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:730
std::string str() const
str - Get the contents as an std::string.
Definition StringRef.h:222
constexpr bool empty() const
empty - Check if the string is empty.
Definition StringRef.h:140
LLVM Value Representation.
Definition Value.h:75
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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")
constexpr StringLiteral Texture("texture")
constexpr StringLiteral ReadOnlyImage("rdoimage")
constexpr StringLiteral WriteOnlyImage("wroimage")
constexpr StringLiteral Sampler("sampler")
constexpr StringLiteral Surface("surface")
constexpr StringLiteral Managed("managed")
constexpr StringLiteral ReadWriteImage("rdwrimage")
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.
Definition Types.h:26
static void cacheAnnotationFromMD(const MDNode *MetadataNode, AnnotationValues &RetVal)
bool isManaged(const Value &V)
std::optional< uint64_t > getOverallClusterRank(const Function &F)
MaybeAlign getAlign(const CallInst &I, unsigned Index)
static std::optional< uint64_t > getVectorProduct(ArrayRef< unsigned > V)
std::optional< unsigned > getMaxNReg(const Function &F)
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 > getMinCTASm(const Function &F)
SmallVector< unsigned, 3 > getReqNTID(const Function &F)
bool capturesFullProvenance(CaptureComponents CC)
Definition ModRef.h:396
static bool argHasNVVMAnnotation(const Value &Val, StringRef Annotation)
void clearAnnotationCache(const Module *Mod)
static bool globalHasNVVMAnnotation(const Value &V, StringRef Prop)
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
std::optional< unsigned > getMaxClusterRank(const Function &F)
@ 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
SmallVector< unsigned, 3 > getMaxNTID(const Function &F)
bool isParamGridConstant(const Argument &Arg)
static std::optional< unsigned > getFnAttrParsedInt(const Function &F, StringRef Attr)
std::optional< uint64_t > getOverallReqNTID(const Function &F)
bool isKernelFunction(const Function &F)
static bool findAllNVVMAnnotation(const GlobalValue *GV, StringRef Prop, std::vector< unsigned > &RetVal)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
std::optional< uint64_t > getOverallMaxNTID(const Function &F)
bool hasBlocksAreClusters(const Function &F)
SmallVector< unsigned, 3 > getClusterDim(const Function &F)
PTXOpaqueType getPTXOpaqueType(const GlobalVariable &GV)
static SmallVector< unsigned, 3 > getFnAttrParsedVector(const Function &F, StringRef Attr)
static std::optional< unsigned > findOneNVVMAnnotation(const GlobalValue *GV, StringRef Prop)
#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