Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/DirectX/DXILResourceImplicitBinding.cpp
213799 views
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 "DXILResourceImplicitBinding.h"
10
#include "DirectX.h"
11
#include "llvm/ADT/APInt.h"
12
#include "llvm/ADT/STLExtras.h"
13
#include "llvm/Analysis/DXILResource.h"
14
#include "llvm/IR/Analysis.h"
15
#include "llvm/IR/Constants.h"
16
#include "llvm/IR/DiagnosticInfo.h"
17
#include "llvm/IR/Function.h"
18
#include "llvm/IR/IRBuilder.h"
19
#include "llvm/IR/Instructions.h"
20
#include "llvm/IR/IntrinsicsDirectX.h"
21
#include "llvm/IR/Module.h"
22
#include "llvm/InitializePasses.h"
23
#include <cstdint>
24
25
#define DEBUG_TYPE "dxil-resource-implicit-binding"
26
27
using namespace llvm;
28
using namespace llvm::dxil;
29
30
namespace {
31
32
static 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
42
static 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
};
50
SmallVector<ImplicitBindingCall> Calls;
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
71
llvm::stable_sort(
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), /* non-uniform flag */
115
IB.Call->getOperand(5)}); /* name */
116
IB.Call->replaceAllUsesWith(NewCall);
117
IB.Call->eraseFromParent();
118
Changed = true;
119
}
120
121
for (Function *F : FunctionsToMaybeRemove) {
122
if (F->user_empty()) {
123
F->eraseFromParent();
124
Changed = true;
125
}
126
}
127
128
DRBI.setHasImplicitBinding(!AllBindingsAssigned);
129
return Changed;
130
}
131
132
} // end anonymous namespace
133
134
PreservedAnalyses DXILResourceImplicitBinding::run(Module &M,
135
ModuleAnalysisManager &AM) {
136
137
DXILResourceBindingInfo &DRBI = AM.getResult<DXILResourceBindingAnalysis>(M);
138
DXILResourceTypeMap &DRTM = AM.getResult<DXILResourceTypeAnalysis>(M);
139
140
if (!DRBI.hasImplicitBinding())
141
return PreservedAnalyses::all();
142
143
if (!assignBindings(M, DRBI, DRTM))
144
return PreservedAnalyses::all();
145
146
PreservedAnalyses PA;
147
PA.preserve<DXILResourceBindingAnalysis>();
148
PA.preserve<DXILResourceTypeAnalysis>();
149
return PA;
150
}
151
152
namespace {
153
154
class DXILResourceImplicitBindingLegacy : public ModulePass {
155
public:
156
DXILResourceImplicitBindingLegacy() : ModulePass(ID) {}
157
158
bool runOnModule(Module &M) override {
159
DXILResourceTypeMap &DRTM =
160
getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
161
DXILResourceBindingInfo &DRBI =
162
getAnalysis<DXILResourceBindingWrapperPass>().getBindingInfo();
163
164
if (DRBI.hasImplicitBinding())
165
return assignBindings(M, DRBI, DRTM);
166
return false;
167
}
168
169
static char ID; // Pass identification.
170
void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
171
AU.addRequired<DXILResourceTypeWrapperPass>();
172
AU.addRequired<DXILResourceBindingWrapperPass>();
173
AU.addPreserved<DXILResourceTypeWrapperPass>();
174
AU.addPreserved<DXILResourceBindingWrapperPass>();
175
}
176
};
177
178
char DXILResourceImplicitBindingLegacy::ID = 0;
179
} // end anonymous namespace
180
181
INITIALIZE_PASS_BEGIN(DXILResourceImplicitBindingLegacy, DEBUG_TYPE,
182
"DXIL Resource Implicit Binding", false, false)
183
INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass)
184
INITIALIZE_PASS_DEPENDENCY(DXILResourceBindingWrapperPass)
185
INITIALIZE_PASS_END(DXILResourceImplicitBindingLegacy, DEBUG_TYPE,
186
"DXIL Resource Implicit Binding", false, false)
187
188
ModulePass *llvm::createDXILResourceImplicitBindingLegacyPass() {
189
return new DXILResourceImplicitBindingLegacy();
190
}
191
192