Skip to content

Commit 531550e

Browse files
committed
Delete discarded options and flesh out the proposed design option.
Also incorporate PR suggestion to add descriptions of all properties of DXIL Operations.
1 parent 8d0073a commit 531550e

File tree

1 file changed

+120
-163
lines changed

1 file changed

+120
-163
lines changed

llvm/docs/DirectX/DXILOpTableGenDesign.rst

Lines changed: 120 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -19,207 +19,164 @@ DXIL Operations are represented in one of the following `two ways
1919
#. Using LLVM instructions
2020
#. Using LLVM External functions. These are represented in LLVM IR as follows:
2121

22-
* "Standard" LLVM intrinsics (e.g., ``llvm.sin.*``) and
23-
* HLSL intrinsics (defined as LLVM intrinsics in ``llvm/include/llvm/IR/IntrinsicsDirectX.td``, e.g., ``llvm.dx.*``)
24-
25-
These are collectively referred to as `LLVM Intrinsics` in this note.
26-
27-
DXIL Ops, as currently represented in ``hctdb.py`` have the following attributes
28-
29-
#. ``name`` - A short, unique name
30-
#. ``llvm_id`` - ID of LLVM instruction. This is just an arbitrary, yet fixed, number that indicates LLVM's ``CallInst`` for all LLVM intrinsics
31-
#. ``llvm_name`` - String name of LLVM instruction type
32-
#. ``is_dxil_op`` - A bool indicating whether this is a call into a built-in DXIL function
33-
#. ``dxil_op`` - String name of DXIL operation
34-
#. ``dxil_opid`` - ID of DXIL operation
35-
#. ``dxil_class`` - String name of the opcode class
36-
#. ``category`` - String classification for this instruction
37-
#. ``doc`` - String documentation description of this instruction
38-
#. ``remarks`` - String long-form remarks on this instruction
39-
#. ``ops`` - List of operands that this instruction takes
40-
#. ``is_allowed`` - Bool indicating whether this instruction is allowed in a DXIL program
41-
#. ``oload_types`` - String denoting overload types if applicable (e.g., "hf", "iwl")
42-
#. ``fn_attr`` - Attribute shorthand strings: rn=does not access memory,ro=only reads from memory,
43-
#. ``is_deriv`` - Bool indicating whether this is some kind of derivative
44-
#. ``is_gradient`` - Bool indicating whether this requires a gradient calculation
45-
#. ``is_feedback`` - Bool indicating whether this is a sampler feedback op
46-
#. ``is_wave`` - Bool indicating whether this requires in-wave, cross-lane functionality
47-
#. ``requires_uniform_inputs`` - Bool indicating whether this operation requires that all of its inputs are uniform across the wave
48-
#. ``is_barrier`` - Bool indicating whether this is a barrier operation
49-
#. ``shader_stages`` - shader stages to which this applies, empty for all.
50-
#. ``shader_model`` - minimum shader model required (e.g., 6, 0)
51-
#. ``inst_helper_prefix`` - None
52-
#. ``fully_qualified_name_prefix`` - Constant string ``"hlsl::OP::OpCode"``
53-
#. ``is_dxil_op`` - Bool that evaluates (dxil_op != "") indicating whether this is a DXIL operation
54-
#. ``is_reserved`` - Bool that evaluates (dxil_class == "Reserved")
55-
#. ``shader_model_translated`` - minimum shader model required with translation by linker
56-
#. ``props`` - extra properties
57-
58-
Core DXIL Operation information is encapsulated in ``utils/hct/hctdb.py``. Additional
59-
refinements of this information, such as supported overload types specific to
60-
Shader Model version, is embedded in various other source locations in
61-
`DirectXShaderCompiler <https://github.com/microsoft/DirectXShaderCompiler>`_
62-
repo. Additional conditions that refine the DXIL Op properties are also encoded
63-
in the DXIL Validator component.
22+
* "Standard" LLVM intrinsics (e.g., ``llvm.sin.*``) and
23+
* HLSL intrinsics (defined as LLVM intrinsics in ``llvm/include/llvm/IR/IntrinsicsDirectX.td``, e.g., ``llvm.dx.*``)
24+
25+
These are collectively referred to as `LLVM Intrinsics` in this note.
26+
27+
Following is the complete list of properties of DXIL Ops with the corresponding field name
28+
as used in ``hctdb.py``, if one exists. A DXIL Op is represented by a set of associated properties
29+
30+
1. Name of operation (``dxil_op``)
31+
2. The generic or HLSL-specific intrinsic that maps to the operation (``llvm_name``).
32+
3. Unique Integer ID (``dxil_opid``)
33+
4. Operation Class signifying the name and function signature of the operation (``dxil_class``).
34+
This string is an integral part of the DXIL Op function name and is constructed in
35+
the format ``dx.op.<class-name>.<overload-type>``. The DXIL validator checks for any
36+
deviation from this for each of the DXIL Op call.
37+
38+
5. List of valid overload types for the operation (``oload_types``).
39+
6. Required minimum Shader Model version with support for the operation. (``shader_model``).
40+
7. Required minimum DXIL version with support for the operation.
41+
8. Minimum shader model required with translation by linker (``shader_model_translated``)
42+
9. List of shader stages the operation is applicable to (``shader_stages``); empty if applicable to all stages.
43+
10. Memory access attributes of the operation (``fn_attr``).
44+
11. Boolean attributes of operation to indicate if it
45+
46+
* is some kind of a derivative (``is_derivative``)
47+
* requires gradient calculation (``is_gradient``)
48+
* is a sampler feedback (``is_feedback``)
49+
* requires in-wave, cross-lane functionality (``is_wave``)
50+
* requires that all of its inputs are uniform across the wave (``requires_uniform_inputs``).
51+
* is a barrier operation (``is_barrier``).
52+
53+
12. A string that documents the operation (``doc``)
6454

