1*9880d681SAndroid Build Coastguard Worker //===- NVVMIntrRange.cpp - Set !range metadata for NVVM intrinsics --------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This pass adds appropriate !range metadata for calls to NVVM
11*9880d681SAndroid Build Coastguard Worker // intrinsics that return a limited range of values.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker
15*9880d681SAndroid Build Coastguard Worker #include "NVPTX.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constants.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/InstIterator.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Intrinsics.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instructions.h"
20*9880d681SAndroid Build Coastguard Worker
21*9880d681SAndroid Build Coastguard Worker using namespace llvm;
22*9880d681SAndroid Build Coastguard Worker
23*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "nvvm-intr-range"
24*9880d681SAndroid Build Coastguard Worker
25*9880d681SAndroid Build Coastguard Worker namespace llvm { void initializeNVVMIntrRangePass(PassRegistry &); }
26*9880d681SAndroid Build Coastguard Worker
27*9880d681SAndroid Build Coastguard Worker // Add !range metadata based on limits of given SM variant.
28*9880d681SAndroid Build Coastguard Worker static cl::opt<unsigned> NVVMIntrRangeSM("nvvm-intr-range-sm", cl::init(20),
29*9880d681SAndroid Build Coastguard Worker cl::Hidden, cl::desc("SM variant"));
30*9880d681SAndroid Build Coastguard Worker
31*9880d681SAndroid Build Coastguard Worker namespace {
32*9880d681SAndroid Build Coastguard Worker class NVVMIntrRange : public FunctionPass {
33*9880d681SAndroid Build Coastguard Worker private:
34*9880d681SAndroid Build Coastguard Worker struct {
35*9880d681SAndroid Build Coastguard Worker unsigned x, y, z;
36*9880d681SAndroid Build Coastguard Worker } MaxBlockSize, MaxGridSize;
37*9880d681SAndroid Build Coastguard Worker
38*9880d681SAndroid Build Coastguard Worker public:
39*9880d681SAndroid Build Coastguard Worker static char ID;
NVVMIntrRange()40*9880d681SAndroid Build Coastguard Worker NVVMIntrRange() : NVVMIntrRange(NVVMIntrRangeSM) {}
NVVMIntrRange(unsigned int SmVersion)41*9880d681SAndroid Build Coastguard Worker NVVMIntrRange(unsigned int SmVersion) : FunctionPass(ID) {
42*9880d681SAndroid Build Coastguard Worker MaxBlockSize.x = 1024;
43*9880d681SAndroid Build Coastguard Worker MaxBlockSize.y = 1024;
44*9880d681SAndroid Build Coastguard Worker MaxBlockSize.z = 64;
45*9880d681SAndroid Build Coastguard Worker
46*9880d681SAndroid Build Coastguard Worker MaxGridSize.x = SmVersion >= 30 ? 0x7fffffff : 0xffff;
47*9880d681SAndroid Build Coastguard Worker MaxGridSize.y = 0xffff;
48*9880d681SAndroid Build Coastguard Worker MaxGridSize.z = 0xffff;
49*9880d681SAndroid Build Coastguard Worker
50*9880d681SAndroid Build Coastguard Worker initializeNVVMIntrRangePass(*PassRegistry::getPassRegistry());
51*9880d681SAndroid Build Coastguard Worker }
52*9880d681SAndroid Build Coastguard Worker
53*9880d681SAndroid Build Coastguard Worker bool runOnFunction(Function &) override;
54*9880d681SAndroid Build Coastguard Worker };
55*9880d681SAndroid Build Coastguard Worker }
56*9880d681SAndroid Build Coastguard Worker
createNVVMIntrRangePass(unsigned int SmVersion)57*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createNVVMIntrRangePass(unsigned int SmVersion) {
58*9880d681SAndroid Build Coastguard Worker return new NVVMIntrRange(SmVersion);
59*9880d681SAndroid Build Coastguard Worker }
60*9880d681SAndroid Build Coastguard Worker
61*9880d681SAndroid Build Coastguard Worker char NVVMIntrRange::ID = 0;
62*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(NVVMIntrRange, "nvvm-intr-range",
63*9880d681SAndroid Build Coastguard Worker "Add !range metadata to NVVM intrinsics.", false, false)
64*9880d681SAndroid Build Coastguard Worker
65*9880d681SAndroid Build Coastguard Worker // Adds the passed-in [Low,High) range information as metadata to the
66*9880d681SAndroid Build Coastguard Worker // passed-in call instruction.
addRangeMetadata(uint64_t Low,uint64_t High,CallInst * C)67*9880d681SAndroid Build Coastguard Worker static bool addRangeMetadata(uint64_t Low, uint64_t High, CallInst *C) {
68*9880d681SAndroid Build Coastguard Worker LLVMContext &Context = C->getParent()->getContext();
69*9880d681SAndroid Build Coastguard Worker IntegerType *Int32Ty = Type::getInt32Ty(Context);
70*9880d681SAndroid Build Coastguard Worker Metadata *LowAndHigh[] = {
71*9880d681SAndroid Build Coastguard Worker ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Low)),
72*9880d681SAndroid Build Coastguard Worker ConstantAsMetadata::get(ConstantInt::get(Int32Ty, High))};
73*9880d681SAndroid Build Coastguard Worker C->setMetadata(LLVMContext::MD_range, MDNode::get(Context, LowAndHigh));
74*9880d681SAndroid Build Coastguard Worker return true;
75*9880d681SAndroid Build Coastguard Worker }
76*9880d681SAndroid Build Coastguard Worker
runOnFunction(Function & F)77*9880d681SAndroid Build Coastguard Worker bool NVVMIntrRange::runOnFunction(Function &F) {
78*9880d681SAndroid Build Coastguard Worker // Go through the calls in this function.
79*9880d681SAndroid Build Coastguard Worker bool Changed = false;
80*9880d681SAndroid Build Coastguard Worker for (Instruction &I : instructions(F)) {
81*9880d681SAndroid Build Coastguard Worker CallInst *Call = dyn_cast<CallInst>(&I);
82*9880d681SAndroid Build Coastguard Worker if (!Call)
83*9880d681SAndroid Build Coastguard Worker continue;
84*9880d681SAndroid Build Coastguard Worker
85*9880d681SAndroid Build Coastguard Worker if (Function *Callee = Call->getCalledFunction()) {
86*9880d681SAndroid Build Coastguard Worker switch (Callee->getIntrinsicID()) {
87*9880d681SAndroid Build Coastguard Worker // Index within block
88*9880d681SAndroid Build Coastguard Worker case Intrinsic::nvvm_read_ptx_sreg_tid_x:
89*9880d681SAndroid Build Coastguard Worker Changed |= addRangeMetadata(0, MaxBlockSize.x, Call);
90*9880d681SAndroid Build Coastguard Worker break;
91*9880d681SAndroid Build Coastguard Worker case Intrinsic::nvvm_read_ptx_sreg_tid_y:
92*9880d681SAndroid Build Coastguard Worker Changed |= addRangeMetadata(0, MaxBlockSize.y, Call);
93*9880d681SAndroid Build Coastguard Worker break;
94*9880d681SAndroid Build Coastguard Worker case Intrinsic::nvvm_read_ptx_sreg_tid_z:
95*9880d681SAndroid Build Coastguard Worker Changed |= addRangeMetadata(0, MaxBlockSize.z, Call);
96*9880d681SAndroid Build Coastguard Worker break;
97*9880d681SAndroid Build Coastguard Worker
98*9880d681SAndroid Build Coastguard Worker // Block size
99*9880d681SAndroid Build Coastguard Worker case Intrinsic::nvvm_read_ptx_sreg_ntid_x:
100*9880d681SAndroid Build Coastguard Worker Changed |= addRangeMetadata(1, MaxBlockSize.x+1, Call);
101*9880d681SAndroid Build Coastguard Worker break;
102*9880d681SAndroid Build Coastguard Worker case Intrinsic::nvvm_read_ptx_sreg_ntid_y:
103*9880d681SAndroid Build Coastguard Worker Changed |= addRangeMetadata(1, MaxBlockSize.y+1, Call);
104*9880d681SAndroid Build Coastguard Worker break;
105*9880d681SAndroid Build Coastguard Worker case Intrinsic::nvvm_read_ptx_sreg_ntid_z:
106*9880d681SAndroid Build Coastguard Worker Changed |= addRangeMetadata(1, MaxBlockSize.z+1, Call);
107*9880d681SAndroid Build Coastguard Worker break;
108*9880d681SAndroid Build Coastguard Worker
109*9880d681SAndroid Build Coastguard Worker // Index within grid
110*9880d681SAndroid Build Coastguard Worker case Intrinsic::nvvm_read_ptx_sreg_ctaid_x:
111*9880d681SAndroid Build Coastguard Worker Changed |= addRangeMetadata(0, MaxGridSize.x, Call);
112*9880d681SAndroid Build Coastguard Worker break;
113*9880d681SAndroid Build Coastguard Worker case Intrinsic::nvvm_read_ptx_sreg_ctaid_y:
114*9880d681SAndroid Build Coastguard Worker Changed |= addRangeMetadata(0, MaxGridSize.y, Call);
115*9880d681SAndroid Build Coastguard Worker break;
116*9880d681SAndroid Build Coastguard Worker case Intrinsic::nvvm_read_ptx_sreg_ctaid_z:
117*9880d681SAndroid Build Coastguard Worker Changed |= addRangeMetadata(0, MaxGridSize.z, Call);
118*9880d681SAndroid Build Coastguard Worker break;
119*9880d681SAndroid Build Coastguard Worker
120*9880d681SAndroid Build Coastguard Worker // Grid size
121*9880d681SAndroid Build Coastguard Worker case Intrinsic::nvvm_read_ptx_sreg_nctaid_x:
122*9880d681SAndroid Build Coastguard Worker Changed |= addRangeMetadata(1, MaxGridSize.x+1, Call);
123*9880d681SAndroid Build Coastguard Worker break;
124*9880d681SAndroid Build Coastguard Worker case Intrinsic::nvvm_read_ptx_sreg_nctaid_y:
125*9880d681SAndroid Build Coastguard Worker Changed |= addRangeMetadata(1, MaxGridSize.y+1, Call);
126*9880d681SAndroid Build Coastguard Worker break;
127*9880d681SAndroid Build Coastguard Worker case Intrinsic::nvvm_read_ptx_sreg_nctaid_z:
128*9880d681SAndroid Build Coastguard Worker Changed |= addRangeMetadata(1, MaxGridSize.z+1, Call);
129*9880d681SAndroid Build Coastguard Worker break;
130*9880d681SAndroid Build Coastguard Worker
131*9880d681SAndroid Build Coastguard Worker // warp size is constant 32.
132*9880d681SAndroid Build Coastguard Worker case Intrinsic::nvvm_read_ptx_sreg_warpsize:
133*9880d681SAndroid Build Coastguard Worker Changed |= addRangeMetadata(32, 32+1, Call);
134*9880d681SAndroid Build Coastguard Worker break;
135*9880d681SAndroid Build Coastguard Worker
136*9880d681SAndroid Build Coastguard Worker // Lane ID is [0..warpsize)
137*9880d681SAndroid Build Coastguard Worker case Intrinsic::nvvm_read_ptx_sreg_laneid:
138*9880d681SAndroid Build Coastguard Worker Changed |= addRangeMetadata(0, 32, Call);
139*9880d681SAndroid Build Coastguard Worker break;
140*9880d681SAndroid Build Coastguard Worker
141*9880d681SAndroid Build Coastguard Worker default:
142*9880d681SAndroid Build Coastguard Worker break;
143*9880d681SAndroid Build Coastguard Worker }
144*9880d681SAndroid Build Coastguard Worker }
145*9880d681SAndroid Build Coastguard Worker }
146*9880d681SAndroid Build Coastguard Worker
147*9880d681SAndroid Build Coastguard Worker return Changed;
148*9880d681SAndroid Build Coastguard Worker }
149