Path: blob/main/contrib/llvm-project/llvm/lib/Target/DirectX/DXILResourceImplicitBinding.cpp
213799 views
//===- DXILResourceImplicitBinding.cpp -----------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "DXILResourceImplicitBinding.h"9#include "DirectX.h"10#include "llvm/ADT/APInt.h"11#include "llvm/ADT/STLExtras.h"12#include "llvm/Analysis/DXILResource.h"13#include "llvm/IR/Analysis.h"14#include "llvm/IR/Constants.h"15#include "llvm/IR/DiagnosticInfo.h"16#include "llvm/IR/Function.h"17#include "llvm/IR/IRBuilder.h"18#include "llvm/IR/Instructions.h"19#include "llvm/IR/IntrinsicsDirectX.h"20#include "llvm/IR/Module.h"21#include "llvm/InitializePasses.h"22#include <cstdint>2324#define DEBUG_TYPE "dxil-resource-implicit-binding"2526using namespace llvm;27using namespace llvm::dxil;2829namespace {3031static void diagnoseImplicitBindingNotFound(CallInst *ImplBindingCall) {32Function *F = ImplBindingCall->getFunction();33LLVMContext &Context = F->getParent()->getContext();34// FIXME: include the name of the resource in the error message35// (llvm/llvm-project#137868)36Context.diagnose(37DiagnosticInfoGenericWithLoc("resource cannot be allocated", *F,38ImplBindingCall->getDebugLoc(), DS_Error));39}4041static bool assignBindings(Module &M, DXILResourceBindingInfo &DRBI,42DXILResourceTypeMap &DRTM) {43struct ImplicitBindingCall {44int OrderID;45CallInst *Call;46ImplicitBindingCall(int OrderID, CallInst *Call)47: OrderID(OrderID), Call(Call) {}48};49SmallVector<ImplicitBindingCall> Calls;50SmallVector<Function *> FunctionsToMaybeRemove;5152// collect all of the llvm.dx.resource.handlefromImplicitbinding calls53for (Function &F : M.functions()) {54if (!F.isDeclaration())55continue;5657if (F.getIntrinsicID() != Intrinsic::dx_resource_handlefromimplicitbinding)58continue;5960for (User *U : F.users()) {61if (CallInst *CI = dyn_cast<CallInst>(U)) {62int OrderID = cast<ConstantInt>(CI->getArgOperand(0))->getZExtValue();63Calls.emplace_back(OrderID, CI);64}65}66FunctionsToMaybeRemove.emplace_back(&F);67}6869// sort all the collected implicit bindings by OrderID70llvm::stable_sort(71Calls, [](auto &LHS, auto &RHS) { return LHS.OrderID < RHS.OrderID; });7273// iterate over sorted calls, find binding for each new OrderID and replace74// each call with dx_resource_handlefrombinding using the new binding75int LastOrderID = -1;76llvm::TargetExtType *HandleTy = nullptr;77ConstantInt *RegSlotOp = nullptr;78bool AllBindingsAssigned = true;79bool Changed = false;8081for (ImplicitBindingCall &IB : Calls) {82IRBuilder<> Builder(IB.Call);8384if (IB.OrderID != LastOrderID) {85LastOrderID = IB.OrderID;86HandleTy = cast<TargetExtType>(IB.Call->getType());87ResourceTypeInfo &RTI = DRTM[HandleTy];8889uint32_t Space =90cast<ConstantInt>(IB.Call->getArgOperand(1))->getZExtValue();91int32_t Size =92cast<ConstantInt>(IB.Call->getArgOperand(2))->getZExtValue();9394std::optional<uint32_t> RegSlot =95DRBI.findAvailableBinding(RTI.getResourceClass(), Space, Size);96if (!RegSlot) {97diagnoseImplicitBindingNotFound(IB.Call);98AllBindingsAssigned = false;99continue;100}101RegSlotOp = ConstantInt::get(Builder.getInt32Ty(), RegSlot.value());102}103104if (!RegSlotOp)105continue;106107auto *NewCall = Builder.CreateIntrinsic(108HandleTy, Intrinsic::dx_resource_handlefrombinding,109{IB.Call->getOperand(1), /* space */110RegSlotOp, /* register slot */111IB.Call->getOperand(2), /* size */112IB.Call->getOperand(3), /* index */113IB.Call->getOperand(4), /* non-uniform flag */114IB.Call->getOperand(5)}); /* name */115IB.Call->replaceAllUsesWith(NewCall);116IB.Call->eraseFromParent();117Changed = true;118}119120for (Function *F : FunctionsToMaybeRemove) {121if (F->user_empty()) {122F->eraseFromParent();123Changed = true;124}125}126127DRBI.setHasImplicitBinding(!AllBindingsAssigned);128return Changed;129}130131} // end anonymous namespace132133PreservedAnalyses DXILResourceImplicitBinding::run(Module &M,134ModuleAnalysisManager &AM) {135136DXILResourceBindingInfo &DRBI = AM.getResult<DXILResourceBindingAnalysis>(M);137DXILResourceTypeMap &DRTM = AM.getResult<DXILResourceTypeAnalysis>(M);138139if (!DRBI.hasImplicitBinding())140return PreservedAnalyses::all();141142if (!assignBindings(M, DRBI, DRTM))143return PreservedAnalyses::all();144145PreservedAnalyses PA;146PA.preserve<DXILResourceBindingAnalysis>();147PA.preserve<DXILResourceTypeAnalysis>();148return PA;149}150151namespace {152153class DXILResourceImplicitBindingLegacy : public ModulePass {154public:155DXILResourceImplicitBindingLegacy() : ModulePass(ID) {}156157bool runOnModule(Module &M) override {158DXILResourceTypeMap &DRTM =159getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();160DXILResourceBindingInfo &DRBI =161getAnalysis<DXILResourceBindingWrapperPass>().getBindingInfo();162163if (DRBI.hasImplicitBinding())164return assignBindings(M, DRBI, DRTM);165return false;166}167168static char ID; // Pass identification.169void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {170AU.addRequired<DXILResourceTypeWrapperPass>();171AU.addRequired<DXILResourceBindingWrapperPass>();172AU.addPreserved<DXILResourceTypeWrapperPass>();173AU.addPreserved<DXILResourceBindingWrapperPass>();174}175};176177char DXILResourceImplicitBindingLegacy::ID = 0;178} // end anonymous namespace179180INITIALIZE_PASS_BEGIN(DXILResourceImplicitBindingLegacy, DEBUG_TYPE,181"DXIL Resource Implicit Binding", false, false)182INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass)183INITIALIZE_PASS_DEPENDENCY(DXILResourceBindingWrapperPass)184INITIALIZE_PASS_END(DXILResourceImplicitBindingLegacy, DEBUG_TYPE,185"DXIL Resource Implicit Binding", false, false)186187ModulePass *llvm::createDXILResourceImplicitBindingLegacyPass() {188return new DXILResourceImplicitBindingLegacy();189}190191192