LLVM 22.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 {
32class GenericToNVVM {
33public:
34 bool runOnModule(Module &M);
35
36private:
37 Value *remapConstant(Module *M, Function *F, Constant *C,
38 IRBuilder<> &Builder);
39 Value *remapConstantVectorOrConstantAggregate(Module *M, Function *F,
40 Constant *C,
41 IRBuilder<> &Builder);
42 Value *remapConstantExpr(Module *M, Function *F, ConstantExpr *C,
43 IRBuilder<> &Builder);
44
45 typedef ValueMap<GlobalVariable *, GlobalVariable *> GVMapTy;
46 typedef ValueMap<Constant *, Value *> ConstantToValueMapTy;
47 GVMapTy GVMap;
48 ConstantToValueMapTy ConstantToValueMap;
49};
50} // end namespace
51
52bool GenericToNVVM::runOnModule(Module &M) {
53 // Create a clone of each global variable that has the default address space.
54 // The clone is created with the global address space specifier, and the pair
55 // of original global variable and its clone is placed in the GVMap for later
56 // use.
57
58 for (GlobalVariable &GV : llvm::make_early_inc_range(M.globals())) {
59 if (GV.getType()->getAddressSpace() == llvm::ADDRESS_SPACE_GENERIC &&
60 !llvm::isTexture(GV) && !llvm::isSurface(GV) && !llvm::isSampler(GV) &&
61 !GV.getName().starts_with("llvm.")) {
62 GlobalVariable *NewGV = new GlobalVariable(
63 M, GV.getValueType(), GV.isConstant(), GV.getLinkage(),
64 GV.hasInitializer() ? GV.getInitializer() : nullptr, "", &GV,
65 GV.getThreadLocalMode(), llvm::ADDRESS_SPACE_GLOBAL);
66 NewGV->copyAttributesFrom(&GV);
67 NewGV->copyMetadata(&GV, /*Offset=*/0);
68 GVMap[&GV] = NewGV;
69 }
70 }
71
72 // Return immediately, if every global variable has a specific address space
73 // specifier.
74 if (GVMap.empty()) {
75 return false;
76 }
77
78 // Walk through the instructions in function defitinions, and replace any use
79 // of original global variables in GVMap with a use of the corresponding
80 // copies in GVMap. If necessary, promote constants to instructions.
81 for (Function &F : M) {
82 if (F.isDeclaration()) {
83 continue;
84 }
85 IRBuilder<> Builder(&*F.getEntryBlock().getFirstNonPHIOrDbg());
86 for (BasicBlock &BB : F) {
87 for (Instruction &II : BB) {
88 for (unsigned i = 0, e = II.getNumOperands(); i < e; ++i) {
89 Value *Operand = II.getOperand(i);
90 if (isa<Constant>(Operand)) {
91 II.setOperand(
92 i, remapConstant(&M, &F, cast<Constant>(Operand), Builder));
93 }
94 }
95 }
96 }
97 ConstantToValueMap.clear();
98 }
99
100 // Copy GVMap over to a standard value map.
102 for (auto I = GVMap.begin(), E = GVMap.end(); I != E; ++I)
103 VM[I->first] = I->second;
104
105 // Walk through the global variable initializers, and replace any use of
106 // original global variables in GVMap with a use of the corresponding copies
107 // in GVMap. The copies need to be bitcast to the original global variable
108 // types, as we cannot use cvta in global variable initializers.
109 for (GVMapTy::iterator I = GVMap.begin(), E = GVMap.end(); I != E;) {
110 GlobalVariable *GV = I->first;
111 GlobalVariable *NewGV = I->second;
112
113 // Remove GV from the map so that it can be RAUWed. Note that
114 // DenseMap::erase() won't invalidate any iterators but this one.
115 auto Next = std::next(I);
116 GVMap.erase(I);
117 I = Next;
118
119 Constant *BitCastNewGV = ConstantExpr::getPointerCast(NewGV, GV->getType());
120 // At this point, the remaining uses of GV should be found only in global
121 // variable initializers, as other uses have been already been removed
122 // while walking through the instructions in function definitions.
123 GV->replaceAllUsesWith(BitCastNewGV);
124 std::string Name = std::string(GV->getName());
125 GV->eraseFromParent();
126 NewGV->setName(Name);
127 }
128 assert(GVMap.empty() && "Expected it to be empty by now");
129
130 return true;
131}
132
133Value *GenericToNVVM::remapConstant(Module *M, Function *F, Constant *C,
134 IRBuilder<> &Builder) {
135 // If the constant C has been converted already in the given function F, just
136 // return the converted value.
137 ConstantToValueMapTy::iterator CTII = ConstantToValueMap.find(C);
138 if (CTII != ConstantToValueMap.end()) {
139 return CTII->second;
140 }
141
142 Value *NewValue = C;
143 if (isa<GlobalVariable>(C)) {
144 // If the constant C is a global variable and is found in GVMap, substitute
145 //
146 // addrspacecast GVMap[C] to addrspace(0)
147 //
148 // for our use of C.
149 GVMapTy::iterator I = GVMap.find(cast<GlobalVariable>(C));
150 if (I != GVMap.end()) {
151 GlobalVariable *GV = I->second;
152 NewValue = Builder.CreateAddrSpaceCast(
153 GV, PointerType::get(GV->getContext(), llvm::ADDRESS_SPACE_GENERIC));
154 }
155 } else if (isa<ConstantAggregate>(C)) {
156 // If any element in the constant vector or aggregate C is or uses a global
157 // variable in GVMap, the constant C needs to be reconstructed, using a set
158 // of instructions.
159 NewValue = remapConstantVectorOrConstantAggregate(M, F, C, Builder);
160 } else if (isa<ConstantExpr>(C)) {
161 // If any operand in the constant expression C is or uses a global variable
162 // in GVMap, the constant expression C needs to be reconstructed, using a
163 // set of instructions.
164 NewValue = remapConstantExpr(M, F, cast<ConstantExpr>(C), Builder);
165 }
166
167 ConstantToValueMap[C] = NewValue;
168 return NewValue;
169}
170
171Value *GenericToNVVM::remapConstantVectorOrConstantAggregate(
172 Module *M, Function *F, Constant *C, IRBuilder<> &Builder) {
173 bool OperandChanged = false;
174 SmallVector<Value *, 4> NewOperands;
175 unsigned NumOperands = C->getNumOperands();
176
177 // Check if any element is or uses a global variable in GVMap, and thus
178 // converted to another value.
179 for (unsigned i = 0; i < NumOperands; ++i) {
180 Value *Operand = C->getOperand(i);
181 Value *NewOperand = remapConstant(M, F, cast<Constant>(Operand), Builder);
182 OperandChanged |= Operand != NewOperand;
183 NewOperands.push_back(NewOperand);
184 }
185
186 // If none of the elements has been modified, return C as it is.
187 if (!OperandChanged) {
188 return C;
189 }
190
191 // If any of the elements has been modified, construct the equivalent
192 // vector or aggregate value with a set instructions and the converted
193 // elements.
194 Value *NewValue = PoisonValue::get(C->getType());
195 if (isa<ConstantVector>(C)) {
196 for (unsigned i = 0; i < NumOperands; ++i) {
197 Value *Idx = ConstantInt::get(Type::getInt32Ty(M->getContext()), i);
198 NewValue = Builder.CreateInsertElement(NewValue, NewOperands[i], Idx);
199 }
200 } else {
201 for (unsigned i = 0; i < NumOperands; ++i) {
202 NewValue =
203 Builder.CreateInsertValue(NewValue, NewOperands[i], ArrayRef(i));
204 }
205 }
206
207 return NewValue;
208}
209
210Value *GenericToNVVM::remapConstantExpr(Module *M, Function *F, ConstantExpr *C,
211 IRBuilder<> &Builder) {
212 bool OperandChanged = false;
213 SmallVector<Value *, 4> NewOperands;
214 unsigned NumOperands = C->getNumOperands();
215
216 // Check if any operand is or uses a global variable in GVMap, and thus
217 // converted to another value.
218 for (unsigned i = 0; i < NumOperands; ++i) {
219 Value *Operand = C->getOperand(i);
220 Value *NewOperand = remapConstant(M, F, cast<Constant>(Operand), Builder);
221 OperandChanged |= Operand != NewOperand;
222 NewOperands.push_back(NewOperand);
223 }
224
225 // If none of the operands has been modified, return C as it is.
226 if (!OperandChanged) {
227 return C;
228 }
229
230 // If any of the operands has been modified, construct the instruction with
231 // the converted operands.
232 unsigned Opcode = C->getOpcode();
233 switch (Opcode) {
234 case Instruction::ExtractElement:
235 // ExtractElementConstantExpr
236 return Builder.CreateExtractElement(NewOperands[0], NewOperands[1]);
237 case Instruction::InsertElement:
238 // InsertElementConstantExpr
239 return Builder.CreateInsertElement(NewOperands[0], NewOperands[1],
240 NewOperands[2]);
241 case Instruction::ShuffleVector:
242 // ShuffleVector
243 return Builder.CreateShuffleVector(NewOperands[0], NewOperands[1],
244 NewOperands[2]);
245 case Instruction::GetElementPtr:
246 // GetElementPtrConstantExpr
247 return Builder.CreateGEP(cast<GEPOperator>(C)->getSourceElementType(),
248 NewOperands[0],
249 ArrayRef(&NewOperands[1], NumOperands - 1), "",
250 cast<GEPOperator>(C)->isInBounds());
251 case Instruction::Select:
252 // SelectConstantExpr
253 return Builder.CreateSelect(NewOperands[0], NewOperands[1], NewOperands[2]);
254 default:
255 // BinaryConstantExpr
256 if (Instruction::isBinaryOp(Opcode)) {
257 return Builder.CreateBinOp(Instruction::BinaryOps(C->getOpcode()),
258 NewOperands[0], NewOperands[1]);
259 }
260 // UnaryConstantExpr
261 if (Instruction::isCast(Opcode)) {
262 return Builder.CreateCast(Instruction::CastOps(C->getOpcode()),
263 NewOperands[0], C->getType());
264 }
265 llvm_unreachable("GenericToNVVM encountered an unsupported ConstantExpr");
266 }
267}
268
269namespace {
270class GenericToNVVMLegacyPass : public ModulePass {
271public:
272 static char ID;
273
274 GenericToNVVMLegacyPass() : ModulePass(ID) {}
275
276 bool runOnModule(Module &M) override;
277};
278} // namespace
279
280char GenericToNVVMLegacyPass::ID = 0;
281
283 return new GenericToNVVMLegacyPass();
284}
285
287 GenericToNVVMLegacyPass, "generic-to-nvvm",
288 "Ensure that the global variables are in the global address space", false,
289 false)
290
291bool GenericToNVVMLegacyPass::runOnModule(Module &M) {
292 return GenericToNVVM().runOnModule(M);
293}
294
296 return GenericToNVVM().runOnModule(M) ? PreservedAnalyses::none()
298}
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
Machine Check Debug Module
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static LLVM_ABI Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
LLVM_ABI void copyMetadata(const GlobalObject *Src, unsigned Offset)
Copy metadata from Src, adjusting offsets by Offset.
PointerType * getType() const
Global values are always pointers.
LLVM_ABI void copyAttributesFrom(const GlobalVariable *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a GlobalVariable) fro...
Definition Globals.cpp:553
LLVM_ABI void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
Definition Globals.cpp:520
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Definition IRBuilder.h:2579
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
Definition IRBuilder.h:2633
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Definition IRBuilder.h:2567
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr, FMFSource FMFSource={})
Definition IRBuilder.h:2241
Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Definition IRBuilder.h:1926
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
Definition IRBuilder.h:2601
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:1708
Value * CreateAddrSpaceCast(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2212
bool isCast() const
bool isBinaryOp() const
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:255
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
void push_back(const T &Elt)
bool empty() const
Definition ValueMap.h:143
iterator find(const KeyT &Val)
Definition ValueMap.h:160
iterator begin()
Definition ValueMap.h:138
iterator end()
Definition ValueMap.h:139
bool erase(const KeyT &Val)
Definition ValueMap.h:192
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
Definition Value.cpp:390
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:546
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.cpp:1099
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:322
#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.
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
ModulePass * createGenericToNVVMLegacyPass()
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:632
bool isSampler(const Value &V)
bool isSurface(const Value &V)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
FunctionAddr VTableAddr Next
Definition InstrProf.h:141
ArrayRef(const T &OneElt) -> ArrayRef< T >
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
bool isTexture(const Value &V)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)