121fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski//===- NVVMReflect.cpp - NVVM Emulate conditional compilation -------------===//
221fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski//
321fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski//                     The LLVM Compiler Infrastructure
421fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski//
521fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski// This file is distributed under the University of Illinois Open Source
621fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski// License. See LICENSE.TXT for details.
721fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski//
821fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski//===----------------------------------------------------------------------===//
921fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski//
1036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// This pass replaces occurrences of __nvvm_reflect("string") with an
1121fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski// integer based on -nvvm-reflect-list string=<int> option given to this pass.
12d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski// If an undefined string value is seen in a call to __nvvm_reflect("string"),
13d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski// a default value of 0 will be used.
1421fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski//
1521fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski//===----------------------------------------------------------------------===//
1621fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
17d22367559300c77c73e0ad9e193a33451bf8bf6cJustin Holewinski#include "NVPTX.h"
18d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski#include "llvm/ADT/DenseMap.h"
19d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski#include "llvm/ADT/SmallVector.h"
2021fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski#include "llvm/ADT/StringMap.h"
2136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/Constants.h"
2236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/DerivedTypes.h"
2321fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski#include "llvm/IR/Function.h"
2436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/Instructions.h"
25c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines#include "llvm/IR/Intrinsics.h"
2621fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski#include "llvm/IR/Module.h"
2721fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski#include "llvm/IR/Type.h"
2836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/Pass.h"
2921fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski#include "llvm/Support/CommandLine.h"
3021fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski#include "llvm/Support/Debug.h"
3121fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski#include "llvm/Support/raw_os_ostream.h"
324c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar#include "llvm/Support/raw_ostream.h"
3321fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski#include "llvm/Transforms/Scalar.h"
3421fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski#include <map>
3521fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski#include <sstream>
3621fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski#include <string>
3721fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski#include <vector>
3821fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
3921fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski#define NVVM_REFLECT_FUNCTION "__nvvm_reflect"
4021fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
4121fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinskiusing namespace llvm;
4221fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
43dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#define DEBUG_TYPE "nvptx-reflect"
44dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
4521fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinskinamespace llvm { void initializeNVVMReflectPass(PassRegistry &); }
4621fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
4721fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinskinamespace {
48d22367559300c77c73e0ad9e193a33451bf8bf6cJustin Holewinskiclass NVVMReflect : public ModulePass {
4921fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinskiprivate:
5021fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski  StringMap<int> VarMap;
51d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski  typedef DenseMap<std::string, int>::iterator VarMapIter;
5221fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
5321fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinskipublic:
5421fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski  static char ID;
55c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  NVVMReflect() : ModulePass(ID) {
56d22367559300c77c73e0ad9e193a33451bf8bf6cJustin Holewinski    initializeNVVMReflectPass(*PassRegistry::getPassRegistry());
5721fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski    VarMap.clear();
58d22367559300c77c73e0ad9e193a33451bf8bf6cJustin Holewinski  }
59d22367559300c77c73e0ad9e193a33451bf8bf6cJustin Holewinski
60d22367559300c77c73e0ad9e193a33451bf8bf6cJustin Holewinski  NVVMReflect(const StringMap<int> &Mapping)
61c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  : ModulePass(ID) {
62d22367559300c77c73e0ad9e193a33451bf8bf6cJustin Holewinski    initializeNVVMReflectPass(*PassRegistry::getPassRegistry());
63d22367559300c77c73e0ad9e193a33451bf8bf6cJustin Holewinski    for (StringMap<int>::const_iterator I = Mapping.begin(), E = Mapping.end();
64d22367559300c77c73e0ad9e193a33451bf8bf6cJustin Holewinski         I != E; ++I) {
65d22367559300c77c73e0ad9e193a33451bf8bf6cJustin Holewinski      VarMap[(*I).getKey()] = (*I).getValue();
66d22367559300c77c73e0ad9e193a33451bf8bf6cJustin Holewinski    }
6721fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski  }
6821fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
69dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void getAnalysisUsage(AnalysisUsage &AU) const override {
70dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    AU.setPreservesAll();
71dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  }
72dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  bool runOnModule(Module &) override;
7321fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
74c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesprivate:
75c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  bool handleFunction(Function *ReflectFunction);
7621fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski  void setVarMap();
7721fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski};
7821fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski}
7921fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
80d22367559300c77c73e0ad9e193a33451bf8bf6cJustin HolewinskiModulePass *llvm::createNVVMReflectPass() {
81d22367559300c77c73e0ad9e193a33451bf8bf6cJustin Holewinski  return new NVVMReflect();
82d22367559300c77c73e0ad9e193a33451bf8bf6cJustin Holewinski}
83d22367559300c77c73e0ad9e193a33451bf8bf6cJustin Holewinski
84d22367559300c77c73e0ad9e193a33451bf8bf6cJustin HolewinskiModulePass *llvm::createNVVMReflectPass(const StringMap<int>& Mapping) {
85d22367559300c77c73e0ad9e193a33451bf8bf6cJustin Holewinski  return new NVVMReflect(Mapping);
86d22367559300c77c73e0ad9e193a33451bf8bf6cJustin Holewinski}
87d22367559300c77c73e0ad9e193a33451bf8bf6cJustin Holewinski
8821fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinskistatic cl::opt<bool>
89fe16848601bdde6e3a5e0860199169dd171222a4Nadav RotemNVVMReflectEnabled("nvvm-reflect-enable", cl::init(true), cl::Hidden,
9021fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski                   cl::desc("NVVM reflection, enabled by default"));
9121fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
9221fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinskichar NVVMReflect::ID = 0;
9321fdcb02716f5eae097abfd2f44e40563e90180aJustin HolewinskiINITIALIZE_PASS(NVVMReflect, "nvvm-reflect",
9436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                "Replace occurrences of __nvvm_reflect() calls with 0/1", false,
9521fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski                false)
9621fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
9721fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinskistatic cl::list<std::string>
98fe16848601bdde6e3a5e0860199169dd171222a4Nadav RotemReflectList("nvvm-reflect-list", cl::value_desc("name=<int>"), cl::Hidden,
99d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski            cl::desc("A list of string=num assignments"),
10021fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski            cl::ValueRequired);
10121fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
10221fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski/// The command line can look as follows :
103d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski/// -nvvm-reflect-list a=1,b=2 -nvvm-reflect-list c=3,d=0 -R e=2
10421fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski/// The strings "a=1,b=2", "c=3,d=0", "e=2" are available in the
10521fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski/// ReflectList vector. First, each of ReflectList[i] is 'split'
10621fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski/// using "," as the delimiter. Then each of this part is split
10721fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski/// using "=" as the delimiter.
10821fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinskivoid NVVMReflect::setVarMap() {
10921fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski  for (unsigned i = 0, e = ReflectList.size(); i != e; ++i) {
110d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski    DEBUG(dbgs() << "Option : "  << ReflectList[i] << "\n");
111d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski    SmallVector<StringRef, 4> NameValList;
112cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar    StringRef(ReflectList[i]).split(NameValList, ',');
113d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski    for (unsigned j = 0, ej = NameValList.size(); j != ej; ++j) {
114d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski      SmallVector<StringRef, 2> NameValPair;
115cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar      NameValList[j].split(NameValPair, '=');
116d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski      assert(NameValPair.size() == 2 && "name=val expected");
117d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski      std::stringstream ValStream(NameValPair[1]);
118d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski      int Val;
119d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski      ValStream >> Val;
120d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski      assert((!(ValStream.fail())) && "integer value expected");
121d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski      VarMap[NameValPair[0]] = Val;
12221fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski    }
12321fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski  }
12421fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski}
12521fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
126c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesbool NVVMReflect::handleFunction(Function *ReflectFunction) {
12721fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski  // Validate _reflect function
128d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski  assert(ReflectFunction->isDeclaration() &&
12921fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski         "_reflect function should not have a body");
130d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski  assert(ReflectFunction->getReturnType()->isIntegerTy() &&
13121fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski         "_reflect's return type should be integer");
13221fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
133d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski  std::vector<Instruction *> ToRemove;
13421fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
135d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski  // Go through the uses of ReflectFunction in this Function.
13621fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski  // Each of them should a CallInst with a ConstantArray argument.
13721fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski  // First validate that. If the c-string corresponding to the
13821fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski  // ConstantArray can be found successfully, see if it can be
13921fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski  // found in VarMap. If so, replace the uses of CallInst with the
14021fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski  // value found in VarMap. If not, replace the use  with value 0.
1414c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar
1424c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  // IR for __nvvm_reflect calls differs between CUDA versions:
1434c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  // CUDA 6.5 and earlier uses this sequence:
1444c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  //    %ptr = tail call i8* @llvm.nvvm.ptr.constant.to.gen.p0i8.p4i8
1454c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  //        (i8 addrspace(4)* getelementptr inbounds
1464c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  //           ([8 x i8], [8 x i8] addrspace(4)* @str, i32 0, i32 0))
1474c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  //    %reflect = tail call i32 @__nvvm_reflect(i8* %ptr)
1484c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  //
1494c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  // Value returned by Sym->getOperand(0) is a Constant with a
1504c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  // ConstantDataSequential operand which can be converted to string and used
1514c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  // for lookup.
1524c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  //
1534c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  // CUDA 7.0 does it slightly differently:
1544c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  //   %reflect = call i32 @__nvvm_reflect(i8* addrspacecast
1554c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  //        (i8 addrspace(1)* getelementptr inbounds
1564c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  //           ([8 x i8], [8 x i8] addrspace(1)* @str, i32 0, i32 0) to i8*))
1574c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  //
1584c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  // In this case, we get a Constant with a GlobalVariable operand and we need
1594c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  // to dig deeper to find its initializer with the string we'll use for lookup.
1604c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar
16136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (User *U : ReflectFunction->users()) {
16236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    assert(isa<CallInst>(U) && "Only a call instruction can use _reflect");
16336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    CallInst *Reflect = cast<CallInst>(U);
16421fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
165d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski    assert((Reflect->getNumOperands() == 2) &&
16621fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski           "Only one operand expect for _reflect function");
16721fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski    // In cuda, we will have an extra constant-to-generic conversion of
16821fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski    // the string.
169c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    const Value *Str = Reflect->getArgOperand(0);
170c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    if (isa<CallInst>(Str)) {
171c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      // CUDA path
172c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      const CallInst *ConvCall = cast<CallInst>(Str);
173c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      Str = ConvCall->getArgOperand(0);
174c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    }
175c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    assert(isa<ConstantExpr>(Str) &&
17621fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski           "Format of _reflect function not recognized");
177c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    const ConstantExpr *GEP = cast<ConstantExpr>(Str);
17821fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
179d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski    const Value *Sym = GEP->getOperand(0);
180d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski    assert(isa<Constant>(Sym) && "Format of _reflect function not recognized");
18121fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
1824c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar    const Value *Operand = cast<Constant>(Sym)->getOperand(0);
1834c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar    if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Operand)) {
1844c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar      // For CUDA-7.0 style __nvvm_reflect calls we need to find operand's
1854c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar      // initializer.
1864c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar      assert(GV->hasInitializer() &&
1874c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar             "Format of _reflect function not recognized");
1884c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar      const Constant *Initializer = GV->getInitializer();
1894c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar      Operand = Initializer;
1904c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar    }
19121fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
1924c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar    assert(isa<ConstantDataSequential>(Operand) &&
19321fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski           "Format of _reflect function not recognized");
1944c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar    assert(cast<ConstantDataSequential>(Operand)->isCString() &&
19521fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski           "Format of _reflect function not recognized");
19621fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
197d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski    std::string ReflectArg =
1984c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar        cast<ConstantDataSequential>(Operand)->getAsString();
19921fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
200d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski    ReflectArg = ReflectArg.substr(0, ReflectArg.size() - 1);
201d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski    DEBUG(dbgs() << "Arg of _reflect : " << ReflectArg << "\n");
20221fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
203d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski    int ReflectVal = 0; // The default value is 0
204d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski    if (VarMap.find(ReflectArg) != VarMap.end()) {
205d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski      ReflectVal = VarMap[ReflectArg];
20621fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski    }
207d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski    Reflect->replaceAllUsesWith(
208d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski        ConstantInt::get(Reflect->getType(), ReflectVal));
209d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski    ToRemove.push_back(Reflect);
21021fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski  }
211d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski  if (ToRemove.size() == 0)
21221fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski    return false;
21321fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski
214d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski  for (unsigned i = 0, e = ToRemove.size(); i != e; ++i)
215d4ab1926af982e4334978fd9bf9156c7c087f6f5Justin Holewinski    ToRemove[i]->eraseFromParent();
21621fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski  return true;
21721fdcb02716f5eae097abfd2f44e40563e90180aJustin Holewinski}
218c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
219c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesbool NVVMReflect::runOnModule(Module &M) {
220c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  if (!NVVMReflectEnabled)
221c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    return false;
222c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
223c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  setVarMap();
224c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
225c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
226c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  bool Res = false;
227c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  std::string Name;
228c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  Type *Tys[1];
229c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  Type *I8Ty = Type::getInt8Ty(M.getContext());
230c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  Function *ReflectFunction;
231c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
232c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  // Check for standard overloaded versions of llvm.nvvm.reflect
233c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
234c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  for (unsigned i = 0; i != 5; ++i) {
235c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    Tys[0] = PointerType::get(I8Ty, i);
236c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    Name = Intrinsic::getName(Intrinsic::nvvm_reflect, Tys);
237c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    ReflectFunction = M.getFunction(Name);
238c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    if(ReflectFunction != 0) {
239c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines      Res |= handleFunction(ReflectFunction);
240c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    }
241c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  }
242c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
243c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  ReflectFunction = M.getFunction(NVVM_REFLECT_FUNCTION);
244c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  // If reflect function is not used, then there will be
245c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  // no entry in the module.
246c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  if (ReflectFunction != 0)
247c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    Res |= handleFunction(ReflectFunction);
248c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
249c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  return Res;
250c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines}
251