6555
Motivation
6656
==========
6757

68-
``DXILLowering`` pass needs to lower the LLVM intrinsics. TableGen file -
69-
``llvm/lib/Target/DirectX/DXIL.td`` - is used to specify the properties of DXIL
70-
Ops including the mapping of each of them to LLVM intrinsics they correspond to,
71-
if any. This purpose is served by ``utils/hct/hctdb.py`` in ``DirectXShaderCompiler``
72-
repo. Analogously, ``DXIL.td`` is planned to be the single source of reference
73-
for the properties and LLVM intrinsic mapping of DXIL Ops for DXIL backend
74-
implementation in ``llvm-project`` repo. Additionally, the refinements of DXIL Op
75-
properties based on aspects such as target Shader Model version, Shader kind (viz.,
76-
Compute, Pixel, Vertex etc) should also be represented in TableGen specification
77-
of DXIL Ops - as much as possible. This will allow generation of valid DXIL code
78-
in all passes and potentially not require (or reduce the complexity of) a post-compile
79-
validation step that ensures valid DXIL binary.
80-
81-
As a result, specification in ``DXIL.td`` needs to have a rich representation
82-
abilities that TableGen backends (such as ``DXILEmitter``) can rely on. The DXIL
83-
Op specification should be declarative - as much as possible - making it
84-
easy to comprehend and amenable to specification of constraints that refine
85-
DXIL Op properties.
86-
87-
.. _DXIL Operation Attributes:
88-
89-
DXIL Operation Attributes
90-
=========================
91-
92-
Distilling the essential attributes of DXIL Op from the above, following
93-
attributes form the core of its specification.
94-
95-
#. ``dxil_opid`` or ``OpCode``
96-
#. ``dxil_class`` or ``OpClass`` - this string is an integral part of the DXIL Op
97-
function name and is constructed in the format ``dx.op.<class-name>.<overload-type>``.
98-
The DXIL validator checks for any deviation from this for each of the DXIL Op call.
99-
#. ``ops`` - list of operands encapsulating the index and valid (fixed or overload) types
100-
#. ``oload_types`` - Valid overload types of the DXIL op
101-
#. Rest of the attributes represented using ``is_*`` booleans along with
102-
``shader_model_translated`` and ``shader_stages``
103-
104-
Each of the LLVM intrinsics maps to an function represented by a call to an
105-
external function of the form ``dx.op.<class-name>.<overload-type>`` as noted above.
106-
107-
TableGen Specification
108-
======================
109-
110-
Shader Model
111-
^^^^^^^^^^^^
112-
113-
DirectX Shader Models are distinguished by their ``major.minor`` number.
114-
This is represented by the following TableGen class.
58+
DXIL backend passes depend on the knowledge of various properties of DXIL Operations.
59+
For example, ``DXILLowering`` pass will need information such as the DXIL operation an
60+
LLVM intrinsic is to be lowered to, along with valid overload and parameter types etc.
61+
TableGen file - ``llvm/lib/Target/DirectX/DXIL.td`` - is used to represent DXIL Operations
62+
by specifying their properties listed above. ``DXIL.td`` is designed to be the single source
63+
of reference of DXIL Operations for DXIL backend implementation in ``llvm-project`` repo -
64+
analogous to ``hctdb.py`` for ``DirectXShadeCompiler`` repo. It needs to have a rich
65+
representation capabilities that TableGen backends (such as ``DXILEmitter``) can rely on.
66+
Additionally, the DXIL Op specification should be easy to read and comprehend.
11567

