LLVM 24.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
9#include "DirectX.h"
10#include "llvm/ADT/APInt.h"
11#include "llvm/ADT/STLExtras.h"
13#include "llvm/IR/Analysis.h"
14#include "llvm/IR/Constants.h"
16#include "llvm/IR/Function.h"
17#include "llvm/IR/IRBuilder.h"
19#include "llvm/IR/IntrinsicsDirectX.h"
20#include "llvm/IR/Module.h"
22#include <cstdint>
23
24#define DEBUG_TYPE "dxil-resource-implicit-binding"
25
26using namespace llvm;
27using namespace llvm::dxil;
28
29namespace {
30
31static void diagnoseImplicitBindingNotFound(CallInst *ImplBindingCall) {
32 Function *F = ImplBindingCall->getFunction();
33 LLVMContext &Context = F->getParent()->getContext();
34 // FIXME: include the name of the resource in the error message
35 // (llvm/llvm-project#137868)
36 Context.diagnose(
37 DiagnosticInfoGenericWithLoc("resource cannot be allocated", *F,
38 ImplBindingCall->getDebugLoc(), DS_Error));
39}
40
41static bool assignBindings(Module &M, DXILResourceBindingInfo &DRBI,
42 DXILResourceTypeMap &DRTM) {
43 struct ImplicitBindingCall {
44 int OrderID;
46 ImplicitBindingCall(int OrderID, CallInst *Call)
47 : OrderID(OrderID), Call(Call) {}
48 };
50 SmallVector<Function *> FunctionsToMaybeRemove;
51
52 // collect all of the llvm.dx.resource.handlefromImplicitbinding calls
53 for (Function &F : M.functions()) {
54 if (!F.isDeclaration())
55 continue;
56
57 if (F.getIntrinsicID() != Intrinsic::dx_resource_handlefromimplicitbinding)
58 continue;
59
60 for (User *U : F.users()) {
61 if (CallInst *CI = dyn_cast<CallInst>(U)) {
62 int OrderID = cast<ConstantInt>(CI->getArgOperand(0))->getZExtValue();
63 Calls.emplace_back(OrderID, CI);
64 }
65 }
66 FunctionsToMaybeRemove.emplace_back(&F);
67 }
68
69 // sort all the collected implicit bindings by OrderID
71 Calls, [](auto &LHS, auto &RHS) { return LHS.OrderID < RHS.OrderID; });
72
73 // iterate over sorted calls, find binding for each new OrderID and replace
74 // each call with dx_resource_handlefrombinding using the new binding
75 int LastOrderID = -1;
76 llvm::TargetExtType *HandleTy = nullptr;
77 ConstantInt *RegSlotOp = nullptr;
78 bool AllBindingsAssigned = true;
79 bool Changed = false;
80
81 for (ImplicitBindingCall &IB : Calls) {
82 IRBuilder<> Builder(IB.Call);
83
84 if (IB.OrderID != LastOrderID) {
85 LastOrderID = IB.OrderID;
86 HandleTy = cast<TargetExtType>(IB.Call->getType());
87 ResourceTypeInfo &RTI = DRTM[HandleTy];
88
89 uint32_t Space =
90 cast<ConstantInt>(IB.Call->getArgOperand(1))->getZExtValue();
91 int32_t Size =
92 cast<ConstantInt>(IB.Call->getArgOperand(2))->getZExtValue();
93
94 std::optional<uint32_t> RegSlot =
95 DRBI.findAvailableBinding(RTI.getResourceClass(), Space, Size);
96 if (!RegSlot) {
97 diagnoseImplicitBindingNotFound(IB.Call);
98 AllBindingsAssigned = false;
99 continue;
100 }
101 RegSlotOp = ConstantInt::get(Builder.getInt32Ty(), RegSlot.value());
102 }
103
104 if (!RegSlotOp)
105 continue;
106
107 auto *NewCall = Builder.CreateIntrinsic(
108 HandleTy, Intrinsic::dx_resource_handlefrombinding,
109 {IB.Call->getOperand(1), /* space */
110 RegSlotOp, /* register slot */
111 IB.Call->getOperand(2), /* size */
112 IB.Call->getOperand(3), /* index */
113 IB.Call->getOperand(4)}); /* name */
114 IB.Call->replaceAllUsesWith(NewCall);
115 IB.Call->eraseFromParent();
116 Changed = true;
117 }
118
119 for (Function *F : FunctionsToMaybeRemove) {
120 if (F->user_empty()) {
121 F->eraseFromParent();
122 Changed = true;
123 }
124 }
125
126 DRBI.setHasImplicitBinding(!AllBindingsAssigned);
127 return Changed;
128}
129
130} // end anonymous namespace
131
134
137
138 if (!DRBI.hasImplicitBinding())
139 return PreservedAnalyses::all();
140
141 if (!assignBindings(M, DRBI, DRTM))
142 return PreservedAnalyses::all();
143
147 return PA;
148}
149
150namespace {
151
152class DXILResourceImplicitBindingLegacy : public ModulePass {
153public:
154 DXILResourceImplicitBindingLegacy() : ModulePass(ID) {}
155
156 bool runOnModule(Module &M) override {
157 DXILResourceTypeMap &DRTM =
158 getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
160 getAnalysis<DXILResourceBindingWrapperPass>().getBindingInfo();
161
162 if (DRBI.hasImplicitBinding())
163 return assignBindings(M, DRBI, DRTM);
164 return false;
165 }
166
167 static char ID; // Pass identification.
168 void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
169 AU.addRequired<DXILResourceTypeWrapperPass>();
170 AU.addRequired<DXILResourceBindingWrapperPass>();
171 AU.addPreserved<DXILResourceTypeWrapperPass>();
172 AU.addPreserved<DXILResourceBindingWrapperPass>();
173 }
174};
175
176char DXILResourceImplicitBindingLegacy::ID = 0;
177} // end anonymous namespace
178
179INITIALIZE_PASS_BEGIN(DXILResourceImplicitBindingLegacy, DEBUG_TYPE,
180 "DXIL Resource Implicit Binding", false, false)
183INITIALIZE_PASS_END(DXILResourceImplicitBindingLegacy, DEBUG_TYPE,
184 "DXIL Resource Implicit Binding", false, false)
185
187 return new DXILResourceImplicitBindingLegacy();
188}
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...
#define DEBUG_TYPE
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition MD5.cpp:54
#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
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
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)
std::optional< uint32_t > findAvailableBinding(dxil::ResourceClass RC, uint32_t Space, int32_t Size)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2947
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:76
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:253
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
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)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Class to represent target extensions types, which are generally unintrospectable from target-independ...
dxil::ResourceClass getResourceClass() const
CallInst * Call
Pass manager infrastructure for declaring and invalidating analyses.
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
Definition STLExtras.h:2132
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
ModulePass * createDXILResourceImplicitBindingLegacyPass()
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39