LLVM 22.0.0git
DXILResourceImplicitBinding.cpp
Go to the documentation of this file.
1//===- DXILResourceImplicitBinding.cpp -----------------------------------===//
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
10#include "DirectX.h"
11#include "llvm/ADT/APInt.h"
12#include "llvm/ADT/STLExtras.h"
14#include "llvm/IR/Analysis.h"
15#include "llvm/IR/Constants.h"
17#include "llvm/IR/Function.h"
18#include "llvm/IR/IRBuilder.h"
20#include "llvm/IR/IntrinsicsDirectX.h"
21#include "llvm/IR/Module.h"
23#include <cstdint>
24
25#define DEBUG_TYPE "dxil-resource-implicit-binding"
26
27using namespace llvm;
28using namespace llvm::dxil;
29
30namespace {
31
32static void diagnoseImplicitBindingNotFound(CallInst *ImplBindingCall) {
33 Function *F = ImplBindingCall->getFunction();
34 LLVMContext &Context = F->getParent()->getContext();
35 // FIXME: include the name of the resource in the error message
36 // (llvm/llvm-project#137868)
37 Context.diagnose(
38 DiagnosticInfoGenericWithLoc("resource cannot be allocated", *F,
39 ImplBindingCall->getDebugLoc(), DS_Error));
40}
41
42static bool assignBindings(Module &M, DXILResourceBindingInfo &DRBI,
43 DXILResourceTypeMap &DRTM) {
44 struct ImplicitBindingCall {
45 int OrderID;
46 CallInst *Call;
47 ImplicitBindingCall(int OrderID, CallInst *Call)
48 : OrderID(OrderID), Call(Call) {}
49 };
51 SmallVector<Function *> FunctionsToMaybeRemove;
52
53 // collect all of the llvm.dx.resource.handlefromImplicitbinding calls
54 for (Function &F : M.functions()) {
55 if (!F.isDeclaration())
56 continue;
57
58 if (F.getIntrinsicID() != Intrinsic::dx_resource_handlefromimplicitbinding)
59 continue;
60
61 for (User *U : F.users()) {
62 if (CallInst *CI = dyn_cast<CallInst>(U)) {
63 int OrderID = cast<ConstantInt>(CI->getArgOperand(0))->getZExtValue();
64 Calls.emplace_back(OrderID, CI);
65 }
66 }
67 FunctionsToMaybeRemove.emplace_back(&F);
68 }
69
70 // sort all the collected implicit bindings by OrderID
72 Calls, [](auto &LHS, auto &RHS) { return LHS.OrderID < RHS.OrderID; });
73
74 // iterate over sorted calls, find binding for each new OrderID and replace
75 // each call with dx_resource_handlefrombinding using the new binding
76 int LastOrderID = -1;
77 llvm::TargetExtType *HandleTy = nullptr;
78 ConstantInt *RegSlotOp = nullptr;
79 bool AllBindingsAssigned = true;
80 bool Changed = false;
81
82 for (ImplicitBindingCall &IB : Calls) {
83 IRBuilder<> Builder(IB.Call);
84
85 if (IB.OrderID != LastOrderID) {
86 LastOrderID = IB.OrderID;
87 HandleTy = cast<TargetExtType>(IB.Call->getType());
88 ResourceTypeInfo &RTI = DRTM[HandleTy];
89
90 uint32_t Space =
91 cast<ConstantInt>(IB.Call->getArgOperand(1))->getZExtValue();
92 int32_t Size =
93 cast<ConstantInt>(IB.Call->getArgOperand(2))->getZExtValue();
94
95 std::optional<uint32_t> RegSlot =
96 DRBI.findAvailableBinding(RTI.getResourceClass(), Space, Size);
97 if (!RegSlot) {
98 diagnoseImplicitBindingNotFound(IB.Call);
99 AllBindingsAssigned = false;
100 continue;
101 }
102 RegSlotOp = ConstantInt::get(Builder.getInt32Ty(), RegSlot.value());
103 }
104
105 if (!RegSlotOp)
106 continue;
107
108 auto *NewCall = Builder.CreateIntrinsic(
109 HandleTy, Intrinsic::dx_resource_handlefrombinding,
110 {IB.Call->getOperand(1), /* space */
111 RegSlotOp, /* register slot */
112 IB.Call->getOperand(2), /* size */
113 IB.Call->getOperand(3), /* index */
114 IB.Call->getOperand(4)}); /* name */
115 IB.Call->replaceAllUsesWith(NewCall);
116 IB.Call->eraseFromParent();
117 Changed = true;
118 }
119
120 for (Function *F : FunctionsToMaybeRemove) {
121 if (F->user_empty()) {
122 F->eraseFromParent();
123 Changed = true;
124 }
125 }
126
127 DRBI.setHasImplicitBinding(!AllBindingsAssigned);
128 return Changed;
129}
130
131} // end anonymous namespace
132
135
138
139 if (!DRBI.hasImplicitBinding())
140 return PreservedAnalyses::all();
141
142 if (!assignBindings(M, DRBI, DRTM))
143 return PreservedAnalyses::all();
144
148 return PA;
149}
150
151namespace {
152
153class DXILResourceImplicitBindingLegacy : public ModulePass {
154public:
155 DXILResourceImplicitBindingLegacy() : ModulePass(ID) {}
156
157 bool runOnModule(Module &M) override {
158 DXILResourceTypeMap &DRTM =
159 getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
161 getAnalysis<DXILResourceBindingWrapperPass>().getBindingInfo();
162
163 if (DRBI.hasImplicitBinding())
164 return assignBindings(M, DRBI, DRTM);
165 return false;
166 }
167
168 static char ID; // Pass identification.
169 void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
174 }
175};
176
177char DXILResourceImplicitBindingLegacy::ID = 0;
178} // end anonymous namespace
179
180INITIALIZE_PASS_BEGIN(DXILResourceImplicitBindingLegacy, DEBUG_TYPE,
181 "DXIL Resource Implicit Binding", false, false)
184INITIALIZE_PASS_END(DXILResourceImplicitBindingLegacy, DEBUG_TYPE,
185 "DXIL Resource Implicit Binding", false, false)
186
188 return new DXILResourceImplicitBindingLegacy();
189}
This file implements a class to represent arbitrary precision integral constant values and operations...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
uint64_t Size
#define DEBUG_TYPE
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition: MD5.cpp:55
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:39
This file contains some templates that are useful if you are working with the STL at all.
Value * RHS
Value * LHS
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:255
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:412
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
This class represents a function call, abstracting a target machine's calling convention.
This is the shared class of boolean and integer constants.
Definition: Constants.h:87
void setHasImplicitBinding(bool Value)
Definition: DXILResource.h:650
std::optional< uint32_t > findAvailableBinding(dxil::ResourceClass RC, uint32_t Space, int32_t Size)
Definition: DXILResource.h:654
PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Definition: IRBuilder.h:562
LLVM_ABI CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
Definition: IRBuilder.cpp:834
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2780
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
Definition: Instruction.h:513
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
Definition: Instruction.cpp:82
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:68
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:255
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:118
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Definition: Analysis.h:132
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:938
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
Class to represent target extensions types, which are generally unintrospectable from target-independ...
Definition: DerivedTypes.h:781
dxil::ResourceClass getResourceClass() const
Definition: DXILResource.h:324
Pass manager infrastructure for declaring and invalidating analyses.
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
void stable_sort(R &&Range)
Definition: STLExtras.h:2077
ModulePass * createDXILResourceImplicitBindingLegacyPass()
Pass to assign register slots to resources without binding.
@ DS_Error