116-
.. code-block::
68+
Design
69+
======
11770

118-
class DXILShaderModel<int major, int minor> {
119-
int Major = major;
120-
int Minor = minor;
121-
}
71+
1. Each DXIL Operation is represented as a TableGen record. The name of each of the records
72+
signifies operation name.
73+
2. The LLVM Intrinsic that maps to the operation is represented using ``Intrinsic::*``.
74+
3. The unique operation id is represented by an integer.
75+
4. DXIL Operation Class is represented as follows
12276

123-
Each of the valid shader models is defined as TableGen records. For
124-
example following is the definition of SM 6.0 and SM 6.2,
77+
.. code-block::
12578
126-
.. code-block::
79+
// Abstraction of DXIL Operation class.
80+
// It encapsulates an associated function signature viz.,
81+
// returnTy(param1Ty, param2Ty, ...) represented as a list of LLVMTypes.
82+
// DXIL Ops that belong to a DXILOpClass record the signature of that DXILOpClass
12783
128-
// Shader Model 6.x
129-
def SM6_0 : DXILShaderModel<6, 0>;
130-
def SM6_2 : DXILShaderModel<6, 2>;
84+
class DXILOpClass<list<LLVMType> OpSig> {
85+
list<LLVMType> OpSignature = OpSig;
86+
}
13187
132-
DXIL Class
133-
^^^^^^^^^^
88+
Concrete operation classes, such as ``unary`` are defined inheriting from ``DXILOpClass``.
89+
5. Valid overload types are represented as a list of ``LLVMType`` s.
90+
6. Concrete records of Shader Model version and DXIL versions and are defined
91+
by inheriting from the class
13492

135-
Each DXIL Op belongs to a class represented by ``dxil_class`` field value. A
136-
DXIL class represents DXIL Ops with the same function prototype (or signature).
137-
This is represented using the following TableGen class.
93+
.. code-block::
13894
139-
.. code-block::
95+
// Abstract class to represent major and minor version values
96+
class Version<int major, int minor> {
97+
int Major = major;
98+
int Minor = minor;
99+
}
140100
141-
class DXILOpClass<list<LLVMType> OpSig> {
142-
list<LLVMType> OpSignature = OpSig;
143-
}
101+
7. Shader stages for which the operation is applicable are represented as a list of
102+
concrete records that inherit from the Class
144103

145-
Each of the valid classes is represented by a concrete TableGen record.
146-
For example, following is the definition of the ``unary`` class
104+
.. code-block::
147105
148-
.. code-block::
106+
class ShaderStage;
149107
150-
def unary : DXILOpClass<[llvm_any_ty, LLVMMatch<0>]>;
151108
109+
8. All remaining properties of the operation are represented as a list as of concrete records
110+
that inherit from the class
152111

153-
Overload Types
154-
^^^^^^^^^^^^^^
112+
.. code-block::
155113
156-
Each DXIL Op has a set of valid overload types denoted by ``oload_types``.
157-
Valid overload types of a DXIL OP are represented as a list. However, overload
158-
types supported by DXIL Ops may vary depending on minimum target shader model
159-
version. So, the list of supported overload types are tagged with the minimum
160-
shader model in which they are valid for the DXIL Op being specified.
161-
Following TableGen class is defined to encapsulate such as representation.
114+
class OpAttributes;
162115
163-
.. code-block::
116+
- memory access - ``ReadNone``, ``ReadNone``
117+
- ``IsDerivative``, ``IsGradient``, ``IsFeedback``, ``IsWave``, ``NeedsUniformInputs``, ``IsBarrier``
164118

165-
class DXILOpOverload<DXILShaderModel minsm, list<LLVMType> overloads> {
166-
DXILShaderModel ShaderModel = minsm;
167-
list<LLVMType> OpOverloads = overloads;
168-
}
119+
9. A documentation string for the operation.
169120

170-
Specification of DXIL Operation
171-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
172121

173-
Specification of DXIL Op is abstracted using the following TableGen class to
174-
represent the core attributes outlined in `DXIL Operation Attributes`_ section.
122+
A DXIL Operation is represented by the following TableGne class by encapsulating the various
123+
TableGen representations of its properties described above.
175124

