LLVM  15.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  NewGV->copyMetadata(&GV, /*Offset=*/0);
87  GVMap[&GV] = NewGV;
88  }
89  }
90 
91  // Return immediately, if every global variable has a specific address space
92  // specifier.
93  if (GVMap.empty()) {
94  return false;
95  }
96 
97  // Walk through the instructions in function defitinions, and replace any use
98  // of original global variables in GVMap with a use of the corresponding
99  // copies in GVMap. If necessary, promote constants to instructions.
100  for (Function &F : M) {
101  if (F.isDeclaration()) {
102  continue;
103  }
104  IRBuilder<> Builder(F.getEntryBlock().getFirstNonPHIOrDbg());
105  for (BasicBlock &BB : F) {
106  for (Instruction &II : BB) {
107  for (unsigned i = 0, e = II.getNumOperands(); i < e; ++i) {
108  Value *Operand = II.getOperand(i);
109  if (isa<Constant>(Operand)) {
110  II.setOperand(
111  i, remapConstant(&M, &F, cast<Constant>(Operand), Builder));
112  }
113  }
114  }
115  }
116  ConstantToValueMap.clear();
117  }
118 
119  // Copy GVMap over to a standard value map.
121  for (auto I = GVMap.begin(), E = GVMap.end(); I != E; ++I)
122  VM[I->first] = I->second;
123 
124  // Walk through the global variable initializers, and replace any use of
125  // original global variables in GVMap with a use of the corresponding copies
126  // in GVMap. The copies need to be bitcast to the original global variable
127  // types, as we cannot use cvta in global variable initializers.
128  for (GVMapTy::iterator I = GVMap.begin(), E = GVMap.end(); I != E;) {
129  GlobalVariable *GV = I->first;
130  GlobalVariable *NewGV = I->second;
131 
132  // Remove GV from the map so that it can be RAUWed. Note that
133  // DenseMap::erase() won't invalidate any iterators but this one.
134  auto Next = std::next(I);
135  GVMap.erase(I);
136  I = Next;
137 
138  Constant *BitCastNewGV = ConstantExpr::getPointerCast(NewGV, GV->getType());
139  // At this point, the remaining uses of GV should be found only in global
140  // variable initializers, as other uses have been already been removed
141  // while walking through the instructions in function definitions.
142  GV->replaceAllUsesWith(BitCastNewGV);
143  std::string Name = std::string(GV->getName());
144  GV->eraseFromParent();
145  NewGV->setName(Name);
146  }
147  assert(GVMap.empty() && "Expected it to be empty by now");
148 
149  return true;
150 }
151 
152 Value *GenericToNVVM::remapConstant(Module *M, Function *F, Constant *C,
153  IRBuilder<> &Builder) {
154  // If the constant C has been converted already in the given function F, just
155  // return the converted value.
156  ConstantToValueMapTy::iterator CTII = ConstantToValueMap.find(C);
157  if (CTII != ConstantToValueMap.end()) {
158  return CTII->second;
159  }
160 
161  Value *NewValue = C;
162  if (isa<GlobalVariable>(C)) {
163  // If the constant C is a global variable and is found in GVMap, substitute
164  //
165  // addrspacecast GVMap[C] to addrspace(0)
166  //
167  // for our use of C.
168  GVMapTy::iterator I = GVMap.find(cast<GlobalVariable>(C));
169  if (I != GVMap.end()) {
170  GlobalVariable *GV = I->second;
171  NewValue = Builder.CreateAddrSpaceCast(
172  GV,
174  }
175  } else if (isa<ConstantAggregate>(C)) {
176  // If any element in the constant vector or aggregate C is or uses a global
177  // variable in GVMap, the constant C needs to be reconstructed, using a set
178  // of instructions.
179  NewValue = remapConstantVectorOrConstantAggregate(M, F, C, Builder);
180  } else if (isa<ConstantExpr>(C)) {
181  // If any operand in the constant expression C is or uses a global variable
182  // in GVMap, the constant expression C needs to be reconstructed, using a
183  // set of instructions.
184  NewValue = remapConstantExpr(M, F, cast<ConstantExpr>(C), Builder);
185  }
186 
187  ConstantToValueMap[C] = NewValue;
188  return NewValue;
189 }
190 
191 Value *GenericToNVVM::remapConstantVectorOrConstantAggregate(
193  bool OperandChanged = false;
194  SmallVector<Value *, 4> NewOperands;
195  unsigned NumOperands = C->getNumOperands();
196 
197  // Check if any element is or uses a global variable in GVMap, and thus
198  // converted to another value.
199  for (unsigned i = 0; i < NumOperands; ++i) {
200  Value *Operand = C->getOperand(i);
201  Value *NewOperand = remapConstant(M, F, cast<Constant>(Operand), Builder);
202  OperandChanged |= Operand != NewOperand;
203  NewOperands.push_back(NewOperand);
204  }
205 
206  // If none of the elements has been modified, return C as it is.
207  if (!OperandChanged) {
208  return C;
209  }
210 
211  // If any of the elements has been modified, construct the equivalent
212  // vector or aggregate value with a set instructions and the converted
213  // elements.
214  Value *NewValue = PoisonValue::get(C->getType());
215  if (isa<ConstantVector>(C)) {
216  for (unsigned i = 0; i < NumOperands; ++i) {
217  Value *Idx = ConstantInt::get(Type::getInt32Ty(M->getContext()), i);
218  NewValue = Builder.CreateInsertElement(NewValue, NewOperands[i], Idx);
219  }
220  } else {
221  for (unsigned i = 0; i < NumOperands; ++i) {
222  NewValue =
223  Builder.CreateInsertValue(NewValue, NewOperands[i], makeArrayRef(i));
224  }
225  }
226 
227  return NewValue;
228 }
229 
230 Value *GenericToNVVM::remapConstantExpr(Module *M, Function *F, ConstantExpr *C,
231  IRBuilder<> &Builder) {
232  bool OperandChanged = false;
233  SmallVector<Value *, 4> NewOperands;
234  unsigned NumOperands = C->getNumOperands();
235 
236  // Check if any operand is or uses a global variable in GVMap, and thus
237  // converted to another value.
238  for (unsigned i = 0; i < NumOperands; ++i) {
239  Value *Operand = C->getOperand(i);
240  Value *NewOperand = remapConstant(M, F, cast<Constant>(Operand), Builder);
241  OperandChanged |= Operand != NewOperand;
242  NewOperands.push_back(NewOperand);
243  }
244 
245  // If none of the operands has been modified, return C as it is.
246  if (!OperandChanged) {
247  return C;
248  }
249 
250  // If any of the operands has been modified, construct the instruction with
251  // the converted operands.
252  unsigned Opcode = C->getOpcode();
253  switch (Opcode) {
254  case Instruction::ICmp:
255  // CompareConstantExpr (icmp)
256  return Builder.CreateICmp(CmpInst::Predicate(C->getPredicate()),
257  NewOperands[0], NewOperands[1]);
258  case Instruction::FCmp:
259  // CompareConstantExpr (fcmp)
260  llvm_unreachable("Address space conversion should have no effect "
261  "on float point CompareConstantExpr (fcmp)!");
262  case Instruction::ExtractElement:
263  // ExtractElementConstantExpr
264  return Builder.CreateExtractElement(NewOperands[0], NewOperands[1]);
265  case Instruction::InsertElement:
266  // InsertElementConstantExpr
267  return Builder.CreateInsertElement(NewOperands[0], NewOperands[1],
268  NewOperands[2]);
269  case Instruction::ShuffleVector:
270  // ShuffleVector
271  return Builder.CreateShuffleVector(NewOperands[0], NewOperands[1],
272  NewOperands[2]);
273  case Instruction::GetElementPtr:
274  // GetElementPtrConstantExpr
275  return Builder.CreateGEP(cast<GEPOperator>(C)->getSourceElementType(),
276  NewOperands[0],
277  makeArrayRef(&NewOperands[1], NumOperands - 1), "",
278  cast<GEPOperator>(C)->isInBounds());
279  case Instruction::Select:
280  // SelectConstantExpr
281  return Builder.CreateSelect(NewOperands[0], NewOperands[1], NewOperands[2]);
282  default:
283  // BinaryConstantExpr
284  if (Instruction::isBinaryOp(Opcode)) {
285  return Builder.CreateBinOp(Instruction::BinaryOps(C->getOpcode()),
286  NewOperands[0], NewOperands[1]);
287  }
288  // UnaryConstantExpr
289  if (Instruction::isCast(Opcode)) {
290  return Builder.CreateCast(Instruction::CastOps(C->getOpcode()),
291  NewOperands[0], C->getType());
292  }
293  llvm_unreachable("GenericToNVVM encountered an unsupported ConstantExpr");
294  }
295 }
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:451
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
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:719
llvm::ModulePass
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:248
llvm::GlobalVariable::copyAttributesFrom
void copyAttributesFrom(const GlobalVariable *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a GlobalVariable) fro...
Definition: Globals.cpp:478
llvm::Function
Definition: Function.h:60
llvm::Instruction::isCast
bool isCast() const
Definition: Instruction.h:165
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:727
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1185
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:239
llvm::isTexture
bool isTexture(const Value &val)
Definition: NVPTXUtilities.cpp:143
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:2011
llvm::isSampler
bool isSampler(const Value &val)
Definition: NVPTXUtilities.cpp:165
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:55
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:785
llvm::Instruction
Definition: Instruction.h:42
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:372
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:879
llvm::CallingConv::ID
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
llvm::Constant
This is an important base class in LLVM.
Definition: Constant.h:41
llvm::GlobalObject::copyMetadata
void copyMetadata(const GlobalObject *Src, unsigned Offset)
Copy metadata from Src, adjusting offsets by Offset.
Definition: Metadata.cpp:1557
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:618
IRBuilder.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::Instruction::isBinaryOp
bool isBinaryOp() const
Definition: Instruction.h:162
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:651
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:143
llvm::Value::replaceAllUsesWith
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:529
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:305
llvm::ValueMap
See the file comment.
Definition: ValueMap.h:85
ValueMap.h
llvm::initializeGenericToNVVMPass
void initializeGenericToNVVMPass(PassRegistry &)
llvm::MCID::Select
@ Select
Definition: MCInstrDesc.h:164
llvm::ConstantExpr
A constant value that is initialized with an expression using other constant values.
Definition: Constants.h:972
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:50
llvm::isSurface
bool isSurface(const Value &val)
Definition: NVPTXUtilities.cpp:154
llvm::makeArrayRef
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
Definition: ArrayRef.h:475
llvm::Instruction::BinaryOps
BinaryOps
Definition: Instruction.h:771
Instructions.h
llvm::createGenericToNVVMPass
ModulePass * createGenericToNVVMPass()
Definition: NVPTXGenericToNVVM.cpp:64
llvm::GlobalValue::getType
PointerType * getType() const
Global values are always pointers.
Definition: GlobalValue.h:276
DerivedTypes.h
llvm::GlobalValue::getValueType
Type * getValueType() const
Definition: GlobalValue.h:278
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:1729