Coverage Report

Created: 2019-07-24 05:18

/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
}