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;
162 return PackingGroup::NotAllocated;
167 llvm_unreachable(
"unexpected semantic interpretation for optimized packing");
171 bool UseNative16BitTypes) {
177 "64-bit types cannot be used in a signature");
179 switch (ComponentType) {
187 return UseNative16BitTypes ? 16 : 32;
194static ElementPlacement
197 bool UseNative16BitTypes) {
218 IndexedRowRange IndexedRange) {
219 const bool IsSystemValue =
225 if (IsSystemValue && !Row.IndexedRange.isEmpty())
230 if (Row.IndexedRangeFixed && !Row.IndexedRange.contains(IndexedRange))
236 !IndexedRange.contains(Row.IndexedRange))
239 if (Row.OccupiedColumns && Row.ComponentWidth !=
Placement.ComponentWidth)
241 if (Row.InterpMode != dxbc::PSV::InterpolationMode::Undefined &&
247 if (Row.OccupiedColumns &&
264 const IndexedRowRange IndexedRange =
265 IndexedRowRange::of(StartRow,
Placement.Rows);
267 for (
unsigned ElementRow = 0; ElementRow !=
Placement.Rows; ++ElementRow) {
268 const SignatureRow &Row = Rows[StartRow + ElementRow];
271 OccupiedColumns |= Row.OccupiedColumns;
278 if (
Placement.Cols != 1 || (OccupiedColumns & LastColumn))
286 ((1U <<
Placement.Cols) - 1U) <<
static_cast<unsigned>(StartCol));
287 if (!(OccupiedColumns & ColumnMask))
295 const IndexedRowRange IndexedRange =
296 IndexedRowRange::of(StartRow,
Placement.Rows);
297 for (
unsigned ElementRow = 0; ElementRow !=
Placement.Rows; ++ElementRow) {
298 SignatureRow &Row = Rows[StartRow + ElementRow];
299 assert(!(Row.OccupiedColumns & ColumnMask) &&
300 "cannot overlap signature elements");
301 const uint8_t PreviousOccupiedColumns = Row.OccupiedColumns;
302 if (!PreviousOccupiedColumns)
303 Row.ComponentWidth =
Placement.ComponentWidth;
304 Row.OccupiedColumns |= ColumnMask;
305 if (Row.InterpMode == dxbc::PSV::InterpolationMode::Undefined)
308 if (!PreviousOccupiedColumns || ColumnMask > PreviousOccupiedColumns)
309 Row.RightmostInterpretation =
Placement.Interpretation;
311 Row.IndexedRange = Row.IndexedRange.unionWith(IndexedRange);
315 assert(Row.IndexedRange == IndexedRange &&
"incompatible index range");
316 Row.IndexedRangeFixed =
true;
323 ElementLocation &Location) {
325 Location.Row = StartRow;
332 for (
unsigned StartRow = 0; StartRow != Rows.
size(); ++StartRow) {
343static ElementPlacement
345 ElementPlacement Reservation =
Placement;
346 Reservation.Rows = RowCount;
353 const ElementPlacement &Reservation) {
354 std::optional<uint8_t> ColumnMask =
canPlaceAt(Rows, StartRow, Reservation);
357 placeRowsAt(Rows, StartRow, Reservation, *ColumnMask);
361static std::optional<unsigned>
363 const ElementPlacement &Reservation) {
364 for (
unsigned StartRow = 0; StartRow != Rows.
size(); ++StartRow)
373static std::optional<SignaturePackingError::ErrorKind>
375 ClipCullState &State,
377 unsigned NewRowsUsed) {
380 for (
unsigned Row = State.RowsUsed; Row < NewRowsUsed; ++Row) {
381 std::optional<unsigned> StartRow =
385 State.SignatureRows[Row] = *StartRow;
390 if (State.RowsUsed == 0) {
395 State.SignatureRows[0] = *StartRow;
396 State.SignatureRows[1] = *StartRow + 1;
400 if (State.RowsUsed == 1) {
401 const unsigned StartRow = State.SignatureRows[0] + 1;
402 if (StartRow >= SignatureRows.
size())
407 State.SignatureRows[1] = StartRow;
411 if (State.SignatureRows[0] + 1 != State.SignatureRows[1])
416static std::optional<SignaturePackingError::ErrorKind>
419 ClipCullState &State,
const ElementPlacement &
Placement) {
420 std::optional<uint8_t> ColumnMask;
421 unsigned ClipCullStartRow = 0;
431 const unsigned NewRowsUsed = ClipCullStartRow +
Placement.Rows;
432 if (std::optional<SignaturePackingError::ErrorKind> Kind =
438 State.RowsUsed = std::max(State.RowsUsed, NewRowsUsed);
439 Location.Row = State.SignatureRows[ClipCullStartRow];
449 if (Elements.empty())
452 std::array<SignatureRow, MaxClipCullRows> LocalRows;
453 bool HasIndexed =
false;
454 for (
auto &Element : Elements) {
458 HasIndexed |= Element.Placement.Rows > 1;
464 std::array<ElementLocation, MaxClipCullRows> Destinations;
467 return Element.Location.Row == Row;
469 if (
First == Elements.end())
471 ElementPlacement Bundle =
First->Placement;
472 Bundle.Cols =
popcount(LocalRows[Row].OccupiedColumns);
477 Rows[Destinations[Row].Row].InterpMode = LocalRows[Row].InterpMode;
479 for (
auto &Element : Elements) {
480 ElementLocation Destination = Destinations[Element.Location.Row];
483 static_cast<uint8_t>(Destination.Col + Element.Location.Col)};
494 for (
auto &Element : Elements) {
495 Element.Location = {};
496 for (
unsigned Start = Row;
498 if (
auto Mask =
canPlaceAt(CandidateRows, Start, Element.Placement)) {
499 placeAt(CandidateRows, Start, Element.Placement, *Mask,
524 bool UseNative16BitTypes) {
528 Streams(Rows.
size());
529 for (
unsigned Index : Order) {
530 const auto &Element = Elements[Index];
533 assert(Element.Rows > 0 &&
"signature element must have at least one row");
535 "signature element must have between 1 and 4 columns");
536 if (Element.GSStream >= Rows.
size())
542 UseNative16BitTypes),
548 for (
unsigned Stream = 0; Stream != Streams.
size(); ++Stream)
551 return std::move(Err);
556 unsigned NumRows = 0;
557 for (
const auto &Stream : Streams)
558 for (
const auto &Element : Stream) {
559 Elements[Element.Index].StartRow = Element.Location.Row;
560 Elements[Element.Index].StartCol = Element.Location.Col;
562 std::max(NumRows, Element.Location.Row + Element.Placement.Rows);
576 OS <<
"clip/cull elements do not fit in " <<
MaxClipCullRows <<
" rows";
579 OS <<
"indexed clip/cull elements require adjacent signature rows";
582 OS <<
"signature element has an invalid geometry stream: expected an index "
587 OS <<
" (element " << ElementIndex <<
")";
594 "stacked packing is only valid for a vertex shader input signature");
596 unsigned NextRow = 0;
597 for (
auto &&[Index, Element] :
enumerate(Elements)) {
600 assert(Element.Rows > 0 &&
"signature element must have at least one row");
602 "signature element must have between 1 and 4 columns");
613 "unexpected semantic interpretation for stacked packing, should "
614 "have been diagnosed by Sema");
619 static_cast<unsigned>(Index));
621 Element.StartRow = NextRow;
622 Element.StartCol = 0;
623 NextRow += Element.Rows;
629template <
typename IndexRange>
635 unsigned NumRows = 0;
636 for (
unsigned Index : Order) {
640 assert(Element.
Rows > 0 &&
"signature element must have at least one row");
642 "signature element must have between 1 and 4 columns");
646 static_cast<unsigned>(Index));
659 "unexpected semantic interpretation for prefix-stable packing, "
660 "should have been diagnosed by Sema");
665 const unsigned StreamIndex = Element.
GSStream;
667 ElementLocation Location;
670 if (std::optional<SignaturePackingError::ErrorKind> Kind =
677 static_cast<unsigned>(Index));
680 Elements[Index].StartRow = Location.Row;
681 Elements[Index].StartCol = Location.Col;
682 NumRows = std::max(NumRows, Location.Row + Element.
Rows);
691 bool UseNative16BitTypes) {
694 "prefix-stable packing is not valid for vertex inputs or pixel "
696 const unsigned StreamCount =
702 ShaderStage, IOTy, UseNative16BitTypes, Rows);
709 "indexed packing is only valid for a pixel shader output signature");
711 static_assert(MaxSignatureRows <= std::numeric_limits<uint32_t>::digits,
712 "row allocation mask is too small");
713 [[maybe_unused]]
uint32_t AllocatedRows = 0;
714 unsigned NumRows = 0;
715 for (
auto &&[Index, Element] :
enumerate(Elements)) {
718 assert(Element.Rows > 0 &&
"signature element must have at least one row");
720 "signature element must have between 1 and 4 columns");
729 "unexpected semantic interpretation for indexed packing, should "
730 "have been diagnosed by Sema");
731 assert(Element.Rows == 1 && Element.SemanticIndices.size() == 1 &&
732 "target elements must occupy one semantic row");
734 const uint32_t Row = Element.SemanticIndices.front();
738 static_cast<unsigned>(Index));
741 assert(!(AllocatedRows & RowMask) &&
742 "target semantic indices must be unique, verified in SemaHLSL");
743 AllocatedRows |= RowMask;
745 Element.StartRow = Row;
746 Element.StartCol = 0;
747 NumRows = std::max(NumRows, Row + 1);
756 bool UseNative16BitTypes) {
759 "optimized packing is not valid for vertex inputs or pixel outputs");
767 unsigned OriginalIndex;
770 SortedKeys.
reserve(Elements.size());
771 for (
auto [Index, Element] :
enumerate(Elements))
773 Element.InterpMode, Element.Rows, Element.Cols,
774 Element.SigId,
static_cast<unsigned>(Index)});
780 return Left.InterpMode <
Right.InterpMode;
788 const unsigned StreamCount =
794 return Key.Group < PackingGroup::ClipCull;
798 [](
const SortKey &
Key) { return Key.Group == PackingGroup::ClipCull; });
800 auto Pack = [&](
auto Begin,
auto End) {
802 return Key.OriginalIndex;
805 UseNative16BitTypes, Rows);
821 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.
@ End
Run the machine verifier once, at the end of the pipeline.
dxil::ElementType CompType
dxbc::PSV::SemanticKind SemanticKind
dxbc::PSV::InterpolationMode InterpMode