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