35struct IndexedRowRange {
39 static IndexedRowRange of(
unsigned StartRow,
unsigned RowCount) {
42 return {
static_cast<uint8_t
>(StartRow),
43 static_cast<uint8_t
>(StartRow + RowCount)};
46 bool isEmpty()
const {
return Begin == End; }
53 IndexedRowRange unionWith(IndexedRowRange
Other)
const {
58 return {std::min(Begin,
Other.Begin), std::max(End,
Other.End)};
62 return Begin ==
Other.Begin && End ==
Other.End;
72 "semantic interpretations must be in component packing order");
75 uint8_t OccupiedColumns = 0;
76 IndexedRowRange IndexedRange;
77 bool IndexedRangeFixed =
false;
78 unsigned ComponentWidth = 0;
80 dxbc::PSV::InterpolationMode::Undefined;
82 SemanticInterpretation::Arbitrary;
85using SignatureRows = std::array<SignatureRow, MaxSignatureRows>;
87struct ElementPlacement {
90 unsigned ComponentWidth;
95struct ElementLocation {
100struct OptimizedClipCullElement {
102 ElementPlacement Placement;
103 ElementLocation Location;
108struct ClipCullState {
109 std::array<SignatureRow, MaxClipCullRows> Rows;
110 std::array<unsigned, MaxClipCullRows> SignatureRows = {
UnallocatedRow,
112 unsigned RowsUsed = 0;
115enum class PackingGroup :
unsigned {
128 assert(ColumnMask != 0 &&
"expected at least one occupied column");
139 "unexpected semantic interpretation for optimized packing, "
140 "should have been diagnosed by Sema");
145 return PackingGroup::FullRegister;
148 return PackingGroup::IndexedTessFactor;
150 switch (Interpretation) {
152 return PackingGroup::Arbitrary;
155 return PackingGroup::SystemValue;
157 return PackingGroup::ClipCull;
159 return PackingGroup::SystemGenerated;
161 return PackingGroup::NotAllocated;
166 llvm_unreachable(
"unexpected semantic interpretation for optimized packing");
170 bool UseNative16BitTypes) {
176 "64-bit types cannot be used in a signature");
178 switch (ComponentType) {
186 return UseNative16BitTypes ? 16 : 32;
193static ElementPlacement
196 bool UseNative16BitTypes) {
217 IndexedRowRange IndexedRange) {
218 const bool IsSystemValue =
224 if (IsSystemValue && !Row.IndexedRange.isEmpty())
229 if (Row.IndexedRangeFixed && !Row.IndexedRange.contains(IndexedRange))
235 !IndexedRange.contains(Row.IndexedRange))
238 if (Row.OccupiedColumns && Row.ComponentWidth !=
Placement.ComponentWidth)
240 if (Row.InterpMode != dxbc::PSV::InterpolationMode::Undefined &&
246 if (Row.OccupiedColumns &&
263 const IndexedRowRange IndexedRange =
264 IndexedRowRange::of(StartRow,
Placement.Rows);
266 for (
unsigned ElementRow = 0; ElementRow !=
Placement.Rows; ++ElementRow) {
267 const SignatureRow &Row = Rows[StartRow + ElementRow];
270 OccupiedColumns |= Row.OccupiedColumns;
277 if (
Placement.Cols != 1 || (OccupiedColumns & LastColumn))
285 ((1U <<
Placement.Cols) - 1U) <<
static_cast<unsigned>(StartCol));
286 if (!(OccupiedColumns & ColumnMask))
294 const IndexedRowRange IndexedRange =
295 IndexedRowRange::of(StartRow,
Placement.Rows);
296 for (
unsigned ElementRow = 0; ElementRow !=
Placement.Rows; ++ElementRow) {
297 SignatureRow &Row = Rows[StartRow + ElementRow];
298 assert(!(Row.OccupiedColumns & ColumnMask) &&
299 "cannot overlap signature elements");
300 const uint8_t PreviousOccupiedColumns = Row.OccupiedColumns;
301 if (!PreviousOccupiedColumns)
302 Row.ComponentWidth =
Placement.ComponentWidth;
303 Row.OccupiedColumns |= ColumnMask;
304 if (Row.InterpMode == dxbc::PSV::InterpolationMode::Undefined)
307 if (!PreviousOccupiedColumns || ColumnMask > PreviousOccupiedColumns)
308 Row.RightmostInterpretation =
Placement.Interpretation;
310 Row.IndexedRange = Row.IndexedRange.unionWith(IndexedRange);
314 assert(Row.IndexedRange == IndexedRange &&
"incompatible index range");
315 Row.IndexedRangeFixed =
true;
322 ElementLocation &Location) {
324 Location.Row = StartRow;
331 for (
unsigned StartRow = 0; StartRow != Rows.
size(); ++StartRow) {
342static ElementPlacement
344 ElementPlacement Reservation =
Placement;
345 Reservation.Rows = RowCount;
352 const ElementPlacement &Reservation) {
353 std::optional<uint8_t> ColumnMask =
canPlaceAt(Rows, StartRow, Reservation);
356 placeRowsAt(Rows, StartRow, Reservation, *ColumnMask);
360static std::optional<unsigned>
362 const ElementPlacement &Reservation) {
363 for (
unsigned StartRow = 0; StartRow != Rows.
size(); ++StartRow)
372static std::optional<SignaturePackingError::ErrorKind>
374 ClipCullState &State,
376 unsigned NewRowsUsed) {
379 for (
unsigned Row = State.RowsUsed; Row < NewRowsUsed; ++Row) {
380 std::optional<unsigned> StartRow =
384 State.SignatureRows[Row] = *StartRow;
389 if (State.RowsUsed == 0) {
394 State.SignatureRows[0] = *StartRow;
395 State.SignatureRows[1] = *StartRow + 1;
399 if (State.RowsUsed == 1) {
400 const unsigned StartRow = State.SignatureRows[0] + 1;
401 if (StartRow >= SignatureRows.
size())
406 State.SignatureRows[1] = StartRow;
410 if (State.SignatureRows[0] + 1 != State.SignatureRows[1])
415static std::optional<SignaturePackingError::ErrorKind>
418 ClipCullState &State,
const ElementPlacement &
Placement) {
419 std::optional<uint8_t> ColumnMask;
420 unsigned ClipCullStartRow = 0;
430 const unsigned NewRowsUsed = ClipCullStartRow +
Placement.Rows;
431 if (std::optional<SignaturePackingError::ErrorKind> Kind =
437 State.RowsUsed = std::max(State.RowsUsed, NewRowsUsed);
438 Location.Row = State.SignatureRows[ClipCullStartRow];
448 if (Elements.empty())
451 std::array<SignatureRow, MaxClipCullRows> LocalRows;
452 bool HasIndexed =
false;
453 for (
auto &Element : Elements) {
457 HasIndexed |= Element.Placement.Rows > 1;
463 std::array<ElementLocation, MaxClipCullRows> Destinations;
466 return Element.Location.Row == Row;
468 if (
First == Elements.end())
470 ElementPlacement Bundle =
First->Placement;
471 Bundle.Cols =
popcount(LocalRows[Row].OccupiedColumns);
476 Rows[Destinations[Row].Row].InterpMode = LocalRows[Row].InterpMode;
478 for (
auto &Element : Elements) {
479 ElementLocation Destination = Destinations[Element.Location.Row];
482 static_cast<uint8_t>(Destination.Col + Element.Location.Col)};
493 for (
auto &Element : Elements) {
494 Element.Location = {};
495 for (
unsigned Start = Row;
497 if (
auto Mask =
canPlaceAt(CandidateRows, Start, Element.Placement)) {
498 placeAt(CandidateRows, Start, Element.Placement, *Mask,
523 bool UseNative16BitTypes) {
527 Streams(Rows.
size());
528 for (
unsigned Index : Order) {
529 const auto &Element = Elements[Index];
532 assert(Element.Rows > 0 &&
"signature element must have at least one row");
534 "signature element must have between 1 and 4 columns");
535 if (Element.GSStream >= Rows.
size())
541 UseNative16BitTypes),
547 for (
unsigned Stream = 0; Stream != Streams.
size(); ++Stream)
550 return std::move(Err);
555 unsigned NumRows = 0;
556 for (
const auto &Stream : Streams)
557 for (
const auto &Element : Stream) {
558 Elements[Element.Index].StartRow = Element.Location.Row;
559 Elements[Element.Index].StartCol = Element.Location.Col;
561 std::max(NumRows, Element.Location.Row + Element.Placement.Rows);
575 OS <<
"clip/cull elements do not fit in " <<
MaxClipCullRows <<
" rows";
578 OS <<
"indexed clip/cull elements require adjacent signature rows";
581 OS <<
"signature element has an invalid geometry stream: expected an index "
586 OS <<
" (element " << ElementIndex <<
")";
593 "stacked packing is only valid for a vertex shader input signature");
595 unsigned NextRow = 0;
596 for (
auto &&[Index, Element] :
enumerate(Elements)) {
599 assert(Element.Rows > 0 &&
"signature element must have at least one row");
601 "signature element must have between 1 and 4 columns");
611 "unexpected semantic interpretation for stacked packing, should "
612 "have been diagnosed by Sema");
617 static_cast<unsigned>(Index));
619 Element.StartRow = NextRow;
620 Element.StartCol = 0;
621 NextRow += Element.Rows;
627template <
typename IndexRange>
633 unsigned NumRows = 0;
634 for (
unsigned Index : Order) {
638 assert(Element.
Rows > 0 &&
"signature element must have at least one row");
640 "signature element must have between 1 and 4 columns");
644 static_cast<unsigned>(Index));
656 "unexpected semantic interpretation for prefix-stable packing, "
657 "should have been diagnosed by Sema");
662 const unsigned StreamIndex = Element.
GSStream;
664 ElementLocation Location;
667 if (std::optional<SignaturePackingError::ErrorKind> Kind =
674 static_cast<unsigned>(Index));
677 Elements[Index].StartRow = Location.Row;
678 Elements[Index].StartCol = Location.Col;
679 NumRows = std::max(NumRows, Location.Row + Element.
Rows);
688 bool UseNative16BitTypes) {
691 "prefix-stable packing is not valid for vertex inputs or pixel "
693 const unsigned StreamCount =
699 ShaderStage, IOTy, UseNative16BitTypes, Rows);
706 "indexed packing is only valid for a pixel shader output signature");
708 static_assert(MaxSignatureRows <= std::numeric_limits<uint32_t>::digits,
709 "row allocation mask is too small");
710 [[maybe_unused]]
uint32_t AllocatedRows = 0;
711 unsigned NumRows = 0;
712 for (
auto &&[Index, Element] :
enumerate(Elements)) {
715 assert(Element.Rows > 0 &&
"signature element must have at least one row");
717 "signature element must have between 1 and 4 columns");
725 "unexpected semantic interpretation for indexed packing, should "
726 "have been diagnosed by Sema");
727 assert(Element.Rows == 1 && Element.SemanticIndices.size() == 1 &&
728 "target elements must occupy one semantic row");
730 const uint32_t Row = Element.SemanticIndices.front();
734 static_cast<unsigned>(Index));
737 assert(!(AllocatedRows & RowMask) &&
738 "target semantic indices must be unique, verified in SemaHLSL");
739 AllocatedRows |= RowMask;
741 Element.StartRow = Row;
742 Element.StartCol = 0;
743 NumRows = std::max(NumRows, Row + 1);
752 bool UseNative16BitTypes) {
755 "optimized packing is not valid for vertex inputs or pixel outputs");
763 unsigned OriginalIndex;
766 SortedKeys.
reserve(Elements.size());
767 for (
auto [Index, Element] :
enumerate(Elements))
769 Element.InterpMode, Element.Rows, Element.Cols,
770 Element.SigId,
static_cast<unsigned>(Index)});
776 return Left.InterpMode <
Right.InterpMode;
784 const unsigned StreamCount =
790 return Key.Group < PackingGroup::ClipCull;
794 [](
const SortKey &
Key) { return Key.Group == PackingGroup::ClipCull; });
796 auto Pack = [&](
auto Begin,
auto End) {
798 return Key.OriginalIndex;
801 UseNative16BitTypes, Rows);
817 return std::max({*Before, *
ClipCull, *After});
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Branch Probability Basic Block Placement
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static std::optional< uint8_t > canPlaceAt(ArrayRef< SignatureRow > Rows, unsigned StartRow, const ElementPlacement &Placement)
static std::optional< SignaturePackingError::ErrorKind > packClipCullElement(ElementLocation &Location, MutableArrayRef< SignatureRow > SignatureRows, ClipCullState &State, const ElementPlacement &Placement)
static std::optional< unsigned > reserveNextClipCullRows(MutableArrayRef< SignatureRow > Rows, const ElementPlacement &Reservation)
static ElementPlacement getElementPlacement(const SemanticSignatureElement &Element, SemanticInterpretation Interpretation, bool UseNative16BitTypes)
static bool reserveClipCullRows(MutableArrayRef< SignatureRow > Rows, unsigned StartRow, const ElementPlacement &Reservation)
static PackingGroup getOptimizedPackingGroup(const SemanticSignatureElement &Element, Triple::EnvironmentType ShaderStage, IOType IOTy)
static Error packOptimizedClipCullStream(MutableArrayRef< OptimizedClipCullElement > Elements, MutableArrayRef< SignatureRow > Rows)
static unsigned getComponentWidth(dxil::ElementType ComponentType, bool UseNative16BitTypes)
static bool prefixPackElement(ElementLocation &Location, MutableArrayRef< SignatureRow > Rows, const ElementPlacement &Placement)
static ElementPlacement getClipCullReservation(const ElementPlacement &Placement, unsigned RowCount)
static void placeAt(MutableArrayRef< SignatureRow > Rows, unsigned StartRow, const ElementPlacement &Placement, uint8_t ColumnMask, ElementLocation &Location)
static bool canCoPack(const SignatureRow &Row, const ElementPlacement &Placement, IndexedRowRange IndexedRange)
static SemanticInterpretation getComponentOrder(SemanticInterpretation Interpretation)
static void placeRowsAt(MutableArrayRef< SignatureRow > Rows, unsigned StartRow, const ElementPlacement &Placement, uint8_t ColumnMask)
static Expected< unsigned > packSignatureInOrder(MutableArrayRef< SemanticSignatureElement > Elements, const IndexRange &Order, Triple::EnvironmentType ShaderStage, IOType IOTy, bool UseNative16BitTypes, MutableArrayRef< SignatureRows > Rows)
static std::optional< SignaturePackingError::ErrorKind > reserveClipCullSignatureRows(MutableArrayRef< SignatureRow > SignatureRows, ClipCullState &State, const ElementPlacement &Placement, unsigned NewRowsUsed)
static uint8_t getStartColumn(uint8_t ColumnMask)
static Expected< unsigned > packOptimizedClipCull(MutableArrayRef< SemanticSignatureElement > Elements, ArrayRef< unsigned > Order, MutableArrayRef< SignatureRows > Rows, bool UseNative16BitTypes)
Provides some synthesis utilities to produce sequences of values.
This file defines the SmallVector class.
This file implements the C++20 <bit> header.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
@ SemanticIndexOutOfRange
void log(raw_ostream &OS) const override
Print an error message to an output stream.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
ElementType
The element type of an SRV or UAV resource.
static constexpr uint32_t UnallocatedRow
static constexpr unsigned MaxGeometryStreams
LLVM_ABI Expected< unsigned > packSignatureStacked(MutableArrayRef< SemanticSignatureElement > Elements, Triple::EnvironmentType ShaderStage, IOType IOTy)
Packs eligible signature elements into consecutive rows.
LLVM_ABI Expected< unsigned > packSignaturePrefixStable(MutableArrayRef< SemanticSignatureElement > Elements, Triple::EnvironmentType ShaderStage, IOType IOTy, bool UseNative16BitTypes)
Packs eligible signature elements without moving previously placed elements.
LLVM_ABI SemanticInterpretation getInterpretationKind(dxbc::PSV::SemanticKind SemanticKind, Triple::EnvironmentType ShaderStage, IOType IOTy)
LLVM_ABI Expected< unsigned > packSignatureIndexed(MutableArrayRef< SemanticSignatureElement > Elements, Triple::EnvironmentType ShaderStage, IOType IOTy)
Packs eligible signature elements at rows selected by semantic index.
LLVM_ABI Expected< unsigned > packSignatureOptimized(MutableArrayRef< SemanticSignatureElement > Elements, Triple::EnvironmentType ShaderStage, IOType IOTy, bool UseNative16BitTypes)
Packs eligible signature elements in an optimized order by reordering elements into an optimal packin...
static constexpr unsigned MaxClipCullRows
static constexpr unsigned MaxSignatureRows
static constexpr uint8_t UnallocatedCol
static constexpr unsigned MaxSignatureCols
This is an optimization pass for GlobalISel generic memory operations.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
auto partition_point(R &&Range, Predicate P)
Binary search for the first iterator in a range where a predicate is false.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
void sort(IteratorTy Start, IteratorTy End)
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
dxil::ElementType CompType
dxbc::PSV::SemanticKind SemanticKind
dxbc::PSV::InterpolationMode InterpMode