LLVM 22.0.0git
HLSLBinding.cpp
Go to the documentation of this file.
1//===- HLSLBinding.cpp - Representation for resource bindings in HLSL -----===//
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
10#include "llvm/ADT/STLExtras.h"
11
12using namespace llvm;
13using namespace hlsl;
14
15std::optional<uint32_t>
17 int32_t Size) {
19 RegisterSpace &RS = BS.getOrInsertSpace(Space);
20 return RS.findAvailableBinding(Size);
21}
22
25 for (auto It = Spaces.begin(), End = Spaces.end(); It != End; ++It) {
26 if (It->Space == Space)
27 return *It;
28 if (It->Space < Space)
29 continue;
30 return *Spaces.insert(It, Space);
31 }
32 return Spaces.emplace_back(Space);
33}
34
35std::optional<uint32_t>
37 assert((Size == -1 || Size > 0) && "invalid size");
38
39 if (FreeRanges.empty())
40 return std::nullopt;
41
42 // unbounded array
43 if (Size == -1) {
44 BindingRange &Last = FreeRanges.back();
45 if (Last.UpperBound != ~0u)
46 // this space is already occupied by an unbounded array
47 return std::nullopt;
48 uint32_t RegSlot = Last.LowerBound;
49 FreeRanges.pop_back();
50 return RegSlot;
51 }
52
53 // single resource or fixed-size array
54 for (BindingRange &R : FreeRanges) {
55 // compare the size as uint64_t to prevent overflow for range (0, ~0u)
56 if ((uint64_t)R.UpperBound - R.LowerBound + 1 < (uint64_t)Size)
57 continue;
58 uint32_t RegSlot = R.LowerBound;
59 // This might create a range where (LowerBound == UpperBound + 1). When
60 // that happens, the next time this function is called the range will
61 // skipped over by the check above (at this point Size is always > 0).
62 R.LowerBound += Size;
63 return RegSlot;
64 }
65
66 return std::nullopt;
67}
68
70 llvm::function_ref<void(const BindingInfoBuilder &Builder,
71 const Binding &Overlapping)>
72 ReportOverlap) {
73 // sort all the collected bindings
74 llvm::stable_sort(Bindings);
75
76 // remove duplicates
77 Binding *NewEnd = llvm::unique(Bindings);
78 if (NewEnd != Bindings.end())
79 Bindings.erase(NewEnd, Bindings.end());
80
82
83 // Go over the sorted bindings and build up lists of free register ranges
84 // for each binding type and used spaces. Bindings are sorted by resource
85 // class, space, and lower bound register slot.
87 &Info.getBindingSpaces(dxil::ResourceClass::SRV);
88 for (const Binding &B : Bindings) {
89 if (BS->RC != B.RC)
90 // move to the next resource class spaces
91 BS = &Info.getBindingSpaces(B.RC);
92
93 BindingInfo::RegisterSpace *S = BS->Spaces.empty()
94 ? &BS->Spaces.emplace_back(B.Space)
95 : &BS->Spaces.back();
96 assert(S->Space <= B.Space && "bindings not sorted correctly?");
97 if (B.Space != S->Space)
98 // add new space
99 S = &BS->Spaces.emplace_back(B.Space);
100
101 // The space is full - there are no free slots left, or the rest of the
102 // slots are taken by an unbounded array. Report the overlapping to the
103 // caller.
104 if (S->FreeRanges.empty() || S->FreeRanges.back().UpperBound < ~0u) {
105 ReportOverlap(*this, B);
106 continue;
107 }
108 // adjust the last free range lower bound, split it in two, or remove it
109 BindingInfo::BindingRange &LastFreeRange = S->FreeRanges.back();
110 if (LastFreeRange.LowerBound == B.LowerBound) {
111 if (B.UpperBound < ~0u)
112 LastFreeRange.LowerBound = B.UpperBound + 1;
113 else
114 S->FreeRanges.pop_back();
115 } else if (LastFreeRange.LowerBound < B.LowerBound) {
116 LastFreeRange.UpperBound = B.LowerBound - 1;
117 if (B.UpperBound < ~0u)
118 S->FreeRanges.emplace_back(B.UpperBound + 1, ~0u);
119 } else {
120 // We don't have room here. Report the overlapping binding to the caller
121 // and mark any extra space this binding would use as unavailable.
122 ReportOverlap(*this, B);
123 if (B.UpperBound < ~0u)
124 LastFreeRange.LowerBound =
125 std::max(LastFreeRange.LowerBound, B.UpperBound + 1);
126 else
127 S->FreeRanges.pop_back();
128 }
129 }
130
131 return Info;
132}
133
134const Binding &
135BindingInfoBuilder::findOverlapping(const Binding &ReportedBinding) const {
136 for (const Binding &Other : Bindings)
137 if (ReportedBinding.LowerBound <= Other.UpperBound &&
138 Other.LowerBound <= ReportedBinding.UpperBound)
139 return Other;
140
141 llvm_unreachable("Searching for overlap for binding that does not overlap");
142}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
uint64_t Size
bool End
Definition: ELF_riscv.cpp:480
This file contains some templates that are useful if you are working with the STL at all.
An efficient, type-erasing, non-owning reference to a callable.
Builder class for creating a /c BindingInfo.
Definition: HLSLBinding.h:151
LLVM_ABI const Binding & findOverlapping(const Binding &ReportedBinding) const
For use in the ReportOverlap callback of calculateBindingInfo - finds a binding that the ReportedBind...
LLVM_ABI BindingInfo calculateBindingInfo(llvm::function_ref< void(const BindingInfoBuilder &Builder, const Binding &Overlapping)> ReportOverlap)
Calculate the binding info - ReportOverlap will be called once for each overlapping binding.
Definition: HLSLBinding.cpp:69
BindingInfo represents the ranges of bindings and free space for each dxil::ResourceClass.
Definition: HLSLBinding.h:46
LLVM_ABI std::optional< uint32_t > findAvailableBinding(dxil::ResourceClass RC, uint32_t Space, int32_t Size)
Definition: HLSLBinding.cpp:16
BindingSpaces & getBindingSpaces(dxil::ResourceClass RC)
Definition: HLSLBinding.h:78
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
ResourceClass
Definition: DXILABI.h:26
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void stable_sort(R &&Range)
Definition: STLExtras.h:2077
auto unique(Range &&R, Predicate P)
Definition: STLExtras.h:2095
@ Other
Any other memory.
LLVM_ABI RegisterSpace & getOrInsertSpace(uint32_t Space)
Definition: HLSLBinding.cpp:24
llvm::SmallVector< RegisterSpace > Spaces
Definition: HLSLBinding.h:66
SmallVector< BindingRange > FreeRanges
Definition: HLSLBinding.h:56
LLVM_ABI std::optional< uint32_t > findAvailableBinding(int32_t Size)
Definition: HLSLBinding.cpp:36