/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/NVPTX/NVPTXGenericToNVVM.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | |
14 | | #include "MCTargetDesc/NVPTXBaseInfo.h" |
15 | | #include "NVPTX.h" |
16 | | #include "NVPTXUtilities.h" |
17 | | #include "llvm/CodeGen/ValueTypes.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" |
23 | | #include "llvm/IR/LegacyPassManager.h" |
24 | | #include "llvm/IR/Module.h" |
25 | | #include "llvm/IR/Operator.h" |
26 | | #include "llvm/IR/ValueMap.h" |
27 | | #include "llvm/Transforms/Utils/ValueMapper.h" |
28 | | |
29 | | using namespace llvm; |
30 | | |
31 | | namespace llvm { |
32 | | void initializeGenericToNVVMPass(PassRegistry &); |
33 | | } |
34 | | |
35 | | namespace { |
36 | | class GenericToNVVM : public ModulePass { |
37 | | public: |
38 | | static char ID; |
39 | | |
40 | 264 | GenericToNVVM() : ModulePass(ID) {} |
41 | | |
42 | | bool runOnModule(Module &M) override; |
43 | | |
44 | 262 | void getAnalysisUsage(AnalysisUsage &AU) const override {} |
45 | | |
46 | | private: |
47 | | Value *remapConstant(Module *M, Function *F, Constant *C, |
48 | | IRBuilder<> &Builder); |
49 | | Value *remapConstantVectorOrConstantAggregate(Module *M, Function *F, |
50 | | Constant *C, |
51 | | IRBuilder<> &Builder); |
52 | | Value *remapConstantExpr(Module *M, Function *F, ConstantExpr *C, |
53 | | IRBuilder<> &Builder); |
54 | | |
55 | | typedef ValueMap<GlobalVariable *, GlobalVariable *> GVMapTy; |
56 | | typedef ValueMap<Constant *, Value *> ConstantToValueMapTy; |
57 | | GVMapTy GVMap; |
58 | | ConstantToValueMapTy ConstantToValueMap; |
59 | | }; |
60 | | } // end namespace |
61 | | |
62 | | char GenericToNVVM::ID = 0; |
63 | | |
64 | 263 | ModulePass *llvm::createGenericToNVVMPass() { return new GenericToNVVM(); } |
65 | | |
66 | | INITIALIZE_PASS( |
67 | | GenericToNVVM, "generic-to-nvvm", |
68 | | "Ensure that the global variables are in the global address space", false, |
69 | | false) |
70 | | |
71 | 259 | bool GenericToNVVM::runOnModule(Module &M) { |
72 | 259 | // Create a clone of each global variable that has the default address space. |
73 | 259 | // The clone is created with the global address space specifier, and the pair |
74 | 259 | // of original global variable and its clone is placed in the GVMap for later |
75 | 259 | // use. |
76 | 259 | |
77 | 259 | for (Module::global_iterator I = M.global_begin(), E = M.global_end(); |
78 | 341 | I != E;) { |
79 | 82 | GlobalVariable *GV = &*I++; |
80 | 82 | if (GV->getType()->getAddressSpace() == llvm::ADDRESS_SPACE_GENERIC && |
81 | 82 | !llvm::isTexture(*GV)30 && !llvm::isSurface(*GV)30 && |
82 | 82 | !llvm::isSampler(*GV)30 && !GV->getName().startswith("llvm.")30 ) { |
83 | 27 | GlobalVariable *NewGV = new GlobalVariable( |
84 | 27 | M, GV->getValueType(), GV->isConstant(), |
85 | 27 | GV->getLinkage(), |
86 | 27 | GV->hasInitializer() ? GV->getInitializer()21 : nullptr6 , |
87 | 27 | "", GV, GV->getThreadLocalMode(), llvm::ADDRESS_SPACE_GLOBAL); |
88 | 27 | NewGV->copyAttributesFrom(GV); |
89 | 27 | GVMap[GV] = NewGV; |
90 | 27 | } |
91 | 82 | } |
92 | 259 | |
93 | 259 | // Return immediately, if every global variable has a specific address space |
94 | 259 | // specifier. |
95 | 259 | if (GVMap.empty()) { |
96 | 246 | return false; |
97 | 246 | } |
98 | 13 | |
99 | 13 | // Walk through the instructions in function defitinions, and replace any use |
100 | 13 | // of original global variables in GVMap with a use of the corresponding |
101 | 13 | // copies in GVMap. If necessary, promote constants to instructions. |
102 | 47 | for (Module::iterator I = M.begin(), E = M.end(); 13 I != E; ++I34 ) { |
103 | 34 | if (I->isDeclaration()) { |
104 | 7 | continue; |
105 | 7 | } |
106 | 27 | IRBuilder<> Builder(I->getEntryBlock().getFirstNonPHIOrDbg()); |
107 | 62 | for (Function::iterator BBI = I->begin(), BBE = I->end(); BBI != BBE; |
108 | 35 | ++BBI) { |
109 | 190 | for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE; |
110 | 155 | ++II) { |
111 | 366 | for (unsigned i = 0, e = II->getNumOperands(); i < e; ++i211 ) { |
112 | 211 | Value *Operand = II->getOperand(i); |
113 | 211 | if (isa<Constant>(Operand)) { |
114 | 90 | II->setOperand( |
115 | 90 | i, remapConstant(&M, &*I, cast<Constant>(Operand), Builder)); |
116 | 90 | } |
117 | 211 | } |
118 | 155 | } |
119 | 35 | } |
120 | 27 | ConstantToValueMap.clear(); |
121 | 27 | } |
122 | 13 | |
123 | 13 | // Copy GVMap over to a standard value map. |
124 | 13 | ValueToValueMapTy VM; |
125 | 40 | for (auto I = GVMap.begin(), E = GVMap.end(); I != E; ++I27 ) |
126 | 27 | VM[I->first] = I->second; |
127 | 13 | |
128 | 13 | // Walk through the global variable initializers, and replace any use of |
129 | 13 | // original global variables in GVMap with a use of the corresponding copies |
130 | 13 | // in GVMap. The copies need to be bitcast to the original global variable |
131 | 13 | // types, as we cannot use cvta in global variable initializers. |
132 | 40 | for (GVMapTy::iterator I = GVMap.begin(), E = GVMap.end(); I != E;) { |
133 | 27 | GlobalVariable *GV = I->first; |
134 | 27 | GlobalVariable *NewGV = I->second; |
135 | 27 | |
136 | 27 | // Remove GV from the map so that it can be RAUWed. Note that |
137 | 27 | // DenseMap::erase() won't invalidate any iterators but this one. |
138 | 27 | auto Next = std::next(I); |
139 | 27 | GVMap.erase(I); |
140 | 27 | I = Next; |
141 | 27 | |
142 | 27 | Constant *BitCastNewGV = ConstantExpr::getPointerCast(NewGV, GV->getType()); |
143 | 27 | // At this point, the remaining uses of GV should be found only in global |
144 | 27 | // variable initializers, as other uses have been already been removed |
145 | 27 | // while walking through the instructions in function definitions. |
146 | 27 | GV->replaceAllUsesWith(BitCastNewGV); |
147 | 27 | std::string Name = GV->getName(); |
148 | 27 | GV->eraseFromParent(); |
149 | 27 | NewGV->setName(Name); |
150 | 27 | } |
151 | 13 | assert(GVMap.empty() && "Expected it to be empty by now"); |
152 | 13 | |
153 | 13 | return true; |
154 | 13 | } |
155 | | |
156 | | Value *GenericToNVVM::remapConstant(Module *M, Function *F, Constant *C, |
157 | 130 | IRBuilder<> &Builder) { |
158 | 130 | // If the constant C has been converted already in the given function F, just |
159 | 130 | // return the converted value. |
160 | 130 | ConstantToValueMapTy::iterator CTII = ConstantToValueMap.find(C); |
161 | 130 | if (CTII != ConstantToValueMap.end()) { |
162 | 39 | return CTII->second; |
163 | 39 | } |
164 | 91 | |
165 | 91 | Value *NewValue = C; |
166 | 91 | if (isa<GlobalVariable>(C)) { |
167 | 26 | // If the constant C is a global variable and is found in GVMap, substitute |
168 | 26 | // |
169 | 26 | // addrspacecast GVMap[C] to addrspace(0) |
170 | 26 | // |
171 | 26 | // for our use of C. |
172 | 26 | GVMapTy::iterator I = GVMap.find(cast<GlobalVariable>(C)); |
173 | 26 | if (I != GVMap.end()) { |
174 | 14 | GlobalVariable *GV = I->second; |
175 | 14 | NewValue = Builder.CreateAddrSpaceCast( |
176 | 14 | GV, |
177 | 14 | PointerType::get(GV->getValueType(), llvm::ADDRESS_SPACE_GENERIC)); |
178 | 14 | } |
179 | 65 | } else if (isa<ConstantAggregate>(C)) { |
180 | 0 | // If any element in the constant vector or aggregate C is or uses a global |
181 | 0 | // variable in GVMap, the constant C needs to be reconstructed, using a set |
182 | 0 | // of instructions. |
183 | 0 | NewValue = remapConstantVectorOrConstantAggregate(M, F, C, Builder); |
184 | 65 | } else if (isa<ConstantExpr>(C)) { |
185 | 22 | // If any operand in the constant expression C is or uses a global variable |
186 | 22 | // in GVMap, the constant expression C needs to be reconstructed, using a |
187 | 22 | // set of instructions. |
188 | 22 | NewValue = remapConstantExpr(M, F, cast<ConstantExpr>(C), Builder); |
189 | 22 | } |
190 | 91 | |
191 | 91 | ConstantToValueMap[C] = NewValue; |
192 | 91 | return NewValue; |
193 | 91 | } |
194 | | |
195 | | Value *GenericToNVVM::remapConstantVectorOrConstantAggregate( |
196 | 0 | Module *M, Function *F, Constant *C, IRBuilder<> &Builder) { |
197 | 0 | bool OperandChanged = false; |
198 | 0 | SmallVector<Value *, 4> NewOperands; |
199 | 0 | unsigned NumOperands = C->getNumOperands(); |
200 | 0 |
|
201 | 0 | // Check if any element is or uses a global variable in GVMap, and thus |
202 | 0 | // converted to another value. |
203 | 0 | for (unsigned i = 0; i < NumOperands; ++i) { |
204 | 0 | Value *Operand = C->getOperand(i); |
205 | 0 | Value *NewOperand = remapConstant(M, F, cast<Constant>(Operand), Builder); |
206 | 0 | OperandChanged |= Operand != NewOperand; |
207 | 0 | NewOperands.push_back(NewOperand); |
208 | 0 | } |
209 | 0 |
|
210 | 0 | // If none of the elements has been modified, return C as it is. |
211 | 0 | if (!OperandChanged) { |
212 | 0 | return C; |
213 | 0 | } |
214 | 0 | |
215 | 0 | // If any of the elements has been modified, construct the equivalent |
216 | 0 | // vector or aggregate value with a set instructions and the converted |
217 | 0 | // elements. |
218 | 0 | Value *NewValue = UndefValue::get(C->getType()); |
219 | 0 | if (isa<ConstantVector>(C)) { |
220 | 0 | for (unsigned i = 0; i < NumOperands; ++i) { |
221 | 0 | Value *Idx = ConstantInt::get(Type::getInt32Ty(M->getContext()), i); |
222 | 0 | NewValue = Builder.CreateInsertElement(NewValue, NewOperands[i], Idx); |
223 | 0 | } |
224 | 0 | } else { |
225 | 0 | for (unsigned i = 0; i < NumOperands; ++i) { |
226 | 0 | NewValue = |
227 | 0 | Builder.CreateInsertValue(NewValue, NewOperands[i], makeArrayRef(i)); |
228 | 0 | } |
229 | 0 | } |
230 | 0 |
|
231 | 0 | return NewValue; |
232 | 0 | } |
233 | | |
234 | | Value *GenericToNVVM::remapConstantExpr(Module *M, Function *F, ConstantExpr *C, |
235 | 22 | IRBuilder<> &Builder) { |
236 | 22 | bool OperandChanged = false; |
237 | 22 | SmallVector<Value *, 4> NewOperands; |
238 | 22 | unsigned NumOperands = C->getNumOperands(); |
239 | 22 | |
240 | 22 | // Check if any operand is or uses a global variable in GVMap, and thus |
241 | 22 | // converted to another value. |
242 | 62 | for (unsigned i = 0; i < NumOperands; ++i40 ) { |
243 | 40 | Value *Operand = C->getOperand(i); |
244 | 40 | Value *NewOperand = remapConstant(M, F, cast<Constant>(Operand), Builder); |
245 | 40 | OperandChanged |= Operand != NewOperand; |
246 | 40 | NewOperands.push_back(NewOperand); |
247 | 40 | } |
248 | 22 | |
249 | 22 | // If none of the operands has been modified, return C as it is. |
250 | 22 | if (!OperandChanged) { |
251 | 17 | return C; |
252 | 17 | } |
253 | 5 | |
254 | 5 | // If any of the operands has been modified, construct the instruction with |
255 | 5 | // the converted operands. |
256 | 5 | unsigned Opcode = C->getOpcode(); |
257 | 5 | switch (Opcode) { |
258 | 5 | case Instruction::ICmp: |
259 | 0 | // CompareConstantExpr (icmp) |
260 | 0 | return Builder.CreateICmp(CmpInst::Predicate(C->getPredicate()), |
261 | 0 | NewOperands[0], NewOperands[1]); |
262 | 5 | case Instruction::FCmp: |
263 | 0 | // CompareConstantExpr (fcmp) |
264 | 0 | llvm_unreachable("Address space conversion should have no effect " |
265 | 5 | "on float point CompareConstantExpr (fcmp)!"); |
266 | 5 | case Instruction::ExtractElement: |
267 | 0 | // ExtractElementConstantExpr |
268 | 0 | return Builder.CreateExtractElement(NewOperands[0], NewOperands[1]); |
269 | 5 | case Instruction::InsertElement: |
270 | 0 | // InsertElementConstantExpr |
271 | 0 | return Builder.CreateInsertElement(NewOperands[0], NewOperands[1], |
272 | 0 | NewOperands[2]); |
273 | 5 | case Instruction::ShuffleVector: |
274 | 0 | // ShuffleVector |
275 | 0 | return Builder.CreateShuffleVector(NewOperands[0], NewOperands[1], |
276 | 0 | NewOperands[2]); |
277 | 5 | case Instruction::ExtractValue: |
278 | 0 | // ExtractValueConstantExpr |
279 | 0 | return Builder.CreateExtractValue(NewOperands[0], C->getIndices()); |
280 | 5 | case Instruction::InsertValue: |
281 | 0 | // InsertValueConstantExpr |
282 | 0 | return Builder.CreateInsertValue(NewOperands[0], NewOperands[1], |
283 | 0 | C->getIndices()); |
284 | 5 | case Instruction::GetElementPtr: |
285 | 5 | // GetElementPtrConstantExpr |
286 | 5 | return cast<GEPOperator>(C)->isInBounds() |
287 | 5 | ? Builder.CreateGEP( |
288 | 5 | cast<GEPOperator>(C)->getSourceElementType(), |
289 | 5 | NewOperands[0], |
290 | 5 | makeArrayRef(&NewOperands[1], NumOperands - 1)) |
291 | 5 | : Builder.CreateInBoundsGEP( |
292 | 0 | cast<GEPOperator>(C)->getSourceElementType(), |
293 | 0 | NewOperands[0], |
294 | 0 | makeArrayRef(&NewOperands[1], NumOperands - 1)); |
295 | 5 | case Instruction::Select: |
296 | 0 | // SelectConstantExpr |
297 | 0 | return Builder.CreateSelect(NewOperands[0], NewOperands[1], NewOperands[2]); |
298 | 5 | default: |
299 | 0 | // BinaryConstantExpr |
300 | 0 | if (Instruction::isBinaryOp(Opcode)) { |
301 | 0 | return Builder.CreateBinOp(Instruction::BinaryOps(C->getOpcode()), |
302 | 0 | NewOperands[0], NewOperands[1]); |
303 | 0 | } |
304 | 0 | // UnaryConstantExpr |
305 | 0 | if (Instruction::isCast(Opcode)) { |
306 | 0 | return Builder.CreateCast(Instruction::CastOps(C->getOpcode()), |
307 | 0 | NewOperands[0], C->getType()); |
308 | 0 | } |
309 | 0 | llvm_unreachable("GenericToNVVM encountered an unsupported ConstantExpr"); |
310 | | } |
311 | | } |