176125
.. code-block::
177126
178-
// Abstraction DXIL Operation to LLVM intrinsic
179-
class DXILOpMappingBase {
180-
int OpCode = 0; // Opcode of DXIL Operation
181-
DXILOpClass OpClass = UnknownOpClass;// Class of DXIL Operation.
182-
Intrinsic LLVMIntrinsic = ?; // LLVM Intrinsic DXIL Operation maps to
183-
list<DXILOpOverload> OpOverloadTypes = ?; // Valid overload type
184-
// of DXIL Operation
185-
string Doc = ""; // A short description of the operation
127+
// Abstraction DXIL Operation
128+
class DXILOpPropertiesBase {
129+
int OpCode = 0; // Opcode of DXIL Operation
130+
DXILOpClass OpClass = UnknownOpClass; // Class of DXIL Operation.
131+
Intrinsic LLVMIntrinsic = ?; // LLVM Intrinsic DXIL Operation maps to
132+
list<LLVMType> OpOverloadTypes = ?; // Valid overload type
133+
// of DXIL Operation
134+
Version SMVer = ?; // Min Shader Model version
135+
Version SMVerLinker = ?; // Min Shader Model required for linking
136+
Version DXILVer = ?; // Min DXIL version
137+
list<ShaderStage> ShaderStages = ?; // List of applicable shader stages
138+
list<OpAttributes> OpAttribs = ?; // Operation attributes
139+
string Doc = ""; // A short description of the operation
186140
}
187141
188-
Following is a convenience TableGen class that inherits from ``DXILOpMappingBase``
189-
with templatized parameters. It is used to define various DXIL Ops.
190142
191-
.. code-block::
143+
The following convenience class is used to demonstrate the definitions of a couple of
144+
operations:
192145

193-
class DXILOpMapping<int opCode,
146+
.. code-block::
147+
148+
class DXILOpProperties<int opCode,
194149
Intrinsic intrinsic,
195-
list<DXILOpOverload> overloadTypes,
196-
string doc> : DXILOpMappingBase {
197-
int OpCode = opCode;
198-
Intrinsic LLVMIntrinsic = intrinsic;
199-
list<DXILOpOverload> OpOverloadTypes = overloadTypes;
200-
string Doc = doc;
201-
}
150+
list<LLVMType> overloadTypes,
151+
string doc> : DXILOpPropertiesBase {
152+
int OpCode = opCode;
153+
Intrinsic LLVMIntrinsic = intrinsic;
154+
list<LLVMType> OpOverloadTypes = overloadTypes;
155+
string Doc = doc;
156+
}
202157
203-
The DXIL Op ``Sin`` is defined as follows:
158+
Additionally, following definition of ``unary`` class is also used:
204159

205160
.. code-block::
206161
207-
let OpClass = unary in
208-
def Sin : DXILOpMapping<13, int_sin,
209-
[DXILOpOverload<SM6_3, [llvm_half_ty, llvm_float_ty]>,
210-
DXILOpOverload<SM6_0, [llvm_float_ty]>],
211-
"Returns sine(theta) for theta in radians.">;
162+
def unary : DXILOpClass<[llvm_any_ty, LLVMMatchType<0>]>;
212163
164+
Following is the definition of ``Sin`` and ``Cos``
213165

214-
Note that validity of overload type ``float`` in SM 6.0 and later, and
215-
that of ``half`` and ``float`` in SM 6.2 and later, is specified.
166+
.. code-block::
167+
168+
let OpClass = unary in {
169+
def Cos : DXILOpProperties<12, int_cos, [llvm_half_ty, llvm_float_ty],
170+
"Returns cosine(theta) for theta in radians.">;
171+
def Sin : DXILOpProperties<13, int_sin, [llvm_half_ty, llvm_float_ty],
172+
"Returns sine(theta) for theta in radians.">;
173+
}
216174
217175
Summary
218176
=======
219177

220-
This note describes design and implementation of a TableGen representation of
221-
DXIL Ops in ``DXIL.td``. ``DXIL.td`` is intended to (a) serve as a single source
222-
of reference for TableGen backends (such as ``DXILEmitter``- specific to DXIL
223-
backend), (b) have an accurate and rich specification including the ability to
224-
represent refinement constraints, and (c) be declarative as much as possible for
225-
readability and maintainability.
178+
This note discusses the design of TableGen specification of DXIL Ops in ``DXIL.td``
179+
that is intended to serve as a single source of reference for TableGen
180+
backends (such as ``DXILEmitter`` - specific to DXIL backend), have an accurate
181+
and rich specification, be readable and maintainable.
182+

0 commit comments

Comments
 (0)