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 declarations for PTX-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/Function.h"
21#include "llvm/IR/IntrinsicInst.h"
22#include "llvm/IR/Value.h"
23#include "llvm/Support/Alignment.h"
24#include "llvm/Support/FormatVariadic.h"
25#include <cstdarg>
26#include <string>
27
28namespace llvm {
29
30class DataLayout;
31class TargetMachine;
32
33Function *getMaybeBitcastedCallee(const CallBase *CB);
34
35/// Since function arguments are passed via .param space, we may want to
36/// increase their alignment in a way that ensures that we can effectively
37/// vectorize their loads & stores. We can increase alignment only if the
38/// function has internal or private linkage as for other linkage types callers
39/// may already rely on default alignment. To allow using 128-bit vectorized
40/// loads/stores, this function ensures that alignment is 16 or greater.
41Align getPTXPromotedParamTypeAlign(const Function *F, Type *ArgTy,
42 const DataLayout &DL);
43
44Align getDeviceByValParamAlign(const Function *F, Type *ArgTy,
45 Align InitialAlign, const DataLayout &DL);
46
47/// Get the alignment for a function parameter or return value.
48/// \p AttrIdx is the AttributeList index (e.g. FirstArgIndex + argNo, or
49/// ReturnIndex for return values). Checks for an explicit alignment attribute,
50/// then falls back to getPromotedParamTypeAlign, incorporating byval param
51/// alignment when applicable.
52Align getPTXParamAlign(const Function *F, Type *Ty, unsigned AttrIdx,
53 const DataLayout &DL);
54
55/// Get the alignment for a call-site argument or return value. Resolves the
56/// callee and delegates to the Function overload of getParamAlign. For
57/// indirect calls with no resolvable callee, falls back to
58/// getPromotedParamTypeAlign.
59Align getPTXParamAlign(const CallBase *CB, Type *Ty, unsigned AttrIdx,
60 const DataLayout &DL);
61
62// PTX ABI requires all scalar argument/return values to have
63// bit-size as a power of two of at least 32 bits.
64inline unsigned promoteScalarArgumentSize(unsigned size) {
65 if (size <= 32)
66 return 32;
67 if (size <= 64)
68 return 64;
69 if (size <= 128)
70 return 128;
71 return size;
72}
73
74bool shouldEmitPTXNoReturn(const Value *V, const TargetMachine &TM);
75
76inline bool shouldPassAsArray(Type *Ty) {
77 return Ty->isAggregateType() || Ty->isVectorTy() ||
78 Ty->getScalarSizeInBits() >= 128 || Ty->isHalfTy() || Ty->isBFloatTy();
79}
80
81namespace NVPTX {
82// Returns a list of vector types that we prefer to fit into a single PTX
83// register. NOTE: This must be kept in sync with the register classes
84// defined in NVPTXRegisterInfo.td.
85inline auto packed_types() {
86 static const auto PackedTypes = {MVT::v4i8, MVT::v2f16, MVT::v2bf16,
87 MVT::v2i16, MVT::v2f32, MVT::v2i32};
88 return PackedTypes;
89}
90
91// Checks if the type VT can fit into a single register.
92inline bool isPackedVectorTy(EVT VT) {
93 return any_of(Range: packed_types(), P: equal_to(Arg&: VT));
94}
95
96// Checks if two or more of the type ET can fit into a single register.
97inline bool isPackedElementTy(EVT ET) {
98 return any_of(Range: packed_types(),
99 P: [ET](EVT OVT) { return OVT.getVectorElementType() == ET; });
100}
101
102inline std::string getValidPTXIdentifier(StringRef Name) {
103 std::string ValidName;
104 ValidName.reserve(res_arg: Name.size() + 4);
105 for (char C : Name)
106 // While PTX also allows '%' at the start of identifiers, LLVM will throw a
107 // fatal error for '%' in symbol names in MCSymbol::print. Exclude for now.
108 if (isAlnum(C) || C == '_' || C == '$')
109 ValidName.push_back(c: C);
110 else
111 ValidName.append(l: {'_', '$', '_'});
112
113 return ValidName;
114}
115
116inline std::string OrderingToString(Ordering Order) {
117 switch (Order) {
118 case Ordering::NotAtomic:
119 return "NotAtomic";
120 case Ordering::Relaxed:
121 return "Relaxed";
122 case Ordering::Acquire:
123 return "Acquire";
124 case Ordering::Release:
125 return "Release";
126 case Ordering::AcquireRelease:
127 return "AcquireRelease";
128 case Ordering::SequentiallyConsistent:
129 return "SequentiallyConsistent";
130 case Ordering::Volatile:
131 return "Volatile";
132 case Ordering::RelaxedMMIO:
133 return "RelaxedMMIO";
134 }
135 report_fatal_error(reason: formatv(Fmt: "Unknown NVPTX::Ordering \"{}\".",
136 Vals: static_cast<OrderingUnderlyingType>(Order)));
137}
138
139inline raw_ostream &operator<<(raw_ostream &O, Ordering Order) {
140 O << OrderingToString(Order);
141 return O;
142}
143
144inline std::string ScopeToString(Scope S) {
145 switch (S) {
146 case Scope::Thread:
147 return "Thread";
148 case Scope::System:
149 return "System";
150 case Scope::Block:
151 return "Block";
152 case Scope::Cluster:
153 return "Cluster";
154 case Scope::Device:
155 return "Device";
156 case Scope::DefaultDevice:
157 return "DefaultDevice";
158 }
159 report_fatal_error(reason: formatv(Fmt: "Unknown NVPTX::Scope \"{}\".",
160 Vals: static_cast<ScopeUnderlyingType>(S)));
161}
162
163inline raw_ostream &operator<<(raw_ostream &O, Scope S) {
164 O << ScopeToString(S);
165 return O;
166}
167
168inline const char *addressSpaceToString(AddressSpace A,
169 bool UseParamSubqualifiers = false) {
170 switch (A) {
171 case AddressSpace::Generic:
172 return "generic";
173 case AddressSpace::Global:
174 return "global";
175 case AddressSpace::Const:
176 return "const";
177 case AddressSpace::Shared:
178 return "shared";
179 case AddressSpace::SharedCluster:
180 return "shared::cluster";
181 case AddressSpace::EntryParam:
182 return UseParamSubqualifiers ? "param::entry" : "param";
183 case AddressSpace::DeviceParam:
184 return UseParamSubqualifiers ? "param::func" : "param";
185 case AddressSpace::Local:
186 return "local";
187 }
188 report_fatal_error(reason: formatv(Fmt: "Unknown NVPTX::AddressSpace \"{}\".",
189 Vals: static_cast<AddressSpaceUnderlyingType>(A)));
190}
191
192inline raw_ostream &operator<<(raw_ostream &O, AddressSpace A) {
193 O << addressSpaceToString(A);
194 return O;
195}
196
197} // namespace NVPTX
198} // namespace llvm
199
200#endif
201