brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.1 KiB · b0d9ad8 Raw
190 lines · cpp
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-exception6//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 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 message36  // (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  };50  SmallVector<ImplicitBindingCall> Calls;51  SmallVector<Function *> FunctionsToMaybeRemove;52 53  // collect all of the llvm.dx.resource.handlefromImplicitbinding calls54  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 OrderID71  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 replace75  // each call with dx_resource_handlefrombinding using the new binding76  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 namespace132 133PreservedAnalyses DXILResourceImplicitBinding::run(Module &M,134                                                   ModuleAnalysisManager &AM) {135 136  DXILResourceBindingInfo &DRBI = AM.getResult<DXILResourceBindingAnalysis>(M);137  DXILResourceTypeMap &DRTM = AM.getResult<DXILResourceTypeAnalysis>(M);138 139  if (!DRBI.hasImplicitBinding())140    return PreservedAnalyses::all();141 142  if (!assignBindings(M, DRBI, DRTM))143    return PreservedAnalyses::all();144 145  PreservedAnalyses PA;146  PA.preserve<DXILResourceBindingAnalysis>();147  PA.preserve<DXILResourceTypeAnalysis>();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();160    DXILResourceBindingInfo &DRBI =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 {170    AU.addRequired<DXILResourceTypeWrapperPass>();171    AU.addRequired<DXILResourceBindingWrapperPass>();172    AU.addPreserved<DXILResourceTypeWrapperPass>();173    AU.addPreserved<DXILResourceBindingWrapperPass>();174  }175};176 177char DXILResourceImplicitBindingLegacy::ID = 0;178} // end anonymous namespace179 180INITIALIZE_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)186 187ModulePass *llvm::createDXILResourceImplicitBindingLegacyPass() {188  return new DXILResourceImplicitBindingLegacy();189}190