1*9880d681SAndroid Build Coastguard Worker //===-- GenericToNVVM.cpp - Convert generic module to NVVM module - C++ -*-===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // Convert generic global variables into either .global or .const access based
11*9880d681SAndroid Build Coastguard Worker // on the variable's "constant" qualifier.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker
15*9880d681SAndroid Build Coastguard Worker #include "NVPTX.h"
16*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/NVPTXBaseInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "NVPTXUtilities.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionAnalysis.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/ValueTypes.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constants.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DerivedTypes.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IRBuilder.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instructions.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Intrinsics.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/LegacyPassManager.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Operator.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/ValueMap.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/ValueMapper.h"
30*9880d681SAndroid Build Coastguard Worker
31*9880d681SAndroid Build Coastguard Worker using namespace llvm;
32*9880d681SAndroid Build Coastguard Worker
33*9880d681SAndroid Build Coastguard Worker namespace llvm {
34*9880d681SAndroid Build Coastguard Worker void initializeGenericToNVVMPass(PassRegistry &);
35*9880d681SAndroid Build Coastguard Worker }
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Worker namespace {
38*9880d681SAndroid Build Coastguard Worker class GenericToNVVM : public ModulePass {
39*9880d681SAndroid Build Coastguard Worker public:
40*9880d681SAndroid Build Coastguard Worker static char ID;
41*9880d681SAndroid Build Coastguard Worker
GenericToNVVM()42*9880d681SAndroid Build Coastguard Worker GenericToNVVM() : ModulePass(ID) {}
43*9880d681SAndroid Build Coastguard Worker
44*9880d681SAndroid Build Coastguard Worker bool runOnModule(Module &M) override;
45*9880d681SAndroid Build Coastguard Worker
getAnalysisUsage(AnalysisUsage & AU) const46*9880d681SAndroid Build Coastguard Worker void getAnalysisUsage(AnalysisUsage &AU) const override {}
47*9880d681SAndroid Build Coastguard Worker
48*9880d681SAndroid Build Coastguard Worker private:
49*9880d681SAndroid Build Coastguard Worker Value *getOrInsertCVTA(Module *M, Function *F, GlobalVariable *GV,
50*9880d681SAndroid Build Coastguard Worker IRBuilder<> &Builder);
51*9880d681SAndroid Build Coastguard Worker Value *remapConstant(Module *M, Function *F, Constant *C,
52*9880d681SAndroid Build Coastguard Worker IRBuilder<> &Builder);
53*9880d681SAndroid Build Coastguard Worker Value *remapConstantVectorOrConstantAggregate(Module *M, Function *F,
54*9880d681SAndroid Build Coastguard Worker Constant *C,
55*9880d681SAndroid Build Coastguard Worker IRBuilder<> &Builder);
56*9880d681SAndroid Build Coastguard Worker Value *remapConstantExpr(Module *M, Function *F, ConstantExpr *C,
57*9880d681SAndroid Build Coastguard Worker IRBuilder<> &Builder);
58*9880d681SAndroid Build Coastguard Worker void remapNamedMDNode(ValueToValueMapTy &VM, NamedMDNode *N);
59*9880d681SAndroid Build Coastguard Worker
60*9880d681SAndroid Build Coastguard Worker typedef ValueMap<GlobalVariable *, GlobalVariable *> GVMapTy;
61*9880d681SAndroid Build Coastguard Worker typedef ValueMap<Constant *, Value *> ConstantToValueMapTy;
62*9880d681SAndroid Build Coastguard Worker GVMapTy GVMap;
63*9880d681SAndroid Build Coastguard Worker ConstantToValueMapTy ConstantToValueMap;
64*9880d681SAndroid Build Coastguard Worker };
65*9880d681SAndroid Build Coastguard Worker } // end namespace
66*9880d681SAndroid Build Coastguard Worker
67*9880d681SAndroid Build Coastguard Worker char GenericToNVVM::ID = 0;
68*9880d681SAndroid Build Coastguard Worker
createGenericToNVVMPass()69*9880d681SAndroid Build Coastguard Worker ModulePass *llvm::createGenericToNVVMPass() { return new GenericToNVVM(); }
70*9880d681SAndroid Build Coastguard Worker
71*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(
72*9880d681SAndroid Build Coastguard Worker GenericToNVVM, "generic-to-nvvm",
73*9880d681SAndroid Build Coastguard Worker "Ensure that the global variables are in the global address space", false,
74*9880d681SAndroid Build Coastguard Worker false)
75*9880d681SAndroid Build Coastguard Worker
runOnModule(Module & M)76*9880d681SAndroid Build Coastguard Worker bool GenericToNVVM::runOnModule(Module &M) {
77*9880d681SAndroid Build Coastguard Worker // Create a clone of each global variable that has the default address space.
78*9880d681SAndroid Build Coastguard Worker // The clone is created with the global address space specifier, and the pair
79*9880d681SAndroid Build Coastguard Worker // of original global variable and its clone is placed in the GVMap for later
80*9880d681SAndroid Build Coastguard Worker // use.
81*9880d681SAndroid Build Coastguard Worker
82*9880d681SAndroid Build Coastguard Worker for (Module::global_iterator I = M.global_begin(), E = M.global_end();
83*9880d681SAndroid Build Coastguard Worker I != E;) {
84*9880d681SAndroid Build Coastguard Worker GlobalVariable *GV = &*I++;
85*9880d681SAndroid Build Coastguard Worker if (GV->getType()->getAddressSpace() == llvm::ADDRESS_SPACE_GENERIC &&
86*9880d681SAndroid Build Coastguard Worker !llvm::isTexture(*GV) && !llvm::isSurface(*GV) &&
87*9880d681SAndroid Build Coastguard Worker !llvm::isSampler(*GV) && !GV->getName().startswith("llvm.")) {
88*9880d681SAndroid Build Coastguard Worker GlobalVariable *NewGV = new GlobalVariable(
89*9880d681SAndroid Build Coastguard Worker M, GV->getValueType(), GV->isConstant(),
90*9880d681SAndroid Build Coastguard Worker GV->getLinkage(),
91*9880d681SAndroid Build Coastguard Worker GV->hasInitializer() ? GV->getInitializer() : nullptr,
92*9880d681SAndroid Build Coastguard Worker "", GV, GV->getThreadLocalMode(), llvm::ADDRESS_SPACE_GLOBAL);
93*9880d681SAndroid Build Coastguard Worker NewGV->copyAttributesFrom(GV);
94*9880d681SAndroid Build Coastguard Worker GVMap[GV] = NewGV;
95*9880d681SAndroid Build Coastguard Worker }
96*9880d681SAndroid Build Coastguard Worker }
97*9880d681SAndroid Build Coastguard Worker
98*9880d681SAndroid Build Coastguard Worker // Return immediately, if every global variable has a specific address space
99*9880d681SAndroid Build Coastguard Worker // specifier.
100*9880d681SAndroid Build Coastguard Worker if (GVMap.empty()) {
101*9880d681SAndroid Build Coastguard Worker return false;
102*9880d681SAndroid Build Coastguard Worker }
103*9880d681SAndroid Build Coastguard Worker
104*9880d681SAndroid Build Coastguard Worker // Walk through the instructions in function defitinions, and replace any use
105*9880d681SAndroid Build Coastguard Worker // of original global variables in GVMap with a use of the corresponding
106*9880d681SAndroid Build Coastguard Worker // copies in GVMap. If necessary, promote constants to instructions.
107*9880d681SAndroid Build Coastguard Worker for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
108*9880d681SAndroid Build Coastguard Worker if (I->isDeclaration()) {
109*9880d681SAndroid Build Coastguard Worker continue;
110*9880d681SAndroid Build Coastguard Worker }
111*9880d681SAndroid Build Coastguard Worker IRBuilder<> Builder(I->getEntryBlock().getFirstNonPHIOrDbg());
112*9880d681SAndroid Build Coastguard Worker for (Function::iterator BBI = I->begin(), BBE = I->end(); BBI != BBE;
113*9880d681SAndroid Build Coastguard Worker ++BBI) {
114*9880d681SAndroid Build Coastguard Worker for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE;
115*9880d681SAndroid Build Coastguard Worker ++II) {
116*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = II->getNumOperands(); i < e; ++i) {
117*9880d681SAndroid Build Coastguard Worker Value *Operand = II->getOperand(i);
118*9880d681SAndroid Build Coastguard Worker if (isa<Constant>(Operand)) {
119*9880d681SAndroid Build Coastguard Worker II->setOperand(
120*9880d681SAndroid Build Coastguard Worker i, remapConstant(&M, &*I, cast<Constant>(Operand), Builder));
121*9880d681SAndroid Build Coastguard Worker }
122*9880d681SAndroid Build Coastguard Worker }
123*9880d681SAndroid Build Coastguard Worker }
124*9880d681SAndroid Build Coastguard Worker }
125*9880d681SAndroid Build Coastguard Worker ConstantToValueMap.clear();
126*9880d681SAndroid Build Coastguard Worker }
127*9880d681SAndroid Build Coastguard Worker
128*9880d681SAndroid Build Coastguard Worker // Copy GVMap over to a standard value map.
129*9880d681SAndroid Build Coastguard Worker ValueToValueMapTy VM;
130*9880d681SAndroid Build Coastguard Worker for (auto I = GVMap.begin(), E = GVMap.end(); I != E; ++I)
131*9880d681SAndroid Build Coastguard Worker VM[I->first] = I->second;
132*9880d681SAndroid Build Coastguard Worker
133*9880d681SAndroid Build Coastguard Worker // Walk through the metadata section and update the debug information
134*9880d681SAndroid Build Coastguard Worker // associated with the global variables in the default address space.
135*9880d681SAndroid Build Coastguard Worker for (NamedMDNode &I : M.named_metadata()) {
136*9880d681SAndroid Build Coastguard Worker remapNamedMDNode(VM, &I);
137*9880d681SAndroid Build Coastguard Worker }
138*9880d681SAndroid Build Coastguard Worker
139*9880d681SAndroid Build Coastguard Worker // Walk through the global variable initializers, and replace any use of
140*9880d681SAndroid Build Coastguard Worker // original global variables in GVMap with a use of the corresponding copies
141*9880d681SAndroid Build Coastguard Worker // in GVMap. The copies need to be bitcast to the original global variable
142*9880d681SAndroid Build Coastguard Worker // types, as we cannot use cvta in global variable initializers.
143*9880d681SAndroid Build Coastguard Worker for (GVMapTy::iterator I = GVMap.begin(), E = GVMap.end(); I != E;) {
144*9880d681SAndroid Build Coastguard Worker GlobalVariable *GV = I->first;
145*9880d681SAndroid Build Coastguard Worker GlobalVariable *NewGV = I->second;
146*9880d681SAndroid Build Coastguard Worker
147*9880d681SAndroid Build Coastguard Worker // Remove GV from the map so that it can be RAUWed. Note that
148*9880d681SAndroid Build Coastguard Worker // DenseMap::erase() won't invalidate any iterators but this one.
149*9880d681SAndroid Build Coastguard Worker auto Next = std::next(I);
150*9880d681SAndroid Build Coastguard Worker GVMap.erase(I);
151*9880d681SAndroid Build Coastguard Worker I = Next;
152*9880d681SAndroid Build Coastguard Worker
153*9880d681SAndroid Build Coastguard Worker Constant *BitCastNewGV = ConstantExpr::getPointerCast(NewGV, GV->getType());
154*9880d681SAndroid Build Coastguard Worker // At this point, the remaining uses of GV should be found only in global
155*9880d681SAndroid Build Coastguard Worker // variable initializers, as other uses have been already been removed
156*9880d681SAndroid Build Coastguard Worker // while walking through the instructions in function definitions.
157*9880d681SAndroid Build Coastguard Worker GV->replaceAllUsesWith(BitCastNewGV);
158*9880d681SAndroid Build Coastguard Worker std::string Name = GV->getName();
159*9880d681SAndroid Build Coastguard Worker GV->eraseFromParent();
160*9880d681SAndroid Build Coastguard Worker NewGV->setName(Name);
161*9880d681SAndroid Build Coastguard Worker }
162*9880d681SAndroid Build Coastguard Worker assert(GVMap.empty() && "Expected it to be empty by now");
163*9880d681SAndroid Build Coastguard Worker
164*9880d681SAndroid Build Coastguard Worker return true;
165*9880d681SAndroid Build Coastguard Worker }
166*9880d681SAndroid Build Coastguard Worker
getOrInsertCVTA(Module * M,Function * F,GlobalVariable * GV,IRBuilder<> & Builder)167*9880d681SAndroid Build Coastguard Worker Value *GenericToNVVM::getOrInsertCVTA(Module *M, Function *F,
168*9880d681SAndroid Build Coastguard Worker GlobalVariable *GV,
169*9880d681SAndroid Build Coastguard Worker IRBuilder<> &Builder) {
170*9880d681SAndroid Build Coastguard Worker PointerType *GVType = GV->getType();
171*9880d681SAndroid Build Coastguard Worker Value *CVTA = nullptr;
172*9880d681SAndroid Build Coastguard Worker
173*9880d681SAndroid Build Coastguard Worker // See if the address space conversion requires the operand to be bitcast
174*9880d681SAndroid Build Coastguard Worker // to i8 addrspace(n)* first.
175*9880d681SAndroid Build Coastguard Worker EVT ExtendedGVType = EVT::getEVT(GV->getValueType(), true);
176*9880d681SAndroid Build Coastguard Worker if (!ExtendedGVType.isInteger() && !ExtendedGVType.isFloatingPoint()) {
177*9880d681SAndroid Build Coastguard Worker // A bitcast to i8 addrspace(n)* on the operand is needed.
178*9880d681SAndroid Build Coastguard Worker LLVMContext &Context = M->getContext();
179*9880d681SAndroid Build Coastguard Worker unsigned int AddrSpace = GVType->getAddressSpace();
180*9880d681SAndroid Build Coastguard Worker Type *DestTy = PointerType::get(Type::getInt8Ty(Context), AddrSpace);
181*9880d681SAndroid Build Coastguard Worker CVTA = Builder.CreateBitCast(GV, DestTy, "cvta");
182*9880d681SAndroid Build Coastguard Worker // Insert the address space conversion.
183*9880d681SAndroid Build Coastguard Worker Type *ResultType =
184*9880d681SAndroid Build Coastguard Worker PointerType::get(Type::getInt8Ty(Context), llvm::ADDRESS_SPACE_GENERIC);
185*9880d681SAndroid Build Coastguard Worker Function *CVTAFunction = Intrinsic::getDeclaration(
186*9880d681SAndroid Build Coastguard Worker M, Intrinsic::nvvm_ptr_global_to_gen, {ResultType, DestTy});
187*9880d681SAndroid Build Coastguard Worker CVTA = Builder.CreateCall(CVTAFunction, CVTA, "cvta");
188*9880d681SAndroid Build Coastguard Worker // Another bitcast from i8 * to <the element type of GVType> * is
189*9880d681SAndroid Build Coastguard Worker // required.
190*9880d681SAndroid Build Coastguard Worker DestTy =
191*9880d681SAndroid Build Coastguard Worker PointerType::get(GV->getValueType(), llvm::ADDRESS_SPACE_GENERIC);
192*9880d681SAndroid Build Coastguard Worker CVTA = Builder.CreateBitCast(CVTA, DestTy, "cvta");
193*9880d681SAndroid Build Coastguard Worker } else {
194*9880d681SAndroid Build Coastguard Worker // A simple CVTA is enough.
195*9880d681SAndroid Build Coastguard Worker SmallVector<Type *, 2> ParamTypes;
196*9880d681SAndroid Build Coastguard Worker ParamTypes.push_back(PointerType::get(GV->getValueType(),
197*9880d681SAndroid Build Coastguard Worker llvm::ADDRESS_SPACE_GENERIC));
198*9880d681SAndroid Build Coastguard Worker ParamTypes.push_back(GVType);
199*9880d681SAndroid Build Coastguard Worker Function *CVTAFunction = Intrinsic::getDeclaration(
200*9880d681SAndroid Build Coastguard Worker M, Intrinsic::nvvm_ptr_global_to_gen, ParamTypes);
201*9880d681SAndroid Build Coastguard Worker CVTA = Builder.CreateCall(CVTAFunction, GV, "cvta");
202*9880d681SAndroid Build Coastguard Worker }
203*9880d681SAndroid Build Coastguard Worker
204*9880d681SAndroid Build Coastguard Worker return CVTA;
205*9880d681SAndroid Build Coastguard Worker }
206*9880d681SAndroid Build Coastguard Worker
remapConstant(Module * M,Function * F,Constant * C,IRBuilder<> & Builder)207*9880d681SAndroid Build Coastguard Worker Value *GenericToNVVM::remapConstant(Module *M, Function *F, Constant *C,
208*9880d681SAndroid Build Coastguard Worker IRBuilder<> &Builder) {
209*9880d681SAndroid Build Coastguard Worker // If the constant C has been converted already in the given function F, just
210*9880d681SAndroid Build Coastguard Worker // return the converted value.
211*9880d681SAndroid Build Coastguard Worker ConstantToValueMapTy::iterator CTII = ConstantToValueMap.find(C);
212*9880d681SAndroid Build Coastguard Worker if (CTII != ConstantToValueMap.end()) {
213*9880d681SAndroid Build Coastguard Worker return CTII->second;
214*9880d681SAndroid Build Coastguard Worker }
215*9880d681SAndroid Build Coastguard Worker
216*9880d681SAndroid Build Coastguard Worker Value *NewValue = C;
217*9880d681SAndroid Build Coastguard Worker if (isa<GlobalVariable>(C)) {
218*9880d681SAndroid Build Coastguard Worker // If the constant C is a global variable and is found in GVMap, generate a
219*9880d681SAndroid Build Coastguard Worker // set set of instructions that convert the clone of C with the global
220*9880d681SAndroid Build Coastguard Worker // address space specifier to a generic pointer.
221*9880d681SAndroid Build Coastguard Worker // The constant C cannot be used here, as it will be erased from the
222*9880d681SAndroid Build Coastguard Worker // module eventually. And the clone of C with the global address space
223*9880d681SAndroid Build Coastguard Worker // specifier cannot be used here either, as it will affect the types of
224*9880d681SAndroid Build Coastguard Worker // other instructions in the function. Hence, this address space conversion
225*9880d681SAndroid Build Coastguard Worker // is required.
226*9880d681SAndroid Build Coastguard Worker GVMapTy::iterator I = GVMap.find(cast<GlobalVariable>(C));
227*9880d681SAndroid Build Coastguard Worker if (I != GVMap.end()) {
228*9880d681SAndroid Build Coastguard Worker NewValue = getOrInsertCVTA(M, F, I->second, Builder);
229*9880d681SAndroid Build Coastguard Worker }
230*9880d681SAndroid Build Coastguard Worker } else if (isa<ConstantAggregate>(C)) {
231*9880d681SAndroid Build Coastguard Worker // If any element in the constant vector or aggregate C is or uses a global
232*9880d681SAndroid Build Coastguard Worker // variable in GVMap, the constant C needs to be reconstructed, using a set
233*9880d681SAndroid Build Coastguard Worker // of instructions.
234*9880d681SAndroid Build Coastguard Worker NewValue = remapConstantVectorOrConstantAggregate(M, F, C, Builder);
235*9880d681SAndroid Build Coastguard Worker } else if (isa<ConstantExpr>(C)) {
236*9880d681SAndroid Build Coastguard Worker // If any operand in the constant expression C is or uses a global variable
237*9880d681SAndroid Build Coastguard Worker // in GVMap, the constant expression C needs to be reconstructed, using a
238*9880d681SAndroid Build Coastguard Worker // set of instructions.
239*9880d681SAndroid Build Coastguard Worker NewValue = remapConstantExpr(M, F, cast<ConstantExpr>(C), Builder);
240*9880d681SAndroid Build Coastguard Worker }
241*9880d681SAndroid Build Coastguard Worker
242*9880d681SAndroid Build Coastguard Worker ConstantToValueMap[C] = NewValue;
243*9880d681SAndroid Build Coastguard Worker return NewValue;
244*9880d681SAndroid Build Coastguard Worker }
245*9880d681SAndroid Build Coastguard Worker
remapConstantVectorOrConstantAggregate(Module * M,Function * F,Constant * C,IRBuilder<> & Builder)246*9880d681SAndroid Build Coastguard Worker Value *GenericToNVVM::remapConstantVectorOrConstantAggregate(
247*9880d681SAndroid Build Coastguard Worker Module *M, Function *F, Constant *C, IRBuilder<> &Builder) {
248*9880d681SAndroid Build Coastguard Worker bool OperandChanged = false;
249*9880d681SAndroid Build Coastguard Worker SmallVector<Value *, 4> NewOperands;
250*9880d681SAndroid Build Coastguard Worker unsigned NumOperands = C->getNumOperands();
251*9880d681SAndroid Build Coastguard Worker
252*9880d681SAndroid Build Coastguard Worker // Check if any element is or uses a global variable in GVMap, and thus
253*9880d681SAndroid Build Coastguard Worker // converted to another value.
254*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < NumOperands; ++i) {
255*9880d681SAndroid Build Coastguard Worker Value *Operand = C->getOperand(i);
256*9880d681SAndroid Build Coastguard Worker Value *NewOperand = remapConstant(M, F, cast<Constant>(Operand), Builder);
257*9880d681SAndroid Build Coastguard Worker OperandChanged |= Operand != NewOperand;
258*9880d681SAndroid Build Coastguard Worker NewOperands.push_back(NewOperand);
259*9880d681SAndroid Build Coastguard Worker }
260*9880d681SAndroid Build Coastguard Worker
261*9880d681SAndroid Build Coastguard Worker // If none of the elements has been modified, return C as it is.
262*9880d681SAndroid Build Coastguard Worker if (!OperandChanged) {
263*9880d681SAndroid Build Coastguard Worker return C;
264*9880d681SAndroid Build Coastguard Worker }
265*9880d681SAndroid Build Coastguard Worker
266*9880d681SAndroid Build Coastguard Worker // If any of the elements has been modified, construct the equivalent
267*9880d681SAndroid Build Coastguard Worker // vector or aggregate value with a set instructions and the converted
268*9880d681SAndroid Build Coastguard Worker // elements.
269*9880d681SAndroid Build Coastguard Worker Value *NewValue = UndefValue::get(C->getType());
270*9880d681SAndroid Build Coastguard Worker if (isa<ConstantVector>(C)) {
271*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < NumOperands; ++i) {
272*9880d681SAndroid Build Coastguard Worker Value *Idx = ConstantInt::get(Type::getInt32Ty(M->getContext()), i);
273*9880d681SAndroid Build Coastguard Worker NewValue = Builder.CreateInsertElement(NewValue, NewOperands[i], Idx);
274*9880d681SAndroid Build Coastguard Worker }
275*9880d681SAndroid Build Coastguard Worker } else {
276*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < NumOperands; ++i) {
277*9880d681SAndroid Build Coastguard Worker NewValue =
278*9880d681SAndroid Build Coastguard Worker Builder.CreateInsertValue(NewValue, NewOperands[i], makeArrayRef(i));
279*9880d681SAndroid Build Coastguard Worker }
280*9880d681SAndroid Build Coastguard Worker }
281*9880d681SAndroid Build Coastguard Worker
282*9880d681SAndroid Build Coastguard Worker return NewValue;
283*9880d681SAndroid Build Coastguard Worker }
284*9880d681SAndroid Build Coastguard Worker
remapConstantExpr(Module * M,Function * F,ConstantExpr * C,IRBuilder<> & Builder)285*9880d681SAndroid Build Coastguard Worker Value *GenericToNVVM::remapConstantExpr(Module *M, Function *F, ConstantExpr *C,
286*9880d681SAndroid Build Coastguard Worker IRBuilder<> &Builder) {
287*9880d681SAndroid Build Coastguard Worker bool OperandChanged = false;
288*9880d681SAndroid Build Coastguard Worker SmallVector<Value *, 4> NewOperands;
289*9880d681SAndroid Build Coastguard Worker unsigned NumOperands = C->getNumOperands();
290*9880d681SAndroid Build Coastguard Worker
291*9880d681SAndroid Build Coastguard Worker // Check if any operand is or uses a global variable in GVMap, and thus
292*9880d681SAndroid Build Coastguard Worker // converted to another value.
293*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < NumOperands; ++i) {
294*9880d681SAndroid Build Coastguard Worker Value *Operand = C->getOperand(i);
295*9880d681SAndroid Build Coastguard Worker Value *NewOperand = remapConstant(M, F, cast<Constant>(Operand), Builder);
296*9880d681SAndroid Build Coastguard Worker OperandChanged |= Operand != NewOperand;
297*9880d681SAndroid Build Coastguard Worker NewOperands.push_back(NewOperand);
298*9880d681SAndroid Build Coastguard Worker }
299*9880d681SAndroid Build Coastguard Worker
300*9880d681SAndroid Build Coastguard Worker // If none of the operands has been modified, return C as it is.
301*9880d681SAndroid Build Coastguard Worker if (!OperandChanged) {
302*9880d681SAndroid Build Coastguard Worker return C;
303*9880d681SAndroid Build Coastguard Worker }
304*9880d681SAndroid Build Coastguard Worker
305*9880d681SAndroid Build Coastguard Worker // If any of the operands has been modified, construct the instruction with
306*9880d681SAndroid Build Coastguard Worker // the converted operands.
307*9880d681SAndroid Build Coastguard Worker unsigned Opcode = C->getOpcode();
308*9880d681SAndroid Build Coastguard Worker switch (Opcode) {
309*9880d681SAndroid Build Coastguard Worker case Instruction::ICmp:
310*9880d681SAndroid Build Coastguard Worker // CompareConstantExpr (icmp)
311*9880d681SAndroid Build Coastguard Worker return Builder.CreateICmp(CmpInst::Predicate(C->getPredicate()),
312*9880d681SAndroid Build Coastguard Worker NewOperands[0], NewOperands[1]);
313*9880d681SAndroid Build Coastguard Worker case Instruction::FCmp:
314*9880d681SAndroid Build Coastguard Worker // CompareConstantExpr (fcmp)
315*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Address space conversion should have no effect "
316*9880d681SAndroid Build Coastguard Worker "on float point CompareConstantExpr (fcmp)!");
317*9880d681SAndroid Build Coastguard Worker case Instruction::ExtractElement:
318*9880d681SAndroid Build Coastguard Worker // ExtractElementConstantExpr
319*9880d681SAndroid Build Coastguard Worker return Builder.CreateExtractElement(NewOperands[0], NewOperands[1]);
320*9880d681SAndroid Build Coastguard Worker case Instruction::InsertElement:
321*9880d681SAndroid Build Coastguard Worker // InsertElementConstantExpr
322*9880d681SAndroid Build Coastguard Worker return Builder.CreateInsertElement(NewOperands[0], NewOperands[1],
323*9880d681SAndroid Build Coastguard Worker NewOperands[2]);
324*9880d681SAndroid Build Coastguard Worker case Instruction::ShuffleVector:
325*9880d681SAndroid Build Coastguard Worker // ShuffleVector
326*9880d681SAndroid Build Coastguard Worker return Builder.CreateShuffleVector(NewOperands[0], NewOperands[1],
327*9880d681SAndroid Build Coastguard Worker NewOperands[2]);
328*9880d681SAndroid Build Coastguard Worker case Instruction::ExtractValue:
329*9880d681SAndroid Build Coastguard Worker // ExtractValueConstantExpr
330*9880d681SAndroid Build Coastguard Worker return Builder.CreateExtractValue(NewOperands[0], C->getIndices());
331*9880d681SAndroid Build Coastguard Worker case Instruction::InsertValue:
332*9880d681SAndroid Build Coastguard Worker // InsertValueConstantExpr
333*9880d681SAndroid Build Coastguard Worker return Builder.CreateInsertValue(NewOperands[0], NewOperands[1],
334*9880d681SAndroid Build Coastguard Worker C->getIndices());
335*9880d681SAndroid Build Coastguard Worker case Instruction::GetElementPtr:
336*9880d681SAndroid Build Coastguard Worker // GetElementPtrConstantExpr
337*9880d681SAndroid Build Coastguard Worker return cast<GEPOperator>(C)->isInBounds()
338*9880d681SAndroid Build Coastguard Worker ? Builder.CreateGEP(
339*9880d681SAndroid Build Coastguard Worker cast<GEPOperator>(C)->getSourceElementType(),
340*9880d681SAndroid Build Coastguard Worker NewOperands[0],
341*9880d681SAndroid Build Coastguard Worker makeArrayRef(&NewOperands[1], NumOperands - 1))
342*9880d681SAndroid Build Coastguard Worker : Builder.CreateInBoundsGEP(
343*9880d681SAndroid Build Coastguard Worker cast<GEPOperator>(C)->getSourceElementType(),
344*9880d681SAndroid Build Coastguard Worker NewOperands[0],
345*9880d681SAndroid Build Coastguard Worker makeArrayRef(&NewOperands[1], NumOperands - 1));
346*9880d681SAndroid Build Coastguard Worker case Instruction::Select:
347*9880d681SAndroid Build Coastguard Worker // SelectConstantExpr
348*9880d681SAndroid Build Coastguard Worker return Builder.CreateSelect(NewOperands[0], NewOperands[1], NewOperands[2]);
349*9880d681SAndroid Build Coastguard Worker default:
350*9880d681SAndroid Build Coastguard Worker // BinaryConstantExpr
351*9880d681SAndroid Build Coastguard Worker if (Instruction::isBinaryOp(Opcode)) {
352*9880d681SAndroid Build Coastguard Worker return Builder.CreateBinOp(Instruction::BinaryOps(C->getOpcode()),
353*9880d681SAndroid Build Coastguard Worker NewOperands[0], NewOperands[1]);
354*9880d681SAndroid Build Coastguard Worker }
355*9880d681SAndroid Build Coastguard Worker // UnaryConstantExpr
356*9880d681SAndroid Build Coastguard Worker if (Instruction::isCast(Opcode)) {
357*9880d681SAndroid Build Coastguard Worker return Builder.CreateCast(Instruction::CastOps(C->getOpcode()),
358*9880d681SAndroid Build Coastguard Worker NewOperands[0], C->getType());
359*9880d681SAndroid Build Coastguard Worker }
360*9880d681SAndroid Build Coastguard Worker llvm_unreachable("GenericToNVVM encountered an unsupported ConstantExpr");
361*9880d681SAndroid Build Coastguard Worker }
362*9880d681SAndroid Build Coastguard Worker }
363*9880d681SAndroid Build Coastguard Worker
remapNamedMDNode(ValueToValueMapTy & VM,NamedMDNode * N)364*9880d681SAndroid Build Coastguard Worker void GenericToNVVM::remapNamedMDNode(ValueToValueMapTy &VM, NamedMDNode *N) {
365*9880d681SAndroid Build Coastguard Worker
366*9880d681SAndroid Build Coastguard Worker bool OperandChanged = false;
367*9880d681SAndroid Build Coastguard Worker SmallVector<MDNode *, 16> NewOperands;
368*9880d681SAndroid Build Coastguard Worker unsigned NumOperands = N->getNumOperands();
369*9880d681SAndroid Build Coastguard Worker
370*9880d681SAndroid Build Coastguard Worker // Check if any operand is or contains a global variable in GVMap, and thus
371*9880d681SAndroid Build Coastguard Worker // converted to another value.
372*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < NumOperands; ++i) {
373*9880d681SAndroid Build Coastguard Worker MDNode *Operand = N->getOperand(i);
374*9880d681SAndroid Build Coastguard Worker MDNode *NewOperand = MapMetadata(Operand, VM);
375*9880d681SAndroid Build Coastguard Worker OperandChanged |= Operand != NewOperand;
376*9880d681SAndroid Build Coastguard Worker NewOperands.push_back(NewOperand);
377*9880d681SAndroid Build Coastguard Worker }
378*9880d681SAndroid Build Coastguard Worker
379*9880d681SAndroid Build Coastguard Worker // If none of the operands has been modified, return immediately.
380*9880d681SAndroid Build Coastguard Worker if (!OperandChanged) {
381*9880d681SAndroid Build Coastguard Worker return;
382*9880d681SAndroid Build Coastguard Worker }
383*9880d681SAndroid Build Coastguard Worker
384*9880d681SAndroid Build Coastguard Worker // Replace the old operands with the new operands.
385*9880d681SAndroid Build Coastguard Worker N->dropAllReferences();
386*9880d681SAndroid Build Coastguard Worker for (SmallVectorImpl<MDNode *>::iterator I = NewOperands.begin(),
387*9880d681SAndroid Build Coastguard Worker E = NewOperands.end();
388*9880d681SAndroid Build Coastguard Worker I != E; ++I) {
389*9880d681SAndroid Build Coastguard Worker N->addOperand(*I);
390*9880d681SAndroid Build Coastguard Worker }
391*9880d681SAndroid Build Coastguard Worker }
392