Skip to content

Commit a8f04ab

Browse files
committed
nfc: move resource range analysis to RootSignatureValidations library
1 parent 586502c commit a8f04ab

File tree

7 files changed

+179
-131
lines changed

7 files changed

+179
-131
lines changed

clang/lib/Sema/SemaHLSL.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
#include "llvm/ADT/StringExtras.h"
4040
#include "llvm/ADT/StringRef.h"
4141
#include "llvm/ADT/Twine.h"
42-
#include "llvm/Frontend/HLSL/HLSLRootSignature.h"
42+
#include "llvm/Frontend/HLSL/RootSignatureValidations.h"
4343
#include "llvm/Support/Casting.h"
4444
#include "llvm/Support/DXILABI.h"
4545
#include "llvm/Support/ErrorHandling.h"

llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h

Lines changed: 0 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#ifndef LLVM_FRONTEND_HLSL_HLSLROOTSIGNATURE_H
1515
#define LLVM_FRONTEND_HLSL_HLSLROOTSIGNATURE_H
1616

17-
#include "llvm/ADT/IntervalMap.h"
1817
#include "llvm/BinaryFormat/DXContainer.h"
1918
#include "llvm/Support/Compiler.h"
2019
#include "llvm/Support/DXILABI.h"
@@ -152,71 +151,6 @@ LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, const RootElement &Element);
152151

153152
LLVM_ABI void dumpRootElements(raw_ostream &OS, ArrayRef<RootElement> Elements);
154153

155-
/// The following contains the validation interface of root elements
156-
struct RangeInfo {
157-
const static uint32_t Unbounded = ~0u;
158-
159-
// Interval information
160-
uint32_t LowerBound;
161-
uint32_t UpperBound;
162-
163-
// Information retained for diagnostics
164-
llvm::dxil::ResourceClass Class;
165-
uint32_t Space;
166-
llvm::dxbc::ShaderVisibility Visibility;
167-
};
168-
169-
class ResourceRange {
170-
public:
171-
using MapT = llvm::IntervalMap<uint32_t, const RangeInfo *, 16,
172-
llvm::IntervalMapInfo<uint32_t>>;
173-
174-
private:
175-
MapT Intervals;
176-
177-
public:
178-
ResourceRange(MapT::Allocator &Allocator) : Intervals(MapT(Allocator)) {}
179-
180-
// Returns a reference to the first RangeInfo that overlaps with
181-
// [Info.LowerBound;Info.UpperBound], or, std::nullopt if there is no overlap
182-
LLVM_ABI std::optional<const RangeInfo *>
183-
getOverlapping(const RangeInfo &Info) const;
184-
185-
// Return the mapped RangeInfo at X or nullptr if no mapping exists
186-
const RangeInfo *lookup(uint32_t X) const;
187-
188-
// Removes all entries of the ResourceRange
189-
LLVM_ABI void clear();
190-
191-
// Insert the required (sub-)intervals such that the interval of [a;b] =
192-
// [Info.LowerBound, Info.UpperBound] is covered and points to a valid
193-
// RangeInfo &.
194-
//
195-
// For instance consider the following chain of inserting RangeInfos with the
196-
// intervals denoting the Lower/Upper-bounds:
197-
//
198-
// A = [0;2]
199-
// insert(A) -> false
200-
// intervals: [0;2] -> &A
201-
// B = [5;7]
202-
// insert(B) -> false
203-
// intervals: [0;2] -> &A, [5;7] -> &B
204-
// C = [4;7]
205-
// insert(C) -> true
206-
// intervals: [0;2] -> &A, [4;7] -> &C
207-
// D = [1;5]
208-
// insert(D) -> true
209-
// intervals: [0;2] -> &A, [3;3] -> &D, [4;7] -> &C
210-
// E = [0;unbounded]
211-
// insert(E) -> true
212-
// intervals: [0;unbounded] -> E
213-
//
214-
// Returns a reference to the first RangeInfo that overlaps with
215-
// [Info.LowerBound;Info.UpperBound], or, std::nullopt if there is no overlap
216-
// (equivalent to getOverlapping)
217-
LLVM_ABI std::optional<const RangeInfo *> insert(const RangeInfo &Info);
218-
};
219-
220154
} // namespace rootsig
221155
} // namespace hlsl
222156
} // namespace llvm
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
//===- RootSignatureValidations.h - HLSL Root Signature helpers -----------===//
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+
///
9+
/// \file This file contains helper obejcts for working with HLSL Root
10+
/// Signatures.
11+
///
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_FRONTEND_HLSL_ROOTSIGNATUREVALIDATIONS_H
15+
#define LLVM_FRONTEND_HLSL_ROOTSIGNATUREVALIDATIONS_H
16+
17+
#include "llvm/ADT/IntervalMap.h"
18+
#include "llvm/Frontend/HLSL/HLSLRootSignature.h"
19+
20+
namespace llvm {
21+
namespace hlsl {
22+
namespace rootsig {
23+
24+
struct RangeInfo {
25+
const static uint32_t Unbounded = ~0u;
26+
27+
// Interval information
28+
uint32_t LowerBound;
29+
uint32_t UpperBound;
30+
31+
// Information retained for diagnostics
32+
llvm::dxil::ResourceClass Class;
33+
uint32_t Space;
34+
llvm::dxbc::ShaderVisibility Visibility;
35+
};
36+
37+
class ResourceRange {
38+
public:
39+
using MapT = llvm::IntervalMap<uint32_t, const RangeInfo *, 16,
40+
llvm::IntervalMapInfo<uint32_t>>;
41+
42+
private:
43+
MapT Intervals;
44+
45+
public:
46+
ResourceRange(MapT::Allocator &Allocator) : Intervals(MapT(Allocator)) {}
47+
48+
// Returns a reference to the first RangeInfo that overlaps with
49+
// [Info.LowerBound;Info.UpperBound], or, std::nullopt if there is no overlap
50+
LLVM_ABI std::optional<const RangeInfo *>
51+
getOverlapping(const RangeInfo &Info) const;
52+
53+
// Return the mapped RangeInfo at X or nullptr if no mapping exists
54+
const RangeInfo *lookup(uint32_t X) const;
55+
56+
// Removes all entries of the ResourceRange
57+
LLVM_ABI void clear();
58+
59+
// Insert the required (sub-)intervals such that the interval of [a;b] =
60+
// [Info.LowerBound, Info.UpperBound] is covered and points to a valid
61+
// RangeInfo &.
62+
//
63+
// For instance consider the following chain of inserting RangeInfos with the
64+
// intervals denoting the Lower/Upper-bounds:
65+
//
66+
// A = [0;2]
67+
// insert(A) -> false
68+
// intervals: [0;2] -> &A
69+
// B = [5;7]
70+
// insert(B) -> false
71+
// intervals: [0;2] -> &A, [5;7] -> &B
72+
// C = [4;7]
73+
// insert(C) -> true
74+
// intervals: [0;2] -> &A, [4;7] -> &C
75+
// D = [1;5]
76+
// insert(D) -> true
77+
// intervals: [0;2] -> &A, [3;3] -> &D, [4;7] -> &C
78+
// E = [0;unbounded]
79+
// insert(E) -> true
80+
// intervals: [0;unbounded] -> E
81+
//
82+
// Returns a reference to the first RangeInfo that overlaps with
83+
// [Info.LowerBound;Info.UpperBound], or, std::nullopt if there is no overlap
84+
// (equivalent to getOverlapping)
85+
LLVM_ABI std::optional<const RangeInfo *> insert(const RangeInfo &Info);
86+
};
87+
88+
} // namespace rootsig
89+
} // namespace hlsl
90+
} // namespace llvm
91+
92+
#endif // LLVM_FRONTEND_HLSL_ROOTSIGNATUREVALIDATIONS_H

