LLVM  14.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"
19 #include "llvm/IR/DerivedTypes.h"
20 #include "llvm/IR/IRBuilder.h"
21 #include "llvm/IR/Instructions.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 
29 using namespace llvm;
30 
31 namespace llvm {
33 }
34 
35 namespace {
36 class GenericToNVVM : public ModulePass {
37 public:
38  static char ID;
39 
40  GenericToNVVM() : ModulePass(ID) {}
41 
42  bool runOnModule(Module &M) override;
43 
44  void getAnalysisUsage(AnalysisUsage &AU) const override {}
45 
46 private:
47  Value *remapConstant(Module *M, Function *F, Constant *C,
49  Value *remapConstantVectorOrConstantAggregate(Module *M, Function *F,
50  Constant *C,
52  Value *remapConstantExpr(Module *M, Function *F, ConstantExpr *C,
54 
56  typedef ValueMap<Constant *, Value *> ConstantToValueMapTy;
57  GVMapTy GVMap;
58  ConstantToValueMapTy ConstantToValueMap;
59 };
60 } // end namespace
61 
62 char GenericToNVVM::ID = 0;
63 
64 ModulePass *llvm::createGenericToNVVMPass() { return new GenericToNVVM(); }
65 
67  GenericToNVVM, "generic-to-nvvm",
68  "Ensure that the global variables are in the global address space", false,
69  false)
70 
71 bool GenericToNVVM::runOnModule(Module &M) {
72  // Create a clone of each global variable that has the default address space.
73  // The clone is created with the global address space specifier, and the pair
74  // of original global variable and its clone is placed in the GVMap for later
75  // use.
76 
77  for (GlobalVariable &GV : llvm::make_early_inc_range(M.globals())) {
78  if (GV.getType()->getAddressSpace() == llvm::ADDRESS_SPACE_GENERIC &&
79  !llvm::isTexture(GV) && !llvm::isSurface(GV) && !llvm::isSampler(GV) &&
80  !GV.getName().startswith("llvm.")) {
81  GlobalVariable *NewGV = new GlobalVariable(
82  M, GV.getValueType(), GV.isConstant(), GV.getLinkage(),
83  GV.hasInitializer() ? GV.getInitializer() : nullptr, "", &GV,
84  GV.getThreadLocalMode(), llvm::ADDRESS_SPACE_GLOBAL);
85  NewGV->copyAttributesFrom(&GV);
86  GVMap[&GV] = NewGV;
87  }
88  }
89 
90  // Return immediately, if every global variable has a specific address space
91  // specifier.
92  if (GVMap.empty()) {
93  return false;
94  }
95 
96  // Walk through the instructions in function defitinions, and replace any use
97  // of original global variables in GVMap with a use of the corresponding
98  // copies in GVMap. If necessary, promote constants to instructions.
99  for (Function &F : M) {
100  if (F.isDeclaration()) {
101  continue;
102  }
103  IRBuilder<> Builder(F.getEntryBlock().getFirstNonPHIOrDbg());
104  for (BasicBlock &BB : F) {
105  for (Instruction &II : BB) {
106  for (unsigned i = 0, e = II.getNumOperands(); i < e; ++i) {
107  Value *Operand = II.getOperand(i);
108  if (isa<Constant>(Operand)) {
109  II.setOperand(
110  i, remapConstant(&M, &F, cast<Constant>(Operand), Builder));
111  }
112  }
113  }
114  }
115  ConstantToValueMap.clear();
116  }
117 
118  // Copy GVMap over to a standard value map.
120  for (auto I = GVMap.begin(), E = GVMap.end(); I != E; ++I)
121  VM[I->first] = I->second;
122 
123  // Walk through the global variable initializers, and replace any use of
124  // original global variables in GVMap with a use of the corresponding copies
125  // in GVMap. The copies need to be bitcast to the original global variable
126  // types, as we cannot use cvta in global variable initializers.
127  for (GVMapTy::iterator I = GVMap.begin(), E = GVMap.end(); I != E;) {
128  GlobalVariable *GV = I->first;
129  GlobalVariable *NewGV = I->second;
130 
131  // Remove GV from the map so that it can be RAUWed. Note that
132  // DenseMap::erase() won't invalidate any iterators but this one.
133  auto Next = std::next(I);
134  GVMap.erase(I);
135  I = Next;
136 
137  Constant *BitCastNewGV = ConstantExpr::getPointerCast(NewGV, GV->getType());
138  // At this point, the remaining uses of GV should be found only in global
139  // variable initializers, as other uses have been already been removed
140  // while walking through the instructions in function definitions.
141  GV->replaceAllUsesWith(BitCastNewGV);
142  std::string Name = std::string(GV->getName());
143  GV->eraseFromParent();
144  NewGV->setName(Name);
145  }
146  assert(GVMap.empty() && "Expected it to be empty by now");
147 
148  return true;
149 }
150 
151 Value *GenericToNVVM::remapConstant(Module *M, Function *F, Constant *C,
152  IRBuilder<> &Builder) {
153  // If the constant C has been converted already in the given function F, just
154  // return the converted value.
155  ConstantToValueMapTy::iterator CTII = ConstantToValueMap.find(C);
156  if (CTII != ConstantToValueMap.end()) {
157  return CTII->second;
158  }
159 
160  Value *NewValue = C;
161  if (isa<GlobalVariable>(C)) {
162  // If the constant C is a global variable and is found in GVMap, substitute
163  //
164  // addrspacecast GVMap[C] to addrspace(0)
165  //
166  // for our use of C.
167  GVMapTy::iterator I = GVMap.find(cast<GlobalVariable>(C));
168  if (I != GVMap.end()) {
169  GlobalVariable *GV = I->second;
170  NewValue = Builder.CreateAddrSpaceCast(
171  GV,
173  }
174  } else if (isa<ConstantAggregate>(C)) {
175  // If any element in the constant vector or aggregate C is or uses a global
176  // variable in GVMap, the constant C needs to be reconstructed, using a set
177  // of instructions.
178  NewValue = remapConstantVectorOrConstantAggregate(M, F, C, Builder);
179  } else if (isa<ConstantExpr>(C)) {
180  // If any operand in the constant expression C is or uses a global variable
181  // in GVMap, the constant expression C needs to be reconstructed, using a
182  // set of instructions.
183  NewValue = remapConstantExpr(M, F, cast<ConstantExpr>(C), Builder);
184  }
185 
186  ConstantToValueMap[C] = NewValue;
187  return NewValue;
188 }
189 
190 Value *GenericToNVVM::remapConstantVectorOrConstantAggregate(
192  bool OperandChanged = false;
193  SmallVector<Value *, 4> NewOperands;
194  unsigned NumOperands = C->getNumOperands();
195 
196  // Check if any element is or uses a global variable in GVMap, and thus
197  // converted to another value.
198  for (unsigned i = 0; i < NumOperands; ++i) {
199  Value *Operand = C->getOperand(i);
200  Value *NewOperand = remapConstant(M, F, cast<Constant>(Operand), Builder);
201  OperandChanged |= Operand != NewOperand;
202  NewOperands.push_back(NewOperand);
203  }
204 
205  // If none of the elements has been modified, return C as it is.
206  if (!OperandChanged) {
207  return C;
208  }
209 
210  // If any of the elements has been modified, construct the equivalent
211  // vector or aggregate value with a set instructions and the converted
212  // elements.
213  Value *NewValue = PoisonValue::get(C->getType());
214  if (isa<ConstantVector>(C)) {
215  for (unsigned i = 0; i < NumOperands; ++i) {
216  Value *Idx = ConstantInt::get(Type::getInt32Ty(M->getContext()), i);
217  NewValue = Builder.CreateInsertElement(NewValue, NewOperands[i], Idx);
218  }
219  } else {
220  for (unsigned i = 0; i < NumOperands; ++i) {
221  NewValue =
222  Builder.CreateInsertValue(NewValue, NewOperands[i], makeArrayRef(i));
223  }
224  }
225 
226  return NewValue;
227 }
228 
229 Value *GenericToNVVM::remapConstantExpr(Module *M, Function *F, ConstantExpr *C,
230  IRBuilder<> &Builder) {
231  bool OperandChanged = false;
232  SmallVector<Value *, 4> NewOperands;
233  unsigned NumOperands = C->getNumOperands();
234 
235  // Check if any operand is or uses a global variable in GVMap, and thus
236  // converted to another value.
237  for (unsigned i = 0; i < NumOperands; ++i) {
238  Value *Operand = C->getOperand(i);
239  Value *NewOperand = remapConstant(M, F, cast<Constant>(Operand), Builder);
240  OperandChanged |= Operand != NewOperand;
241  NewOperands.push_back(NewOperand);
242  }
243 
244  // If none of the operands has been modified, return C as it is.
245  if (!OperandChanged) {
246  return C;
247  }
248 
249  // If any of the operands has been modified, construct the instruction with
250  // the converted operands.
251  unsigned Opcode = C->getOpcode();
252  switch (Opcode) {
253  case Instruction::ICmp:
254  // CompareConstantExpr (icmp)
255  return Builder.CreateICmp(CmpInst::Predicate(C->getPredicate()),
256  NewOperands[0], NewOperands[1]);
257  case Instruction::FCmp:
258  // CompareConstantExpr (fcmp)
259  llvm_unreachable("Address space conversion should have no effect "
260  "on float point CompareConstantExpr (fcmp)!");
261  case Instruction::ExtractElement:
262  // ExtractElementConstantExpr
263  return Builder.CreateExtractElement(NewOperands[0], NewOperands[1]);
264  case Instruction::InsertElement:
265  // InsertElementConstantExpr
266  return Builder.CreateInsertElement(NewOperands[0], NewOperands[1],
267  NewOperands[2]);
268  case Instruction::ShuffleVector:
269  // ShuffleVector
270  return Builder.CreateShuffleVector(NewOperands[0], NewOperands[1],
271  NewOperands[2]);
272  case Instruction::ExtractValue:
273  // ExtractValueConstantExpr
274  return Builder.CreateExtractValue(NewOperands[0], C->getIndices());
275  case Instruction::InsertValue:
276  // InsertValueConstantExpr
277  return Builder.CreateInsertValue(NewOperands[0], NewOperands[1],
278  C->getIndices());
279  case Instruction::GetElementPtr:
280  // GetElementPtrConstantExpr
281  return cast<GEPOperator>(C)->isInBounds()
282  ? Builder.CreateGEP(
283  cast<GEPOperator>(C)->getSourceElementType(),
284  NewOperands[0],
285  makeArrayRef(&NewOperands[1], NumOperands - 1))
286  : Builder.CreateInBoundsGEP(
287  cast<GEPOperator>(C)->getSourceElementType(),
288  NewOperands[0],
289  makeArrayRef(&NewOperands[1], NumOperands - 1));
290  case Instruction::Select:
291  // SelectConstantExpr
292  return Builder.CreateSelect(NewOperands[0], NewOperands[1], NewOperands[2]);
293  default:
294  // BinaryConstantExpr
295  if (Instruction::isBinaryOp(Opcode)) {
296  return Builder.CreateBinOp(Instruction::BinaryOps(C->getOpcode()),
297  NewOperands[0], NewOperands[1]);
298  }
299  // UnaryConstantExpr
300  if (Instruction::isCast(Opcode)) {
301  return Builder.CreateCast(Instruction::CastOps(C->getOpcode()),
302  NewOperands[0], C->getType());
303  }
304  llvm_unreachable("GenericToNVVM encountered an unsupported ConstantExpr");
305  }
306 }
i
i
Definition: README.txt:29
ValueTypes.h
llvm::GlobalVariable::eraseFromParent
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
Definition: Globals.cpp:430
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
ValueMapper.h
llvm::CmpInst::Predicate
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition: InstrTypes.h:721
llvm::ModulePass
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:238
llvm::GlobalVariable::copyAttributesFrom
void copyAttributesFrom(const GlobalVariable *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a GlobalVariable) fro...
Definition: Globals.cpp:457
llvm::Function
Definition: Function.h:62
llvm::Instruction::isCast
bool isCast() const
Definition: Instruction.h:168
llvm::PointerType::get
static PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
Definition: Type.cpp:729
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1177
llvm::IRBuilder<>
llvm::GlobalVariable
Definition: GlobalVariable.h:39
Module.h
Operator.h
LegacyPassManager.h
llvm::Type::getInt32Ty
static IntegerType * getInt32Ty(LLVMContext &C)
Definition: Type.cpp:241
llvm::isTexture
bool isTexture(const Value &val)
Definition: NVPTXUtilities.cpp:133
F
#define F(x, y, z)
Definition: MD5.cpp:55
NVPTX.h
llvm::ConstantExpr::getPointerCast
static Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
Definition: Constants.cpp:2094
llvm::isSampler
bool isSampler(const Value &val)
Definition: NVPTXUtilities.cpp:155
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
NVPTXUtilities.h
Constants.h
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::ADDRESS_SPACE_GLOBAL
@ ADDRESS_SPACE_GLOBAL
Definition: NVPTXBaseInfo.h:23
Intrinsics.h
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
llvm::Instruction::CastOps
CastOps
Definition: Instruction.h:803
llvm::Instruction
Definition: Instruction.h:45
llvm::PassRegistry
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:38
llvm::Value::setName
void setName(const Twine &Name)
Change the name of the value.
Definition: Value.cpp:376
llvm::ConstantInt::get
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Definition: Constants.cpp:932
llvm::Constant
This is an important base class in LLVM.
Definition: Constant.h:41
llvm::numbers::e
constexpr double e
Definition: MathExtras.h:57
NVPTXBaseInfo.h
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::make_early_inc_range
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:642
IRBuilder.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::Instruction::isBinaryOp
bool isBinaryOp() const
Definition: Instruction.h:165
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
Builder
assume Assume Builder
Definition: AssumeBundleBuilder.cpp:650
INITIALIZE_PASS
INITIALIZE_PASS(GenericToNVVM, "generic-to-nvvm", "Ensure that the global variables are in the global address space", false, false) bool GenericToNVVM
Definition: NVPTXGenericToNVVM.cpp:66
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:134
llvm::Value::replaceAllUsesWith
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:532
llvm::ADDRESS_SPACE_GENERIC
@ ADDRESS_SPACE_GENERIC
Definition: NVPTXBaseInfo.h:22
llvm::Value::getName
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:309
llvm::ValueMap
See the file comment.
Definition: ValueMap.h:85
ValueMap.h
llvm::initializeGenericToNVVMPass
void initializeGenericToNVVMPass(PassRegistry &)
llvm::MCID::Select
@ Select
Definition: MCInstrDesc.h:162
llvm::ConstantExpr
A constant value that is initialized with an expression using other constant values.
Definition: Constants.h:971
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
llvm::isSurface
bool isSurface(const Value &val)
Definition: NVPTXUtilities.cpp:144
llvm::makeArrayRef
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
Definition: ArrayRef.h:474
llvm::Instruction::BinaryOps
BinaryOps
Definition: Instruction.h:789
Instructions.h
llvm::createGenericToNVVMPass
ModulePass * createGenericToNVVMPass()
Definition: NVPTXGenericToNVVM.cpp:64
llvm::GlobalValue::getType
PointerType * getType() const
Global values are always pointers.
Definition: GlobalValue.h:271
DerivedTypes.h
llvm::GlobalValue::getValueType
Type * getValueType() const
Definition: GlobalValue.h:273
BB
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
Definition: README.txt:39
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38
llvm::PoisonValue::get
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Definition: Constants.cpp:1823