1//===-- NVPTXUtilities - Utilities -----------------------------*- 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// This file contains the declaration of the NVVM specific utility functions.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_LIB_TARGET_NVPTX_NVPTXUTILITIES_H
14#define LLVM_LIB_TARGET_NVPTX_NVPTXUTILITIES_H
15
16#include "NVPTX.h"
17#include "llvm/ADT/SmallVector.h"
18#include "llvm/ADT/StringExtras.h"
19#include "llvm/CodeGen/ValueTypes.h"
20#include "llvm/IR/CallingConv.h"
21#include "llvm/IR/Function.h"
22#include "llvm/IR/GlobalVariable.h"
23#include "llvm/IR/IntrinsicInst.h"
24#include "llvm/IR/Value.h"
25#include "llvm/Support/Alignment.h"
26#include "llvm/Support/FormatVariadic.h"
27#include <cstdarg>
28#include <string>
29
30namespace llvm {
31
32class TargetMachine;
33
34void clearAnnotationCache(const Module *);
35
36bool isTexture(const Value &);
37bool isSurface(const Value &);
38bool isSampler(const Value &);
39bool isImage(const Value &);
40bool isImageReadOnly(const Value &);
41bool isImageWriteOnly(const Value &);
42bool isImageReadWrite(const Value &);
43bool isManaged(const Value &);
44
45StringRef getTextureName(const Value &);
46StringRef getSurfaceName(const Value &);
47StringRef getSamplerName(const Value &);
48
49SmallVector<unsigned, 3> getMaxNTID(const Function &);
50SmallVector<unsigned, 3> getReqNTID(const Function &);
51SmallVector<unsigned, 3> getClusterDim(const Function &);
52
53std::optional<uint64_t> getOverallMaxNTID(const Function &);
54std::optional<uint64_t> getOverallReqNTID(const Function &);
55std::optional<uint64_t> getOverallClusterRank(const Function &);
56
57std::optional<unsigned> getMaxClusterRank(const Function &);
58std::optional<unsigned> getMinCTASm(const Function &);
59std::optional<unsigned> getMaxNReg(const Function &);
60
61bool hasBlocksAreClusters(const Function &);
62
63inline bool isKernelFunction(const Function &F) {
64 return F.getCallingConv() == CallingConv::PTX_Kernel;
65}
66
67bool isParamGridConstant(const Argument &);
68
69inline MaybeAlign getAlign(const Function &F, unsigned Index) {
70 return F.getAttributes().getAttributes(Index).getStackAlignment();
71}
72
73MaybeAlign getAlign(const CallInst &, unsigned);
74Function *getMaybeBitcastedCallee(const CallBase *CB);
75
76// PTX ABI requires all scalar argument/return values to have
77// bit-size as a power of two of at least 32 bits.
78inline unsigned promoteScalarArgumentSize(unsigned size) {
79 if (size <= 32)
80 return 32;
81 if (size <= 64)
82 return 64;
83 if (size <= 128)
84 return 128;
85 return size;
86}
87
88bool shouldEmitPTXNoReturn(const Value *V, const TargetMachine &TM);
89
90inline bool shouldPassAsArray(Type *Ty) {
91 return Ty->isAggregateType() || Ty->isVectorTy() ||
92 Ty->getScalarSizeInBits() >= 128 || Ty->isHalfTy() || Ty->isBFloatTy();
93}
94
95namespace NVPTX {
96// Returns a list of vector types that we prefer to fit into a single PTX
97// register. NOTE: This must be kept in sync with the register classes
98// defined in NVPTXRegisterInfo.td.
99inline auto packed_types() {
100 static const auto PackedTypes = {MVT::v4i8, MVT::v2f16, MVT::v2bf16,
101 MVT::v2i16, MVT::v2f32, MVT::v2i32};
102 return PackedTypes;
103}
104
105// Checks if the type VT can fit into a single register.
106inline bool isPackedVectorTy(EVT VT) {
107 return any_of(Range: packed_types(), P: equal_to(Arg&: VT));
108}
109
110// Checks if two or more of the type ET can fit into a single register.
111inline bool isPackedElementTy(EVT ET) {
112 return any_of(Range: packed_types(),
113 P: [ET](EVT OVT) { return OVT.getVectorElementType() == ET; });
114}
115
116inline std::string getValidPTXIdentifier(StringRef Name) {
117 std::string ValidName;
118 ValidName.reserve(res_arg: Name.size() + 4);
119 for (char C : Name)
120 // While PTX also allows '%' at the start of identifiers, LLVM will throw a
121 // fatal error for '%' in symbol names in MCSymbol::print. Exclude for now.
122 if (isAlnum(C) || C == '_' || C == '$')
123 ValidName.push_back(c: C);
124 else
125 ValidName.append(l: {'_', '$', '_'});
126
127 return ValidName;
128}
129
130inline std::string OrderingToString(Ordering Order) {
131 switch (Order) {
132 case Ordering::NotAtomic:
133 return "NotAtomic";
134 case Ordering::Relaxed:
135 return "Relaxed";
136 case Ordering::Acquire:
137 return "Acquire";
138 case Ordering::Release:
139 return "Release";
140 case Ordering::AcquireRelease:
141 return "AcquireRelease";
142 case Ordering::SequentiallyConsistent:
143 return "SequentiallyConsistent";
144 case Ordering::Volatile:
145 return "Volatile";
146 case Ordering::RelaxedMMIO:
147 return "RelaxedMMIO";
148 }
149 report_fatal_error(reason: formatv(Fmt: "Unknown NVPTX::Ordering \"{}\".",
150 Vals: static_cast<OrderingUnderlyingType>(Order)));
151}
152
153inline raw_ostream &operator<<(raw_ostream &O, Ordering Order) {
154 O << OrderingToString(Order);
155 return O;
156}
157
158inline std::string ScopeToString(Scope S) {
159 switch (S) {
160 case Scope::Thread:
161 return "Thread";
162 case Scope::System:
163 return "System";
164 case Scope::Block:
165 return "Block";
166 case Scope::Cluster:
167 return "Cluster";
168 case Scope::Device:
169 return "Device";
170 case Scope::DefaultDevice:
171 return "DefaultDevice";
172 }
173 report_fatal_error(reason: formatv(Fmt: "Unknown NVPTX::Scope \"{}\".",
174 Vals: static_cast<ScopeUnderlyingType>(S)));
175}
176
177inline raw_ostream &operator<<(raw_ostream &O, Scope S) {
178 O << ScopeToString(S);
179 return O;
180}
181
182inline std::string AddressSpaceToString(AddressSpace A) {
183 switch (A) {
184 case AddressSpace::Generic:
185 return "generic";
186 case AddressSpace::Global:
187 return "global";
188 case AddressSpace::Const:
189 return "const";
190 case AddressSpace::Shared:
191 return "shared";
192 case AddressSpace::SharedCluster:
193 return "shared::cluster";
194 case AddressSpace::Param:
195 return "param";
196 case AddressSpace::Local:
197 return "local";
198 }
199 report_fatal_error(reason: formatv(Fmt: "Unknown NVPTX::AddressSpace \"{}\".",
200 Vals: static_cast<AddressSpaceUnderlyingType>(A)));
201}
202
203inline raw_ostream &operator<<(raw_ostream &O, AddressSpace A) {
204 O << AddressSpaceToString(A);
205 return O;
206}
207
208} // namespace NVPTX
209} // namespace llvm
210
211#endif
212