llvm/lib/Frontend/HLSL/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ add_llvm_component_library(LLVMFrontendHLSL
33
HLSLResource.cpp
44
HLSLRootSignature.cpp
55
RootSignatureMetadata.cpp
6+
RootSignatureValidations.cpp
67

78
ADDITIONAL_HEADER_DIRS
89
${LLVM_MAIN_INCLUDE_DIR}/llvm/Frontend

llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp

Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -239,69 +239,6 @@ void dumpRootElements(raw_ostream &OS, ArrayRef<RootElement> Elements) {
239239
OS << "}";
240240
}
241241

242-
std::optional<const RangeInfo *>
243-
ResourceRange::getOverlapping(const RangeInfo &Info) const {
244-
MapT::const_iterator Interval = Intervals.find(Info.LowerBound);
245-
if (!Interval.valid() || Info.UpperBound < Interval.start())
246-
return std::nullopt;
247-
return Interval.value();
248-
}
249-
250-
const RangeInfo *ResourceRange::lookup(uint32_t X) const {
251-
return Intervals.lookup(X, nullptr);
252-
}
253-
254-
void ResourceRange::clear() { return Intervals.clear(); }
255-
256-
std::optional<const RangeInfo *> ResourceRange::insert(const RangeInfo &Info) {
257-
uint32_t LowerBound = Info.LowerBound;
258-
uint32_t UpperBound = Info.UpperBound;
259-
260-
std::optional<const RangeInfo *> Res = std::nullopt;
261-
MapT::iterator Interval = Intervals.begin();
262-
263-
while (true) {
264-
if (UpperBound < LowerBound)
265-
break;
266-
267-
Interval.advanceTo(LowerBound);
268-
if (!Interval.valid()) // No interval found
269-
break;
270-
271-
// Let Interval = [x;y] and [LowerBound;UpperBound] = [a;b] and note that
272-
// a <= y implicitly from Intervals.find(LowerBound)
273-
if (UpperBound < Interval.start())
274-
break; // found interval does not overlap with inserted one
275-
276-
if (!Res.has_value()) // Update to be the first found intersection
277-
Res = Interval.value();
278-
279-
if (Interval.start() <= LowerBound && UpperBound <= Interval.stop()) {
280-
// x <= a <= b <= y implies that [a;b] is covered by [x;y]
281-
// -> so we don't need to insert this, report an overlap
282-
return Res;
283-
} else if (LowerBound <= Interval.start() &&
284-
Interval.stop() <= UpperBound) {
285-
// a <= x <= y <= b implies that [x;y] is covered by [a;b]
286-
// -> so remove the existing interval that we will cover with the
287-
// overwrite
288-
Interval.erase();
289-
} else if (LowerBound < Interval.start() && UpperBound <= Interval.stop()) {
290-
// a < x <= b <= y implies that [a; x] is not covered but [x;b] is
291-
// -> so set b = x - 1 such that [a;x-1] is now the interval to insert
292-
UpperBound = Interval.start() - 1;
293-
} else if (Interval.start() <= LowerBound && Interval.stop() < UpperBound) {
294-
// a < x <= b <= y implies that [y; b] is not covered but [a;y] is
295-
// -> so set a = y + 1 such that [y+1;b] is now the interval to insert
296-
LowerBound = Interval.stop() + 1;
297-
}
298-
}
299-
300-
assert(LowerBound <= UpperBound && "Attempting to insert an empty interval");
301-
Intervals.insert(LowerBound, UpperBound, &Info);
302-
return Res;
303-
}
304-
305242
} // namespace rootsig
306243
} // namespace hlsl
307244
} // namespace llvm
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//===- HLSLRootSignatureValidations.cpp - HLSL Root Signature helpers -----===//
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+
///
9+
/// \file This file contains helpers for working with HLSL Root Signatures.
10+
///
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "llvm/Frontend/HLSL/RootSignatureValidations.h"
14+
15+
namespace llvm {
16+
namespace hlsl {
17+
namespace rootsig {
18+
19+
std::optional<const RangeInfo *>
20+
ResourceRange::getOverlapping(const RangeInfo &Info) const {
21+
MapT::const_iterator Interval = Intervals.find(Info.LowerBound);
22+
if (!Interval.valid() || Info.UpperBound < Interval.start())
23+
return std::nullopt;
24+
return Interval.value();
25+
}
26+
27+
const RangeInfo *ResourceRange::lookup(uint32_t X) const {
28+
return Intervals.lookup(X, nullptr);
29+
}
30+
31+
void ResourceRange::clear() { return Intervals.clear(); }
32+
33+
std::optional<const RangeInfo *> ResourceRange::insert(const RangeInfo &Info) {
34+
uint32_t LowerBound = Info.LowerBound;
35+
uint32_t UpperBound = Info.UpperBound;
36+
37+
std::optional<const RangeInfo *> Res = std::nullopt;
38+
MapT::iterator Interval = Intervals.begin();
39+
40+
while (true) {
41+
if (UpperBound < LowerBound)
42+
break;
43+
44+
Interval.advanceTo(LowerBound);
45+
if (!Interval.valid()) // No interval found
46+
break;
47+
48+
// Let Interval = [x;y] and [LowerBound;UpperBound] = [a;b] and note that
49+
// a <= y implicitly from Intervals.find(LowerBound)
50+
if (UpperBound < Interval.start())
51+
break; // found interval does not overlap with inserted one
52+
53+
if (!Res.has_value()) // Update to be the first found intersection
54+
Res = Interval.value();
55+
56+
if (Interval.start() <= LowerBound && UpperBound <= Interval.stop()) {
57+
// x <= a <= b <= y implies that [a;b] is covered by [x;y]
58+
// -> so we don't need to insert this, report an overlap
59+
return Res;
60+
} else if (LowerBound <= Interval.start() &&
61+
Interval.stop() <= UpperBound) {
62+
// a <= x <= y <= b implies that [x;y] is covered by [a;b]
63+
// -> so remove the existing interval that we will cover with the
64+
// overwrite
65+
Interval.erase();
66+
} else if (LowerBound < Interval.start() && UpperBound <= Interval.stop()) {
67+
// a < x <= b <= y implies that [a; x] is not covered but [x;b] is
68+
// -> so set b = x - 1 such that [a;x-1] is now the interval to insert
69+
UpperBound = Interval.start() - 1;
70+
} else if (Interval.start() <= LowerBound && Interval.stop() < UpperBound) {
71+
// a < x <= b <= y implies that [y; b] is not covered but [a;y] is
72+
// -> so set a = y + 1 such that [y+1;b] is now the interval to insert
73+
LowerBound = Interval.stop() + 1;
74+
}
75+
}
76+
77+
assert(LowerBound <= UpperBound && "Attempting to insert an empty interval");
78+
Intervals.insert(LowerBound, UpperBound, &Info);
79+
return Res;
80+
}
81+
82+
} // namespace rootsig
83+
} // namespace hlsl
84+
} // namespace llvm

llvm/unittests/Frontend/HLSLRootSignatureRangesTest.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
#include "llvm/Frontend/HLSL/HLSLRootSignature.h"
9+
#include "llvm/Frontend/HLSL/RootSignatureValidations.h"
1010
#include "gtest/gtest.h"
1111

1212
using namespace llvm::hlsl::rootsig;

0 commit comments

Comments
 (0)