LLVM  6.0.0svn
NVVMIntrRange.cpp
Go to the documentation of this file.
1 //===- NVVMIntrRange.cpp - Set !range metadata for NVVM intrinsics --------===//
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 adds appropriate !range metadata for calls to NVVM
11 // intrinsics that return a limited range of values.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "NVPTX.h"
16 #include "llvm/IR/Constants.h"
17 #include "llvm/IR/InstIterator.h"
18 #include "llvm/IR/Instructions.h"
19 #include "llvm/IR/Intrinsics.h"
20 
21 using namespace llvm;
22 
23 #define DEBUG_TYPE "nvvm-intr-range"
24 
25 namespace llvm { void initializeNVVMIntrRangePass(PassRegistry &); }
26 
27 // Add !range metadata based on limits of given SM variant.
28 static cl::opt<unsigned> NVVMIntrRangeSM("nvvm-intr-range-sm", cl::init(20),
29  cl::Hidden, cl::desc("SM variant"));
30 
31 namespace {
32 class NVVMIntrRange : public FunctionPass {
33  private:
34  struct {
35  unsigned x, y, z;
36  } MaxBlockSize, MaxGridSize;
37 
38  public:
39  static char ID;
40  NVVMIntrRange() : NVVMIntrRange(NVVMIntrRangeSM) {}
41  NVVMIntrRange(unsigned int SmVersion) : FunctionPass(ID) {
42  MaxBlockSize.x = 1024;
43  MaxBlockSize.y = 1024;
44  MaxBlockSize.z = 64;
45 
46  MaxGridSize.x = SmVersion >= 30 ? 0x7fffffff : 0xffff;
47  MaxGridSize.y = 0xffff;
48  MaxGridSize.z = 0xffff;
49 
51  }
52 
53  bool runOnFunction(Function &) override;
54 };
55 }
56 
57 FunctionPass *llvm::createNVVMIntrRangePass(unsigned int SmVersion) {
58  return new NVVMIntrRange(SmVersion);
59 }
60 
61 char NVVMIntrRange::ID = 0;
62 INITIALIZE_PASS(NVVMIntrRange, "nvvm-intr-range",
63  "Add !range metadata to NVVM intrinsics.", false, false)
64 
65 // Adds the passed-in [Low,High) range information as metadata to the
66 // passed-in call instruction.
67 static bool addRangeMetadata(uint64_t Low, uint64_t High, CallInst *C) {
68  // This call already has range metadata, nothing to do.
70  return false;
71 
77  C->setMetadata(LLVMContext::MD_range, MDNode::get(Context, LowAndHigh));
78  return true;
79 }
80 
81 bool NVVMIntrRange::runOnFunction(Function &F) {
82  // Go through the calls in this function.
83  bool Changed = false;
84  for (Instruction &I : instructions(F)) {
85  CallInst *Call = dyn_cast<CallInst>(&I);
86  if (!Call)
87  continue;
88 
89  if (Function *Callee = Call->getCalledFunction()) {
90  switch (Callee->getIntrinsicID()) {
91  // Index within block
92  case Intrinsic::nvvm_read_ptx_sreg_tid_x:
93  Changed |= addRangeMetadata(0, MaxBlockSize.x, Call);
94  break;
95  case Intrinsic::nvvm_read_ptx_sreg_tid_y:
96  Changed |= addRangeMetadata(0, MaxBlockSize.y, Call);
97  break;
98  case Intrinsic::nvvm_read_ptx_sreg_tid_z:
99  Changed |= addRangeMetadata(0, MaxBlockSize.z, Call);
100  break;
101 
102  // Block size
103  case Intrinsic::nvvm_read_ptx_sreg_ntid_x:
104  Changed |= addRangeMetadata(1, MaxBlockSize.x+1, Call);
105  break;
106  case Intrinsic::nvvm_read_ptx_sreg_ntid_y:
107  Changed |= addRangeMetadata(1, MaxBlockSize.y+1, Call);
108  break;
109  case Intrinsic::nvvm_read_ptx_sreg_ntid_z:
110  Changed |= addRangeMetadata(1, MaxBlockSize.z+1, Call);
111  break;
112 
113  // Index within grid
114  case Intrinsic::nvvm_read_ptx_sreg_ctaid_x:
115  Changed |= addRangeMetadata(0, MaxGridSize.x, Call);
116  break;
117  case Intrinsic::nvvm_read_ptx_sreg_ctaid_y:
118  Changed |= addRangeMetadata(0, MaxGridSize.y, Call);
119  break;
120  case Intrinsic::nvvm_read_ptx_sreg_ctaid_z:
121  Changed |= addRangeMetadata(0, MaxGridSize.z, Call);
122  break;
123 
124  // Grid size
125  case Intrinsic::nvvm_read_ptx_sreg_nctaid_x:
126  Changed |= addRangeMetadata(1, MaxGridSize.x+1, Call);
127  break;
128  case Intrinsic::nvvm_read_ptx_sreg_nctaid_y:
129  Changed |= addRangeMetadata(1, MaxGridSize.y+1, Call);
130  break;
131  case Intrinsic::nvvm_read_ptx_sreg_nctaid_z:
132  Changed |= addRangeMetadata(1, MaxGridSize.z+1, Call);
133  break;
134 
135  // warp size is constant 32.
136  case Intrinsic::nvvm_read_ptx_sreg_warpsize:
137  Changed |= addRangeMetadata(32, 32+1, Call);
138  break;
139 
140  // Lane ID is [0..warpsize)
141  case Intrinsic::nvvm_read_ptx_sreg_laneid:
142  Changed |= addRangeMetadata(0, 32, Call);
143  break;
144 
145  default:
146  break;
147  }
148  }
149  }
150 
151  return Changed;
152 }
uint64_t CallInst * C
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
LLVMContext & Context
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
This class represents a function call, abstracting a target machine&#39;s calling convention.
F(f)
LLVMContext & getContext() const
Get the context in which this basic block lives.
Definition: BasicBlock.cpp:33
uint64_t High
Metadata * LowAndHigh[]
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
Definition: Instruction.h:194
static ConstantAsMetadata * get(Constant *C)
Definition: Metadata.h:408
amdgpu Simplify well known AMD library false Value * Callee
void initializeNVVMIntrRangePass(PassRegistry &)
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata *> MDs)
Definition: Metadata.h:1164
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:406
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:69
INITIALIZE_PASS(NVVMIntrRange, "nvvm-intr-range", "Add !range metadata to NVVM intrinsics.", false, false) static bool addRangeMetadata(uint64_t Low
This file contains the declarations for the subclasses of Constant, which represent the different fla...
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:285
Class to represent integer types.
Definition: DerivedTypes.h:40
static cl::opt< unsigned > NVVMIntrRangeSM("nvvm-intr-range-sm", cl::init(20), cl::Hidden, cl::desc("SM variant"))
void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
Definition: Metadata.cpp:1214
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:560
Function * getCalledFunction() const
Return the function called, or null if this is an indirect function invocation.
FunctionPass * createNVVMIntrRangePass(unsigned int SmVersion)
static IntegerType * getInt32Ty(LLVMContext &C)
Definition: Type.cpp:176
#define I(x, y, z)
Definition: MD5.cpp:58
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:323
inst_range instructions(Function *F)
Definition: InstIterator.h:134
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:39
Root of the metadata hierarchy.
Definition: Metadata.h:58
IntegerType * Int32Ty
const BasicBlock * getParent() const
Definition: Instruction.h:66