Skip to content

Commit d857061

Browse files
authored
[DirectX][DXIL] Update DXIL Op TableGen Specification (#95807)
Add a mechanism to specify constraints to the design document. These facilitate specification of DXIL Op attributes that are predicated by Shader Model version.
1 parent abd9534 commit d857061

File tree

1 file changed

+219
-92
lines changed

1 file changed

+219
-92
lines changed

llvm/docs/DirectX/DXILOpTableGenDesign.rst

Lines changed: 219 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -14,147 +14,274 @@ Introduction
1414
encapsulates, among other information, various DXIL Operations in
1515
`hctdb.py <https://github.com/microsoft/DirectXShaderCompiler/blob/main/utils/hct/hctdb.py>`_.
1616
DXIL Operations are represented in one of the following `two ways
17-
<https://github.com/microsoft/DirectXShaderCompiler/blob/130877392c263888ef06bab768856d3dab1f1c9a/docs/DXIL.rst#L1978>`_:
17+
<https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#operations>`_:
1818

1919
#. Using LLVM instructions.
2020
#. Using LLVM External functions. These are represented in LLVM IR as follows:
21+
2122
* "Standard" LLVM intrinsics (e.g., ``llvm.sin.*``) and
2223
* HLSL intrinsics (defined as LLVM intrinsics in ``llvm/include/llvm/IR/IntrinsicsDirectX.td``, e.g., ``llvm.dx.*``)
2324

2425
These are collectively referred to as `LLVM Intrinsics` in this note.
2526

26-
Following is the complete list of properties of DXIL Ops with the corresponding field name
27-
as used in ``hctdb.py``. A DXIL Op is represented by a set of associated properties. These
28-
are categorized into two groups - viz., those that are (1) consumed in DXIL backend passes
29-
and (2) consumed in other usage scenarios such as validation, DXIL reader, etc.
27+
Following is the complete list of attributes of DXIL Ops with the corresponding field name
28+
as used in ``hctdb.py``. A DXIL Op is represented by a set of associated attributes. These
29+
are consumed in DXIL backend passes as well as in other usage scenarios such as validation,
30+
DXIL reader, etc.
3031

31-
A. Properties consumed in DXIL backend passes
32+
A. Attributes consumed in DXIL backend passes
3233

3334
1. Name of operation (``dxil_op``)
34-
2. The generic or HLSL-specific intrinsic that maps to the operation (``llvm_name``).
35-
3. Unique Integer ID (``dxil_opid``)
36-
4. Operation Class signifying the name and function signature of the operation (``dxil_class``).
37-
This string is an integral part of the DXIL Op function name and is constructed in
38-
the format ``dx.op.<class-name>.<overload-type>``. The DXIL validator checks for any
39-
deviation from this for each of the DXIL Op call.
40-
5. List of valid overload types for the operation (``oload_types``).
41-
6. Required DXIL Version with support for the operation.
42-
7. A string that documents the operation (``doc``) - This is not strictly necessary but is included
35+
2. A string that documents the operation (``doc``) - This is not strictly necessary but is included
4336
for readability and documentation of the operation.
44-
45-
B. Properties consumed in other usage scenarios
46-
47-
1. Required minimum Shader Model (``shader_model``).
48-
2. Minimum shader model required with translation by linker (``shader_model_translated``)
49-
3. List of shader stages applicable to (``shader_stages``), empty for all.
50-
4. Memory access attributes of the operation (``fn_attr``).
51-
5. Boolean attributes of operation to indicate if it
52-
53-
* is some kind of a derivative (``is_derivative``)
54-
* requires gradient calculation (``is_gradient``)
55-
* is a sampler feedback (``is_feedback``)
56-
* requires in-wave, cross-lane functionality (``is_wave``)
57-
* requires that all of its inputs are uniform across the wave (``requires_uniform_inputs``).
58-
* is a barrier operation (``is_barrier``).
37+
3. The generic or HLSL-specific intrinsic that maps to the operation (``llvm_name``).
38+
4. Unique Integer ID (``dxil_opid``)
39+
5. Operation Class signifying the name and function signature of the operation (``dxil_class``).
40+
This string is an integral part of the DXIL Op function name and is constructed in
41+
the format ``dx.op.<class-name>.<overload-type>``. Each DXIL Op call target function name
42+
is required to conform to this format per existing contract with the driver.
43+
6. List of valid overload types for the operation (``oload_types``).
44+
7. Required DXIL Version with support for the operation.
45+
8. Required minimum Shader Model (``shader_model``).
46+
9. Minimum shader model required with translation by linker (``shader_model_translated``)
47+
10. List of shader stages applicable to (``shader_stages``), empty, if applicable to all stages.
48+
11. Memory access attributes of the operation (``fn_attr``).
49+
12. Boolean attributes of operation to indicate if it
50+
51+
* is some kind of a derivative (``is_derivative``)
52+
* requires gradient calculation (``is_gradient``)
53+
* is a sampler feedback (``is_feedback``)
54+
* requires in-wave, cross-lane functionality (``is_wave``)
55+
* requires that all of its inputs are uniform across the wave (``requires_uniform_inputs``).
56+
* is a barrier operation (``is_barrier``).
5957

6058
Motivation
6159
==========
6260

63-
DXIL backend passes depend on various properties of DXIL Operations. For example, ``DXILLowering``
61+
DXIL backend passes depend on various attributes of DXIL Operations. For example, ``DXILOpLowering``
6462
pass will need information such as the DXIL operation an LLVM intrinsic is to be lowered to,
6563
along with valid overload and parameter types etc. The TableGen file -
6664
``llvm/lib/Target/DirectX/DXIL.td`` - is used to represent DXIL Operations
67-
by specifying their properties listed above. ``DXIL.td`` is designed to be the single source
68-
of reference of DXIL Operations for DXIL backend implementation in ``llvm-project`` repo -
69-
analogous to ``hctdb.py`` for ``DirectXShadeCompiler`` repo. It needs to have a rich
70-
representation capabilities that TableGen backends (such as ``DXILEmitter``) can rely on.
71-
Additionally, the DXIL Op specification should be easy to read and comprehend.
65+
by specifying their attributes listed above. ``DXIL.td`` is designed to be the single source
66+
of reference of DXIL Operations primarily for the implementation of passes in DXIL backend in
67+
``llvm-project`` repo - analogous to ``hctdb.py`` for ``DirectXShadeCompiler`` repo. However,
68+
the current design does not intend to encapsulate various validation rules, present in ``hctdb.py``,
69+
but do not pertain to DXIL Operations. It needs to have a rich representation capabilities that
70+
TableGen backends (such as ``DXILEmitter``) can rely on. Additionally, the DXIL Op specification
71+
should be easy to read and comprehend.
7272

73-
This note focuses on specification of the set of properties consumed by DXIL backend
74-
passes identified above in category A. Any of the properties from category B are expected to be
75-
included as deemed necessary during implementation.
73+
This note provides the design of the specification DXIL Ops as TableGen class ``DXILOp``
74+
by specifying its attributes identified above.
7675

77-
Design
78-
======
76+
DXIL Operation Specification
77+
============================
78+
79+
The DXIL Operation is represented using the TableGen class ``DXILOp``. The DXIL operation
80+
attributes are specified as fields of the ``DXILOp`` class as described below.
7981

8082
1. Each DXIL Operation is represented as a TableGen record. The name of each of the records
8183
signifies operation name.
82-
2. The LLVM Intrinsic that maps to the operation is represented using ``Intrinsic::*``.
83-
3. The unique operation id is represented by an integer.
84-
4. DXIL Operation Class is represented as follows
84+
2. A documentation string for the operation.
85+
3. The LLVM Intrinsic that maps to the operation is represented as ``Intrinsic`` defined in
86+
`Intrinsics.td <https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/IR/Intrinsics.td>`_.
87+
4. The unique operation id is represented by an integer.
88+
5. DXIL Operation Class is represented as follows
8589

8690
.. code-block::
8791
8892
// Abstraction of DXIL Operation class.
89-
// It encapsulates an associated function signature viz.,
90-
// returnTy(param1Ty, param2Ty, ...) represented as a list of LLVMTypes.
91-
// DXIL Ops that belong to a DXILOpClass record the signature of that DXILOpClass
92-
93-
class DXILOpClass<list<LLVMType> OpSig> {
94-
list<LLVMType> OpSignature = OpSig;
95-
}
93+
class DXILOpClass;
9694
97-
Concrete operation classes, such as ``unary`` are defined inheriting from ``DXILOpClass``.
98-
5. Valid overload types are represented as a list of ``LLVMType``.
99-
6. Concrete records of DXIL versions and are defined by inheriting from the class
95+
Concrete operation records, such as ``unary`` are defined by inheriting from ``DXILOpClass``.
96+
6. Return and argument types of the operation are represented as ``dag``s using the
97+
special markers ``out`` and ``ins``. An overload type, if supported by the operation, is
98+
denoted as the positional type ``dxil_overload_ty`` in the argument or in the result, where
99+
``dxil_overload_ty`` is defined to be synonymous to ``llvm_any_ty``.
100100

101101
.. code-block::
102102
103-
// Abstract class to represent major and minor version values
104-
class Version<int major, int minor> {
105-
int Major = major;
106-
int Minor = minor;
107-
}
103+
defvar dxil_overload_ty = llvm_any_ty
108104
109-
7. A documentation string for the operation.
110105
106+
7. Valid overload types and shader stages predicated on Shader Model version are specified
107+
as a list of ``Constraint`` records. Representation of ``Constraints`` class is described
108+
a later section.
109+
8. Various attributes of the DXIL Operation that are not predicated on Shader Model version
110+
are represented as a ``dag`` using the special marker ``attrs``. Representation of ``Attributes``
111+
class is described in a later section.
111112

112113
A DXIL Operation is represented by the following TableGen class by encapsulating the various
113-
TableGen representations of its properties described above.
114+
TableGen representations of its attributes described above.
114115

115116
.. code-block::
116117
117-
// Abstraction DXIL Operation
118-
class DXILOpPropertiesBase {
119-
int OpCode = 0; // Opcode of DXIL Operation
120-
DXILOpClass OpClass = UnknownOpClass; // Class of DXIL Operation.
121-
Intrinsic LLVMIntrinsic = ?; // LLVM Intrinsic DXIL Operation maps to
122-
list<LLVMType> OpOverloadTypes = ?; // Valid overload type
123-
// of DXIL Operation
124-
Version DXILVer = ?; // Min DXIL version
125-
string Doc = ""; // A short description of the operation
126-
}
118+
// Abstraction DXIL Operation
119+
class DXILOp {
120+
// A short description of the operation
121+
string Doc = "";
122+
123+
// Opcode of DXIL Operation
124+
int OpCode = 0;
125+
126+
// Class of DXIL Operation.
127+
DXILOpClass OpClass = UnknownOpClass;
128+
129+
// LLVM Intrinsic DXIL Operation maps to
130+
Intrinsic LLVMIntrinsic = ?;
127131
132+
// Dag containing the arguments of the op. Default to 0 arguments.
133+
dag arguments = (ins);
128134
129-
The following convenience class, definitions of ``unary`` and ``DXVer1_0`` are used to
130-
illustrate the definitions of ``Sin`` and ``Cos`` operations:
135+
// Results of the op. Default to 0 results.
136+
dag result = (out);
131137
132-
.. code-block::
138+
// List of constraints predicated on Shader Model version
139+
list<SMVersionConstraints> sm_constraints;
133140
134-
class DXILOpProperties<int opCode,
135-
Intrinsic intrinsic,
136-
list<LLVMType> overloadTypes,
137-
string doc> : DXILOpPropertiesBase {
138-
int OpCode = opCode;
139-
Intrinsic LLVMIntrinsic = intrinsic;
140-
list<LLVMType> OpOverloadTypes = overloadTypes;
141-
string Doc = doc;
142-
}
141+
// Non-predicated operation attributes
142+
dag attrtibutes = (attrs);
143+
Version DXILVersion = ?;
144+
}
143145
144-
def unary : DXILOpClass<[llvm_any_ty, LLVMMatchType<0>]>;
145-
def DXVer1_0 : Version<1, 0>;
146+
Constraint Specification
147+
========================
148+
149+
DXIL Operation attributes such as valid overload types and valid shader stages are
150+
predicated on Shader Model version. These are represented as list of constrained
151+
attributes.
152+
153+
Following is the definition of a generic constraint and the associated predicate
154+
155+
.. code-block::
156+
157+
// Primitive predicate
158+
class Pred;
159+
160+
// Generic constraint
161+
class Constraint<Pred pred> {
162+
Pred predicate = pred;
163+
}
164+
165+
Shader Model version is represented as follows:
166+
167+
.. code-block::
168+
169+
// Abstract class to represent major and minor version values
170+
class Version<int major, int minor> {
171+
int Major = major;
172+
int Minor = minor;
173+
}
174+
175+
// Valid Shader model version records
176+
177+
// Definition of Shader Model 6.0 - 6.8 and DXIL Version 1.0 - 1.8
178+
foreach i = 0...8 in {
179+
def SM6_#i : Version<6, i>;
180+
def DX1_#i : Version<1, i>;
181+
}
182+
183+
A shader model version predicate class is defined as
184+
185+
.. code-block::
186+
187+
class SMVersion<Version ver> : Pred {
188+
Version SMVersion = ver;
189+
}
190+
191+
A constraint class to represent overload types and shader stages predicated on shader
192+
model version is defined as
193+
194+
.. code-block::
146195
147-
let OpClass = unary, DXILVer = DXVer1_0 in {
148-
def Cos : DXILOpProperties<12, int_cos, [llvm_half_ty, llvm_float_ty],
149-
"Returns cosine(theta) for theta in radians.">;
150-
def Sin : DXILOpProperties<13, int_sin, [llvm_half_ty, llvm_float_ty],
151-
"Returns sine(theta) for theta in radians.">;
152-
}
196+
class SMVersionConstraints<SMVersion smver, dag oloads, dag stages> : Constraint<smver> {
197+
dag overload_types = oloads;
198+
dag stage_kinds = stages;
199+
}
200+
201+
The ``dag overload_types`` and ``dag shader_kinds`` use a special markers ``overloads``
202+
and ``stages``, respectively.
203+
204+
Examples of Constraints
205+
-----------------------
206+
207+
Consider a DXIL Operation that is valid in Shader Model 6.2 and later,
208+
209+
1. with valid overload types ``half``, ``float``, ``i16`` and ``i32``
210+
2. is valid for stages ``pixel`` and ``compute``
211+
3. with valid overload types ``double`` and ``i614`` if Shader Model version 6.3 and later
212+
4. is valid for all stages if Shader Model version 6.3 and later
213+
214+
This is represented as
215+
216+
.. code-block::
217+
218+
[SMVersionConstraints<SMVersion<SM6_2>,
219+
(overloads llvm_half_ty, llvm_float_ty, llvm_i16_ty, llvm_i32_ty),
220+
(stages pixel, compute)>,
221+
SMVersionConstraints<SMVersion<SM6_3>,
222+
(overloads llvm_half_ty, llvm_float_ty, llvm_double_ty,
223+
llvm_i16_ty, llvm_i32_ty, llvm_i64_ty),
224+
(stages allKinds)>];
225+
226+
Consider a DXIL operation that is valid in Shader Model version 6.2 and later,
227+
228+
1. with no overload types, i.e., all argument typess and result type are fixed.
229+
2. is valid for all stages.
230+
231+
This is represented as
232+
233+
.. code-block::
234+
235+
[SMVersionConstraints<SMVersion<SM6_2>, (overloads), (stages allKinds)>];
236+
237+
238+
Specifying attributes predicated on Shader Model version using the single field
239+
``sm_constraints`` not only allows for all of them to be specified together but
240+
also allows for a single place to specify minimum shader model version that supports
241+
the operation. Thus, a separate fiels is not needed to specify minimum shader model
242+
version.
243+
244+
Attribute Specification
245+
=======================
246+
247+
DXIL Operation attributes that are not predicated on any constraint, are represented as
248+
a ``dag`` of Attribute records of the following abstract ``DXILAttributes`` class.
249+
250+
.. code-block::
251+
252+
class DXILAttributes;
253+
254+
Following example records represent memory attributes
255+
256+
.. code-block::
257+
258+
def ReadOnly : DXILOpAttributes;
259+
def ReadNone : DXILOpAttributes;
260+
261+
DXIL Operation Specification Example
262+
====================================
263+
Following illustrates the specification of the DXIL Op ``Sin``
264+
265+
.. code-block::
266+
267+
def Sin : DXILOp {
268+
let Doc ="Returns sine(theta) for theta in radians.";
269+
let OpCode = 13;
270+
let OpClass = unary;
271+
let LLVMIntrinsic = int_sin;
272+
let arguments = (ins LLVMMatchType<0>);
273+
let result = (out dxil_overload_ty);
274+
let sm_constraints = [SMVersionConstraints<SMVersion<SM6_0>,
275+
(overloads llvm_half_ty, llvm_float_ty),
276+
(stages allKinds)>];
277+
let attributes = (attrs ReadNone);
278+
let DXILVersion = DX1_0;
279+
}
153280
154281
Summary
155282
=======
156283

157284
This note sketches the design of a readable and maintainable TableGen specification of
158285
DXIL Ops in ``DXIL.td`` intended to serve as a single source of reference for TableGen
159-
backends (such as ``DXILEmitter``) that generates C++ representations used in DXIL
286+
backends (such as ``DXILEmitter``) that generate C++ representations used in DXIL
160287
backend passes.

0 commit comments

Comments
 (0)