LLVM  4.0.0
NVVMReflect.cpp
Go to the documentation of this file.
1 //===- NVVMReflect.cpp - NVVM Emulate conditional compilation -------------===//
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 // This pass replaces occurrences of __nvvm_reflect("foo") and llvm.nvvm.reflect
11 // with an integer.
12 //
13 // We choose the value we use by looking, in this order, at:
14 //
15 // * the -nvvm-reflect-list flag, which has the format "foo=1,bar=42",
16 // * the StringMap passed to the pass's constructor, and
17 // * metadata in the module itself.
18 //
19 // If we see an unknown string, we replace its call with 0.
20 //
21 //===----------------------------------------------------------------------===//
22 
23 #include "NVPTX.h"
24 #include "llvm/ADT/SmallVector.h"
25 #include "llvm/ADT/StringMap.h"
26 #include "llvm/IR/Constants.h"
27 #include "llvm/IR/DerivedTypes.h"
28 #include "llvm/IR/Function.h"
29 #include "llvm/IR/InstIterator.h"
30 #include "llvm/IR/Instructions.h"
31 #include "llvm/IR/Intrinsics.h"
32 #include "llvm/IR/Module.h"
33 #include "llvm/IR/Type.h"
34 #include "llvm/Pass.h"
36 #include "llvm/Support/Debug.h"
39 #include "llvm/Transforms/Scalar.h"
40 #include <sstream>
41 #include <string>
42 #define NVVM_REFLECT_FUNCTION "__nvvm_reflect"
43 
44 using namespace llvm;
45 
46 #define DEBUG_TYPE "nvptx-reflect"
47 
48 namespace llvm { void initializeNVVMReflectPass(PassRegistry &); }
49 
50 namespace {
51 class NVVMReflect : public FunctionPass {
52 private:
53  StringMap<int> VarMap;
54 
55 public:
56  static char ID;
57  NVVMReflect() : NVVMReflect(StringMap<int>()) {}
58 
59  NVVMReflect(const StringMap<int> &Mapping)
60  : FunctionPass(ID), VarMap(Mapping) {
62  setVarMap();
63  }
64 
65  bool runOnFunction(Function &) override;
66 
67 private:
68  void setVarMap();
69 };
70 }
71 
72 FunctionPass *llvm::createNVVMReflectPass() { return new NVVMReflect(); }
74  return new NVVMReflect(Mapping);
75 }
76 
77 static cl::opt<bool>
78 NVVMReflectEnabled("nvvm-reflect-enable", cl::init(true), cl::Hidden,
79  cl::desc("NVVM reflection, enabled by default"));
80 
81 char NVVMReflect::ID = 0;
82 INITIALIZE_PASS(NVVMReflect, "nvvm-reflect",
83  "Replace occurrences of __nvvm_reflect() calls with 0/1", false,
84  false)
85 
86 static cl::list<std::string>
87 ReflectList("nvvm-reflect-list", cl::value_desc("name=<int>"), cl::Hidden,
88  cl::desc("A list of string=num assignments"),
89  cl::ValueRequired);
90 
91 /// The command line can look as follows :
92 /// -nvvm-reflect-list a=1,b=2 -nvvm-reflect-list c=3,d=0 -R e=2
93 /// The strings "a=1,b=2", "c=3,d=0", "e=2" are available in the
94 /// ReflectList vector. First, each of ReflectList[i] is 'split'
95 /// using "," as the delimiter. Then each of this part is split
96 /// using "=" as the delimiter.
97 void NVVMReflect::setVarMap() {
98  for (unsigned i = 0, e = ReflectList.size(); i != e; ++i) {
99  DEBUG(dbgs() << "Option : " << ReflectList[i] << "\n");
100  SmallVector<StringRef, 4> NameValList;
101  StringRef(ReflectList[i]).split(NameValList, ',');
102  for (unsigned j = 0, ej = NameValList.size(); j != ej; ++j) {
103  SmallVector<StringRef, 2> NameValPair;
104  NameValList[j].split(NameValPair, '=');
105  assert(NameValPair.size() == 2 && "name=val expected");
106  std::stringstream ValStream(NameValPair[1]);
107  int Val;
108  ValStream >> Val;
109  assert((!(ValStream.fail())) && "integer value expected");
110  VarMap[NameValPair[0]] = Val;
111  }
112  }
113 }
114 
115 bool NVVMReflect::runOnFunction(Function &F) {
116  if (!NVVMReflectEnabled)
117  return false;
118 
119  if (F.getName() == NVVM_REFLECT_FUNCTION) {
120  assert(F.isDeclaration() && "_reflect function should not have a body");
122  "_reflect's return type should be integer");
123  return false;
124  }
125 
127 
128  // Go through the calls in this function. Each call to __nvvm_reflect or
129  // llvm.nvvm.reflect should be a CallInst with a ConstantArray argument.
130  // First validate that. If the c-string corresponding to the ConstantArray can
131  // be found successfully, see if it can be found in VarMap. If so, replace the
132  // uses of CallInst with the value found in VarMap. If not, replace the use
133  // with value 0.
134 
135  // The IR for __nvvm_reflect calls differs between CUDA versions.
136  //
137  // CUDA 6.5 and earlier uses this sequence:
138  // %ptr = tail call i8* @llvm.nvvm.ptr.constant.to.gen.p0i8.p4i8
139  // (i8 addrspace(4)* getelementptr inbounds
140  // ([8 x i8], [8 x i8] addrspace(4)* @str, i32 0, i32 0))
141  // %reflect = tail call i32 @__nvvm_reflect(i8* %ptr)
142  //
143  // The value returned by Sym->getOperand(0) is a Constant with a
144  // ConstantDataSequential operand which can be converted to string and used
145  // for lookup.
146  //
147  // CUDA 7.0 does it slightly differently:
148  // %reflect = call i32 @__nvvm_reflect(i8* addrspacecast
149  // (i8 addrspace(1)* getelementptr inbounds
150  // ([8 x i8], [8 x i8] addrspace(1)* @str, i32 0, i32 0) to i8*))
151  //
152  // In this case, we get a Constant with a GlobalVariable operand and we need
153  // to dig deeper to find its initializer with the string we'll use for lookup.
154  for (Instruction &I : instructions(F)) {
156  if (!Call)
157  continue;
158  Function *Callee = Call->getCalledFunction();
159  if (!Callee || (Callee->getName() != NVVM_REFLECT_FUNCTION &&
160  Callee->getIntrinsicID() != Intrinsic::nvvm_reflect))
161  continue;
162 
163  // FIXME: Improve error handling here and elsewhere in this pass.
164  assert(Call->getNumOperands() == 2 &&
165  "Wrong number of operands to __nvvm_reflect function");
166 
167  // In cuda 6.5 and earlier, we will have an extra constant-to-generic
168  // conversion of the string.
169  const Value *Str = Call->getArgOperand(0);
170  if (const CallInst *ConvCall = dyn_cast<CallInst>(Str)) {
171  // FIXME: Add assertions about ConvCall.
172  Str = ConvCall->getArgOperand(0);
173  }
174  assert(isa<ConstantExpr>(Str) &&
175  "Format of __nvvm__reflect function not recognized");
176  const ConstantExpr *GEP = cast<ConstantExpr>(Str);
177 
178  const Value *Sym = GEP->getOperand(0);
179  assert(isa<Constant>(Sym) &&
180  "Format of __nvvm_reflect function not recognized");
181 
182  const Value *Operand = cast<Constant>(Sym)->getOperand(0);
183  if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Operand)) {
184  // For CUDA-7.0 style __nvvm_reflect calls, we need to find the operand's
185  // initializer.
186  assert(GV->hasInitializer() &&
187  "Format of _reflect function not recognized");
188  const Constant *Initializer = GV->getInitializer();
189  Operand = Initializer;
190  }
191 
192  assert(isa<ConstantDataSequential>(Operand) &&
193  "Format of _reflect function not recognized");
194  assert(cast<ConstantDataSequential>(Operand)->isCString() &&
195  "Format of _reflect function not recognized");
196 
197  StringRef ReflectArg = cast<ConstantDataSequential>(Operand)->getAsString();
198  ReflectArg = ReflectArg.substr(0, ReflectArg.size() - 1);
199  DEBUG(dbgs() << "Arg of _reflect : " << ReflectArg << "\n");
200 
201  int ReflectVal = 0; // The default value is 0
202  auto Iter = VarMap.find(ReflectArg);
203  if (Iter != VarMap.end())
204  ReflectVal = Iter->second;
205  else if (ReflectArg == "__CUDA_FTZ") {
206  // Try to pull __CUDA_FTZ from the nvvm-reflect-ftz module flag.
207  if (auto *Flag = mdconst::extract_or_null<ConstantInt>(
208  F.getParent()->getModuleFlag("nvvm-reflect-ftz")))
209  ReflectVal = Flag->getSExtValue();
210  }
211  Call->replaceAllUsesWith(ConstantInt::get(Call->getType(), ReflectVal));
212  ToRemove.push_back(Call);
213  }
214 
215  for (Instruction *I : ToRemove)
216  I->eraseFromParent();
217 
218  return ToRemove.size() > 0;
219 }
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
size_t i
FunctionPass * createNVVMReflectPass()
Definition: NVVMReflect.cpp:72
unsigned getNumOperands() const
Definition: User.h:167
This class represents a function call, abstracting a target machine's calling convention.
Type * getReturnType() const
Returns the type of the ret val.
Definition: Function.cpp:238
Hexagon Common GEP
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:191
static cl::opt< bool > NVVMReflectEnabled("nvvm-reflect-enable", cl::init(true), cl::Hidden, cl::desc("NVVM reflection, enabled by default"))
A constant value that is initialized with an expression using other constant values.
Definition: Constants.h:873
#define F(x, y, z)
Definition: MD5.cpp:51
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:401
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Definition: StringRef.h:135
Flag
These should be considered private to the implementation of the MCInstrDesc class.
Definition: MCInstrDesc.h:121
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:395
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
void initializeNVVMReflectPass(PassRegistry &)
This is an important base class in LLVM.
Definition: Constant.h:42
This file contains the declarations for the subclasses of Constant, which represent the different fla...
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:587
#define NVVM_REFLECT_FUNCTION
Definition: NVVMReflect.cpp:42
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
Value * getOperand(unsigned i) const
Definition: User.h:145
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:36
Metadata * getModuleFlag(StringRef Key) const
Return the corresponding value if Key appears in module flags, otherwise return null.
Definition: Module.cpp:325
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:843
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:230
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:558
Function * getCalledFunction() const
Return the function called, or null if this is an indirect function invocation.
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
Definition: Function.h:146
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
Value * getArgOperand(unsigned i) const
getArgOperand/setArgOperand - Return/set the i-th call argument.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings"...
Definition: StringMap.h:223
LLVM_NODISCARD std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:716
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition: Type.h:195
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition: Globals.cpp:188
#define I(x, y, z)
Definition: MD5.cpp:54
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
Definition: SmallVector.h:135
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:287
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:537
LLVM Value Representation.
Definition: Value.h:71
static const char * name
#define DEBUG(X)
Definition: Debug.h:100
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
inst_range instructions(Function *F)
Definition: InstIterator.h:132
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:40
static GCRegistry::Add< ErlangGC > A("erlang","erlang-compatible garbage collector")