LLVM 19.0.0git
NVPTXGenericToNVVM.cpp
Go to the documentation of this file.
1//===-- GenericToNVVM.cpp - Convert generic module to NVVM module - 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// Convert generic global variables into either .global or .const access based
10// on the variable's "constant" qualifier.
11//
12//===----------------------------------------------------------------------===//
13
15#include "NVPTX.h"
16#include "NVPTXUtilities.h"
18#include "llvm/IR/Constants.h"
20#include "llvm/IR/IRBuilder.h"
22#include "llvm/IR/Intrinsics.h"
24#include "llvm/IR/Module.h"
25#include "llvm/IR/Operator.h"
26#include "llvm/IR/ValueMap.h"
28
29using namespace llvm;
30
31namespace llvm {
33}
34
35namespace {
36class GenericToNVVM {
37public:
38 bool runOnModule(Module &M);
39
40private:
41 Value *remapConstant(Module *M, Function *F, Constant *C,
42 IRBuilder<> &Builder);
43 Value *remapConstantVectorOrConstantAggregate(Module *M, Function *F,
44 Constant *C,
45 IRBuilder<> &Builder);
46 Value *remapConstantExpr(Module *M, Function *F, ConstantExpr *C,
47 IRBuilder<> &Builder);
48
50 typedef ValueMap<Constant *, Value *> ConstantToValueMapTy;
51 GVMapTy GVMap;
52 ConstantToValueMapTy ConstantToValueMap;
53};
54} // end namespace
55
56bool GenericToNVVM::runOnModule(Module &M) {
57 // Create a clone of each global variable that has the default address space.
58 // The clone is created with the global address space specifier, and the pair
59 // of original global variable and its clone is placed in the GVMap for later
60 // use.
61
62 for (GlobalVariable &GV : llvm::make_early_inc_range(M.globals())) {
63 if (GV.getType()->getAddressSpace() == llvm::ADDRESS_SPACE_GENERIC &&
64 !llvm::isTexture(GV) && !llvm::isSurface(GV) && !llvm::isSampler(GV) &&
65 !GV.getName().starts_with("llvm.")) {
66 GlobalVariable *NewGV = new GlobalVariable(
67 M, GV.getValueType(), GV.isConstant(), GV.getLinkage(),
68 GV.hasInitializer() ? GV.getInitializer() : nullptr, "", &GV,
69 GV.getThreadLocalMode(), llvm::ADDRESS_SPACE_GLOBAL);
70 NewGV->copyAttributesFrom(&GV);
71 NewGV->copyMetadata(&GV, /*Offset=*/0);
72 GVMap[&GV] = NewGV;
73 }
74 }
75
76 // Return immediately, if every global variable has a specific address space
77 // specifier.
78 if (GVMap.empty()) {
79 return false;
80 }
81
82 // Walk through the instructions in function defitinions, and replace any use
83 // of original global variables in GVMap with a use of the corresponding
84 // copies in GVMap. If necessary, promote constants to instructions.
85 for (Function &F : M) {
86 if (F.isDeclaration()) {
87 continue;
88 }
89 IRBuilder<> Builder(F.getEntryBlock().getFirstNonPHIOrDbg());
90 for (BasicBlock &BB : F) {
91 for (Instruction &II : BB) {
92 for (unsigned i = 0, e = II.getNumOperands(); i < e; ++i) {
93 Value *Operand = II.getOperand(i);
94 if (isa<Constant>(Operand)) {
95 II.setOperand(
96 i, remapConstant(&M, &F, cast<Constant>(Operand), Builder));
97 }
98 }
99 }
100 }
101 ConstantToValueMap.clear();
102 }
103
104 // Copy GVMap over to a standard value map.
106 for (auto I = GVMap.begin(), E = GVMap.end(); I != E; ++I)
107 VM[I->first] = I->second;
108
109 // Walk through the global variable initializers, and replace any use of
110 // original global variables in GVMap with a use of the corresponding copies
111 // in GVMap. The copies need to be bitcast to the original global variable
112 // types, as we cannot use cvta in global variable initializers.
113 for (GVMapTy::iterator I = GVMap.begin(), E = GVMap.end(); I != E;) {
114 GlobalVariable *GV = I->first;
115 GlobalVariable *NewGV = I->second;
116
117 // Remove GV from the map so that it can be RAUWed. Note that
118 // DenseMap::erase() won't invalidate any iterators but this one.
119 auto Next = std::next(I);
120 GVMap.erase(I);
121 I = Next;
122
123 Constant *BitCastNewGV = ConstantExpr::getPointerCast(NewGV, GV->getType());
124 // At this point, the remaining uses of GV should be found only in global
125 // variable initializers, as other uses have been already been removed
126 // while walking through the instructions in function definitions.
127 GV->replaceAllUsesWith(BitCastNewGV);
128 std::string Name = std::string(GV->getName());
129 GV->eraseFromParent();
130 NewGV->setName(Name);
131 }
132 assert(GVMap.empty() && "Expected it to be empty by now");
133
134 return true;
135}
136
137Value *GenericToNVVM::remapConstant(Module *M, Function *F, Constant *C,
138 IRBuilder<> &Builder) {
139 // If the constant C has been converted already in the given function F, just
140 // return the converted value.
141 ConstantToValueMapTy::iterator CTII = ConstantToValueMap.find(C);
142 if (CTII != ConstantToValueMap.end()) {
143 return CTII->second;
144 }
145
146 Value *NewValue = C;
147 if (isa<GlobalVariable>(C)) {
148 // If the constant C is a global variable and is found in GVMap, substitute
149 //
150 // addrspacecast GVMap[C] to addrspace(0)
151 //
152 // for our use of C.
153 GVMapTy::iterator I = GVMap.find(cast<GlobalVariable>(C));
154 if (I != GVMap.end()) {
155 GlobalVariable *GV = I->second;
156 NewValue = Builder.CreateAddrSpaceCast(
157 GV,
158 PointerType::get(GV->getValueType(), llvm::ADDRESS_SPACE_GENERIC));
159 }
160 } else if (isa<ConstantAggregate>(C)) {
161 // If any element in the constant vector or aggregate C is or uses a global
162 // variable in GVMap, the constant C needs to be reconstructed, using a set
163 // of instructions.
164 NewValue = remapConstantVectorOrConstantAggregate(M, F, C, Builder);
165 } else if (isa<ConstantExpr>(C)) {
166 // If any operand in the constant expression C is or uses a global variable
167 // in GVMap, the constant expression C needs to be reconstructed, using a
168 // set of instructions.
169 NewValue = remapConstantExpr(M, F, cast<ConstantExpr>(C), Builder);
170 }
171
172 ConstantToValueMap[C] = NewValue;
173 return NewValue;
174}
175
176Value *GenericToNVVM::remapConstantVectorOrConstantAggregate(
177 Module *M, Function *F, Constant *C, IRBuilder<> &Builder) {
178 bool OperandChanged = false;
179 SmallVector<Value *, 4> NewOperands;
180 unsigned NumOperands = C->getNumOperands();
181
182 // Check if any element is or uses a global variable in GVMap, and thus
183 // converted to another value.
184 for (unsigned i = 0; i < NumOperands; ++i) {
185 Value *Operand = C->getOperand(i);
186 Value *NewOperand = remapConstant(M, F, cast<Constant>(Operand), Builder);
187 OperandChanged |= Operand != NewOperand;
188 NewOperands.push_back(NewOperand);
189 }
190
191 // If none of the elements has been modified, return C as it is.
192 if (!OperandChanged) {
193 return C;
194 }
195
196 // If any of the elements has been modified, construct the equivalent
197 // vector or aggregate value with a set instructions and the converted
198 // elements.
199 Value *NewValue = PoisonValue::get(C->getType());
200 if (isa<ConstantVector>(C)) {
201 for (unsigned i = 0; i < NumOperands; ++i) {
202 Value *Idx = ConstantInt::get(Type::getInt32Ty(M->getContext()), i);
203 NewValue = Builder.CreateInsertElement(NewValue, NewOperands[i], Idx);
204 }
205 } else {
206 for (unsigned i = 0; i < NumOperands; ++i) {
207 NewValue =
208 Builder.CreateInsertValue(NewValue, NewOperands[i], ArrayRef(i));
209 }
210 }
211
212 return NewValue;
213}
214
215Value *GenericToNVVM::remapConstantExpr(Module *M, Function *F, ConstantExpr *C,
216 IRBuilder<> &Builder) {
217 bool OperandChanged = false;
218 SmallVector<Value *, 4> NewOperands;
219 unsigned NumOperands = C->getNumOperands();
220
221 // Check if any operand is or uses a global variable in GVMap, and thus
222 // converted to another value.
223 for (unsigned i = 0; i < NumOperands; ++i) {
224 Value *Operand = C->getOperand(i);
225 Value *NewOperand = remapConstant(M, F, cast<Constant>(Operand), Builder);
226 OperandChanged |= Operand != NewOperand;
227 NewOperands.push_back(NewOperand);
228 }
229
230 // If none of the operands has been modified, return C as it is.
231 if (!OperandChanged) {
232 return C;
233 }
234
235 // If any of the operands has been modified, construct the instruction with
236 // the converted operands.
237 unsigned Opcode = C->getOpcode();
238 switch (Opcode) {
239 case Instruction::ICmp:
240 // CompareConstantExpr (icmp)
241 return Builder.CreateICmp(CmpInst::Predicate(C->getPredicate()),
242 NewOperands[0], NewOperands[1]);
243 case Instruction::FCmp:
244 // CompareConstantExpr (fcmp)
245 llvm_unreachable("Address space conversion should have no effect "
246 "on float point CompareConstantExpr (fcmp)!");
247 case Instruction::ExtractElement:
248 // ExtractElementConstantExpr
249 return Builder.CreateExtractElement(NewOperands[0], NewOperands[1]);
250 case Instruction::InsertElement:
251 // InsertElementConstantExpr
252 return Builder.CreateInsertElement(NewOperands[0], NewOperands[1],
253 NewOperands[2]);
254 case Instruction::ShuffleVector:
255 // ShuffleVector
256 return Builder.CreateShuffleVector(NewOperands[0], NewOperands[1],
257 NewOperands[2]);
258 case Instruction::GetElementPtr:
259 // GetElementPtrConstantExpr
260 return Builder.CreateGEP(cast<GEPOperator>(C)->getSourceElementType(),
261 NewOperands[0],
262 ArrayRef(&NewOperands[1], NumOperands - 1), "",
263 cast<GEPOperator>(C)->isInBounds());
264 case Instruction::Select:
265 // SelectConstantExpr
266 return Builder.CreateSelect(NewOperands[0], NewOperands[1], NewOperands[2]);
267 default:
268 // BinaryConstantExpr
269 if (Instruction::isBinaryOp(Opcode)) {
270 return Builder.CreateBinOp(Instruction::BinaryOps(C->getOpcode()),
271 NewOperands[0], NewOperands[1]);
272 }
273 // UnaryConstantExpr
274 if (Instruction::isCast(Opcode)) {
275 return Builder.CreateCast(Instruction::CastOps(C->getOpcode()),
276 NewOperands[0], C->getType());
277 }
278 llvm_unreachable("GenericToNVVM encountered an unsupported ConstantExpr");
279 }
280}
281
282namespace {
283class GenericToNVVMLegacyPass : public ModulePass {
284public:
285 static char ID;
286
287 GenericToNVVMLegacyPass() : ModulePass(ID) {}
288
289 bool runOnModule(Module &M) override;
290};
291} // namespace
292
293char GenericToNVVMLegacyPass::ID = 0;
294
296 return new GenericToNVVMLegacyPass();
297}
298
300 GenericToNVVMLegacyPass, "generic-to-nvvm",
301 "Ensure that the global variables are in the global address space", false,
302 false)
303
304bool GenericToNVVMLegacyPass::runOnModule(Module &M) {
305 return GenericToNVVM().runOnModule(M);
306}
307
309 return GenericToNVVM().runOnModule(M) ? PreservedAnalyses::none()
311}
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
std::string Name
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
Module.h This file contains the declarations for the Module class.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:348
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
LLVM Basic Block Representation.
Definition: BasicBlock.h:60
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition: InstrTypes.h:960
A constant value that is initialized with an expression using other constant values.
Definition: Constants.h:1017
static Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
Definition: Constants.cpp:2072
This is an important base class in LLVM.
Definition: Constant.h:41
void copyMetadata(const GlobalObject *Src, unsigned Offset)
Copy metadata from Src, adjusting offsets by Offset.
Definition: Metadata.cpp:1756
PointerType * getType() const
Global values are always pointers.
Definition: GlobalValue.h:294
Type * getValueType() const
Definition: GlobalValue.h:296
void copyAttributesFrom(const GlobalVariable *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a GlobalVariable) fro...
Definition: Globals.cpp:482
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
Definition: Globals.cpp:455
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Definition: IRBuilder.h:2450
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
Definition: IRBuilder.h:2501
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Definition: IRBuilder.h:2438
Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
Definition: IRBuilder.cpp:1110
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
Definition: IRBuilder.h:2472
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition: IRBuilder.h:1660
Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:2139
Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", bool IsInBounds=false)
Definition: IRBuilder.h:1860
Value * CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:2329
Value * CreateAddrSpaceCast(Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:2110
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2644
bool isCast() const
Definition: Instruction.h:260
bool isBinaryOp() const
Definition: Instruction.h:257
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:251
virtual bool runOnModule(Module &M)=0
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:37
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Definition: Constants.cpp:1827
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:109
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:115
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
static IntegerType * getInt32Ty(LLVMContext &C)
See the file comment.
Definition: ValueMap.h:84
LLVM Value Representation.
Definition: Value.h:74
void setName(const Twine &Name)
Change the name of the value.
Definition: Value.cpp:377
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:534
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:309
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
ModulePass * createGenericToNVVMLegacyPass()
@ ADDRESS_SPACE_GENERIC
Definition: NVPTXBaseInfo.h:22
@ ADDRESS_SPACE_GLOBAL
Definition: NVPTXBaseInfo.h:23
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition: STLExtras.h:665
void initializeGenericToNVVMLegacyPassPass(PassRegistry &)
bool isSurface(const Value &val)
bool isTexture(const Value &val)
bool isSampler(const Value &val)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)