[llvm] [DirectX] Implement DXILResourceBindingAnalysis (PR #137258)
Helena Kotas via llvm-commits
llvm-commits at lists.llvm.org
Thu May 8 23:10:52 PDT 2025
================
@@ -879,8 +883,122 @@ SmallVector<dxil::ResourceInfo *> DXILResourceMap::findByUse(const Value *Key) {
//===----------------------------------------------------------------------===//
+void DXILResourceBindingInfo::populate(Module &M, DXILResourceTypeMap &DRTM) {
+ struct Binding {
+ ResourceClass ResClass;
+ uint32_t Space;
+ uint32_t LowerBound;
+ uint32_t UpperBound;
+ Binding(ResourceClass RC, uint32_t Sp, uint32_t LB, uint32_t UB)
+ : ResClass(RC), Space(Sp), LowerBound(LB), UpperBound(UB) {}
+ };
+ SmallVector<Binding> Bindings;
+
+ // collect all of the llvm.dx.resource.handlefrombinding calls;
+ // make a note if there is llvm.dx.resource.handlefromimplicitbinding
+ for (Function &F : M.functions()) {
+ if (!F.isDeclaration())
+ continue;
+
+ switch (F.getIntrinsicID()) {
+ default:
+ continue;
+ case Intrinsic::dx_resource_handlefrombinding: {
+ auto *HandleTy = cast<TargetExtType>(F.getReturnType());
+ ResourceTypeInfo &RTI = DRTM[HandleTy];
+
+ for (User *U : F.users())
+ if (CallInst *CI = dyn_cast<CallInst>(U)) {
+ uint32_t Space =
+ cast<ConstantInt>(CI->getArgOperand(0))->getZExtValue();
+ uint32_t LowerBound =
+ cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
+ int32_t Size =
+ cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
+
+ // negative size means unbounded resource array;
+ // upper bound register overflow should be detected in Sema
+ assert((Size < 0 || (unsigned)LowerBound + Size - 1 <= UINT32_MAX) &&
+ "upper bound register overflow");
+ uint32_t UpperBound = Size < 0 ? UINT32_MAX : LowerBound + Size - 1;
+ Bindings.emplace_back(RTI.getResourceClass(), Space, LowerBound,
+ UpperBound);
+ }
+ break;
+ }
+ case Intrinsic::dx_resource_handlefromimplicitbinding: {
+ ImplicitBinding = true;
+ break;
+ }
+ }
+ }
+
+ // sort all the collected bindings
+ llvm::stable_sort(Bindings, [](auto &LHS, auto &RHS) {
+ return std::tie(LHS.ResClass, LHS.Space, LHS.LowerBound) <
+ std::tie(RHS.ResClass, RHS.Space, RHS.LowerBound);
+ });
+
+ // remove duplicates
+ llvm::unique(Bindings, [](auto &LHS, auto &RHS) {
+ return std::tie(LHS.ResClass, LHS.Space, LHS.LowerBound, LHS.UpperBound) ==
+ std::tie(RHS.ResClass, RHS.Space, RHS.LowerBound, RHS.UpperBound);
+ });
+
+ // Go over the sorted bindings and build up lists of free register ranges
+ // for each binding type and used spaces. Bindings are sorted by resource
+ // class, space, and lower bound register slot.
+ BindingSpaces *BS = &SRVSpaces;
+ for (unsigned I = 0, E = Bindings.size(); I != E; ++I) {
+ Binding &B = Bindings[I];
+
+ if (BS->ResClass != B.ResClass)
+ // move to the next resource class spaces
+ BS = &getBindingSpaces(B.ResClass);
+
+ RegisterSpace *S = BS->Spaces.empty() ? &BS->Spaces.emplace_back(B.Space)
+ : &BS->Spaces.back();
+ assert(S->Space <= B.Space && "bindings not sorted correctly?");
+ if (B.Space != S->Space)
+ // add new space
+ S = &BS->Spaces.emplace_back(B.Space);
+
+ // the space is full - set flag to report overlapping binding later
+ if (S->FreeRanges.empty()) {
+ OverlappingBinding = true;
----------------
hekota wrote:
Actually, for resources with explicit binding the error message is always the same, and the analysis only maps space occupied by explicit bindings: https://godbolt.org/z/eGsfcEG35
The error message `resource A could not be allocated` is going to be raised during `DXILResourceImplicitBinding` pass when it cannot find a space for a resource.
https://github.com/llvm/llvm-project/pull/137258
More information about the llvm-commits
mailing list