LLVM 20.0.0git
NVVMIntrRange.cpp
Go to the documentation of this file.
1//===- NVVMIntrRange.cpp - Set range attributes for NVVM intrinsics -------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This pass adds appropriate range attributes for calls to NVVM
10// intrinsics that return a limited range of values.
11//
12//===----------------------------------------------------------------------===//
13
14#include "NVPTX.h"
15#include "NVPTXUtilities.h"
19#include "llvm/IR/Intrinsics.h"
20#include "llvm/IR/IntrinsicsNVPTX.h"
21#include "llvm/IR/PassManager.h"
22#include <cstdint>
23
24using namespace llvm;
25
26#define DEBUG_TYPE "nvvm-intr-range"
27
29
30namespace {
31class NVVMIntrRange : public FunctionPass {
32public:
33 static char ID;
34 NVVMIntrRange() : FunctionPass(ID) {
35
37 }
38
39 bool runOnFunction(Function &) override;
40};
41} // namespace
42
43FunctionPass *llvm::createNVVMIntrRangePass() { return new NVVMIntrRange(); }
44
45char NVVMIntrRange::ID = 0;
46INITIALIZE_PASS(NVVMIntrRange, "nvvm-intr-range",
47 "Add !range metadata to NVVM intrinsics.", false, false)
48
49// Adds the passed-in [Low,High) range information as metadata to the
50// passed-in call instruction.
51static bool addRangeAttr(uint64_t Low, uint64_t High, IntrinsicInst *II) {
52 if (II->getMetadata(LLVMContext::MD_range))
53 return false;
54
55 const uint64_t BitWidth = II->getType()->getIntegerBitWidth();
57
58 if (auto CurrentRange = II->getRange())
59 Range = Range.intersectWith(CurrentRange.value());
60
61 II->addRangeRetAttr(Range);
62 return true;
63}
64
66 struct {
67 unsigned x, y, z;
68 } MaxBlockSize, MaxGridSize;
69
70 const unsigned MetadataNTID = getReqNTID(F).value_or(
71 getMaxNTID(F).value_or(std::numeric_limits<unsigned>::max()));
72
73 MaxBlockSize.x = std::min(1024u, MetadataNTID);
74 MaxBlockSize.y = std::min(1024u, MetadataNTID);
75 MaxBlockSize.z = std::min(64u, MetadataNTID);
76
77 MaxGridSize.x = 0x7fffffff;
78 MaxGridSize.y = 0xffff;
79 MaxGridSize.z = 0xffff;
80
81 // Go through the calls in this function.
82 bool Changed = false;
83 for (Instruction &I : instructions(F)) {
84 IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I);
85 if (!II)
86 continue;
87
88 switch (II->getIntrinsicID()) {
89 // Index within block
90 case Intrinsic::nvvm_read_ptx_sreg_tid_x:
91 Changed |= addRangeAttr(0, MaxBlockSize.x, II);
92 break;
93 case Intrinsic::nvvm_read_ptx_sreg_tid_y:
94 Changed |= addRangeAttr(0, MaxBlockSize.y, II);
95 break;
96 case Intrinsic::nvvm_read_ptx_sreg_tid_z:
97 Changed |= addRangeAttr(0, MaxBlockSize.z, II);
98 break;
99
100 // Block size
101 case Intrinsic::nvvm_read_ptx_sreg_ntid_x:
102 Changed |= addRangeAttr(1, MaxBlockSize.x + 1, II);
103 break;
104 case Intrinsic::nvvm_read_ptx_sreg_ntid_y:
105 Changed |= addRangeAttr(1, MaxBlockSize.y + 1, II);
106 break;
107 case Intrinsic::nvvm_read_ptx_sreg_ntid_z:
108 Changed |= addRangeAttr(1, MaxBlockSize.z + 1, II);
109 break;
110
111 // Index within grid
112 case Intrinsic::nvvm_read_ptx_sreg_ctaid_x:
113 Changed |= addRangeAttr(0, MaxGridSize.x, II);
114 break;
115 case Intrinsic::nvvm_read_ptx_sreg_ctaid_y:
116 Changed |= addRangeAttr(0, MaxGridSize.y, II);
117 break;
118 case Intrinsic::nvvm_read_ptx_sreg_ctaid_z:
119 Changed |= addRangeAttr(0, MaxGridSize.z, II);
120 break;
121
122 // Grid size
123 case Intrinsic::nvvm_read_ptx_sreg_nctaid_x:
124 Changed |= addRangeAttr(1, MaxGridSize.x + 1, II);
125 break;
126 case Intrinsic::nvvm_read_ptx_sreg_nctaid_y:
127 Changed |= addRangeAttr(1, MaxGridSize.y + 1, II);
128 break;
129 case Intrinsic::nvvm_read_ptx_sreg_nctaid_z:
130 Changed |= addRangeAttr(1, MaxGridSize.z + 1, II);
131 break;
132
133 // warp size is constant 32.
134 case Intrinsic::nvvm_read_ptx_sreg_warpsize:
135 Changed |= addRangeAttr(32, 32 + 1, II);
136 break;
137
138 // Lane ID is [0..warpsize)
139 case Intrinsic::nvvm_read_ptx_sreg_laneid:
140 Changed |= addRangeAttr(0, 32, II);
141 break;
142
143 default:
144 break;
145 }
146 }
147
148 return Changed;
149}
150
151bool NVVMIntrRange::runOnFunction(Function &F) { return runNVVMIntrRange(F); }
152
157}
Expand Atomic instructions
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
const uint64_t BitWidth
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t High
static bool runNVVMIntrRange(Function &F)
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
Class for arbitrary precision integers.
Definition: APInt.h:78
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:253
This class represents a range of values.
Definition: ConstantRange.h:47
ConstantRange intersectWith(const ConstantRange &CR, PreferredRangeType Type=Smallest) const
Return the range that results from the intersection of this range with another range.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
A wrapper class for inspecting calls to intrinsic functions.
Definition: IntrinsicInst.h:48
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:37
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:111
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: Analysis.h:114
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:117
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
void initializeNVVMIntrRangePass(PassRegistry &)
FunctionPass * createNVVMIntrRangePass()
std::optional< unsigned > getReqNTID(const Function &F)
std::optional< unsigned > getMaxNTID(const Function &F)
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)