22#include "llvm/IR/IntrinsicsSPIRV.h"
31class SPIRVLegalizeImplicitBinding :
public ModulePass {
34 SPIRVLegalizeImplicitBinding() : ModulePass(ID) {}
36 bool runOnModule(
Module &M)
override;
39 void collectBindingInfo(
Module &M);
40 uint32_t getAndReserveFirstUnusedBinding(uint32_t DescSet);
41 void replaceImplicitBindingCalls(
Module &M);
44 std::vector<BitVector> UsedBindings;
49struct BindingInfoCollector :
public InstVisitor<BindingInfoCollector> {
50 std::vector<BitVector> &UsedBindings;
53 BindingInfoCollector(std::vector<BitVector> &UsedBindings,
55 : UsedBindings(UsedBindings), ImplicitBindingCalls(ImplicitBindingCalls) {
58 void visitCallInst(CallInst &CI) {
59 if (CI.
getIntrinsicID() == Intrinsic::spv_resource_handlefrombinding) {
60 const uint32_t DescSet =
65 if (UsedBindings.size() <= DescSet) {
66 UsedBindings.resize(DescSet + 1);
67 UsedBindings[DescSet].resize(64);
70 UsedBindings[DescSet].resize(2 *
Binding + 1);
72 UsedBindings[DescSet].set(
Binding);
74 Intrinsic::spv_resource_handlefromimplicitbinding) {
75 ImplicitBindingCalls.push_back(&CI);
80void SPIRVLegalizeImplicitBinding::collectBindingInfo(
Module &M) {
81 BindingInfoCollector InfoCollector(UsedBindings, ImplicitBindingCalls);
82 InfoCollector.visit(M);
86 ImplicitBindingCalls.
begin(), ImplicitBindingCalls.
end(),
87 [](
const CallInst *
A,
const CallInst *
B) {
88 const uint32_t OrderIdArgIdx = 0;
89 const uint32_t OrderA =
90 cast<ConstantInt>(A->getArgOperand(OrderIdArgIdx))->getZExtValue();
91 const uint32_t OrderB =
92 cast<ConstantInt>(B->getArgOperand(OrderIdArgIdx))->getZExtValue();
93 return OrderA < OrderB;
97uint32_t SPIRVLegalizeImplicitBinding::getAndReserveFirstUnusedBinding(
99 if (UsedBindings.size() <= DescSet) {
100 UsedBindings.resize(DescSet + 1);
101 UsedBindings[DescSet].resize(64);
104 int NewBinding = UsedBindings[DescSet].find_first_unset();
105 if (NewBinding == -1) {
106 NewBinding = UsedBindings[DescSet].size();
107 UsedBindings[DescSet].resize(2 * NewBinding + 1);
110 UsedBindings[DescSet].set(NewBinding);
114void SPIRVLegalizeImplicitBinding::replaceImplicitBindingCalls(
Module &M) {
115 for (CallInst *OldCI : ImplicitBindingCalls) {
117 const uint32_t DescSet =
119 const uint32_t NewBinding = getAndReserveFirstUnusedBinding(DescSet);
121 SmallVector<Value *, 8>
Args;
122 Args.push_back(Builder.getInt32(DescSet));
123 Args.push_back(Builder.getInt32(NewBinding));
126 for (uint32_t i = 2; i < OldCI->arg_size(); ++i) {
127 Args.push_back(OldCI->getArgOperand(i));
131 &M, Intrinsic::spv_resource_handlefrombinding, OldCI->getType());
132 CallInst *NewCI = Builder.CreateCall(NewFunc, Args);
135 OldCI->replaceAllUsesWith(NewCI);
136 OldCI->eraseFromParent();
140bool SPIRVLegalizeImplicitBinding::runOnModule(
Module &M) {
141 collectBindingInfo(M);
142 if (ImplicitBindingCalls.empty()) {
146 replaceImplicitBindingCalls(M);
151char SPIRVLegalizeImplicitBinding::ID = 0;
154 "Legalize SPIR-V implicit bindings",
false,
false)
157 return new SPIRVLegalizeImplicitBinding();
This file implements the BitVector class.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
DXIL Resource Implicit Binding
Module.h This file contains the declarations for the Module class.
Machine Check Debug Module
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file defines the SmallVector class.
void setCallingConv(CallingConv::ID CC)
Value * getArgOperand(unsigned i) const
LLVM_ABI Intrinsic::ID getIntrinsicID() const
Returns the intrinsic ID of the intrinsic called or Intrinsic::not_intrinsic if the called function i...
Base class for instruction visitors.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
A Module instance is used to store all the information related to an LLVM module.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
ModulePass * createSPIRVLegalizeImplicitBindingPass()