Home | History | Annotate | Download | only in NVPTX
      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 
     50      initializeNVVMIntrRangePass(*PassRegistry::getPassRegistry());
     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.
     69   if (C->getMetadata(LLVMContext::MD_range))
     70     return false;
     71 
     72   LLVMContext &Context = C->getParent()->getContext();
     73   IntegerType *Int32Ty = Type::getInt32Ty(Context);
     74   Metadata *LowAndHigh[] = {
     75       ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Low)),
     76       ConstantAsMetadata::get(ConstantInt::get(Int32Ty, High))};
     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 }
    153