xref: /aosp_15_r20/external/llvm/lib/Target/NVPTX/NVVMIntrRange.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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