[llvm] [DirectX][DXIL] Design document for TableGen Spec of DXIL Operations (PR #85170)

Justin Bogner via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 9 16:18:41 PDT 2024


================
@@ -0,0 +1,224 @@
+==============================================================
+Specification of DXIL Operations using TableGen Representation
+==============================================================
+.. contents::
+   :local:
+
+.. toctree
+   :hidden
+
+Introduction
+============
+
+`DirectXShaderCompiler <https://github.com/microsoft/DirectXShaderCompiler>`_
+encapsulates, among other information, various DXIL Operations in
+`hctdb.py <https://github.com/microsoft/DirectXShaderCompiler/blob/main/utils/hct/hctdb.py>`_.
+DXIL Operations are represented in one of the following `two ways
+<https://github.com/microsoft/DirectXShaderCompiler/blob/130877392c263888ef06bab768856d3dab1f1c9a/docs/DXIL.rst#L1978>`_:
+
+#. Using LLVM instructions
+#. Using LLVM External functions. These are represented in LLVM IR as follows:
+
+   * "Standard" LLVM intrinsics (e.g., ``llvm.sin.*``) and
+   * HLSL intrinsics (defined as LLVM intrinsics in ``llvm/include/llvm/IR/IntrinsicsDirectX.td``, e.g., ``llvm.dx.*``)
+
+These are  collectively referred to as `LLVM Intrinsics` in this note.
+
+DXIL Ops, as currently represented in ``hctdb.py`` have the following attributes
+
+#. ``name`` - A short, unique name
+#. ``llvm_id`` - ID of LLVM instruction. This is just an arbitrary, yet fixed, number that indicates LLVM's ``CallInst`` for all LLVM intrinsics
+#. ``llvm_name`` - String name of LLVM instruction type
+#. ``is_dxil_op`` - A bool indicating whether this is a call into a built-in DXIL function
+#. ``dxil_op`` - String name of DXIL operation
+#. ``dxil_opid`` - ID of DXIL operation
+#. ``dxil_class`` - String name of the opcode class
+#. ``category`` - String classification for this instruction
+#. ``doc`` - String documentation description of this instruction
+#. ``remarks`` - String long-form remarks on this instruction
+#. ``ops`` - List of operands that this instruction takes
+#. ``is_allowed`` - Bool indicating whether this instruction is allowed in a DXIL program
+#. ``oload_types`` - String denoting overload types if applicable (e.g., "hf", "iwl")
+#. ``fn_attr`` - Attribute shorthand strings: rn=does not access memory,ro=only reads from memory,
+#. ``is_deriv`` - Bool indicating whether this is some kind of derivative
+#. ``is_gradient`` - Bool indicating whether this requires a gradient calculation
+#. ``is_feedback`` - Bool indicating whether this is a sampler feedback op
+#. ``is_wave``  - Bool indicating whether this requires in-wave, cross-lane functionality
+#. ``requires_uniform_inputs``  - Bool indicating whether this operation requires that all of its inputs are uniform across the wave
+#. ``is_barrier``  - Bool indicating whether this is a barrier operation
+#. ``shader_stages`` - shader stages to which this applies, empty for all.
+#. ``shader_model`` - minimum shader model required (e.g., 6, 0)
+#. ``inst_helper_prefix`` - None
+#. ``fully_qualified_name_prefix`` - Constant string ``"hlsl::OP::OpCode"``
+#. ``is_dxil_op`` - Bool that evaluates (dxil_op != "") indicating whether this is a DXIL operation
+#. ``is_reserved`` - Bool that evaluates (dxil_class == "Reserved")
+#. ``shader_model_translated`` - minimum shader model required with translation by linker
+#. ``props`` - extra properties
+
+Core DXIL Operation information is encapsulated in ``utils/hct/hctdb.py``. Additional
+refinements of this information, such as supported overload types specific to
+Shader Model version, is embedded in various other source locations in
+`DirectXShaderCompiler <https://github.com/microsoft/DirectXShaderCompiler>`_
+repo. Additional conditions that refine the DXIL Op properties are also encoded
+in the DXIL Validator component.
+
+Motivation
+==========
+
+``DXILLowering`` pass needs to lower the LLVM intrinsics. TableGen file -
+``llvm/lib/Target/DirectX/DXIL.td`` - is used to specify the properties of DXIL
+Ops including the mapping of each of them to LLVM intrinsics they correspond to,
+if any. This purpose is served by ``utils/hct/hctdb.py`` in ``DirectXShaderCompiler``
+repo. Analogously, ``DXIL.td`` is planned to be the single source of reference
+for the properties and LLVM intrinsic mapping of DXIL Ops for DXIL backend
+implementation in ``llvm-project`` repo. Additionally, the refinements of DXIL Op
+properties based on aspects such as target Shader Model version, Shader kind (viz.,
+Compute, Pixel, Vertex etc) should also be represented in TableGen specification
+of DXIL Ops - as much as possible. This will allow generation of valid DXIL code
+in all passes and potentially not require (or reduce the complexity of) a post-compile
+validation step that ensures valid DXIL binary.
+
+As a result, specification in ``DXIL.td`` needs to have a rich representation
+abilities that TableGen backends (such as ``DXILEmitter``) can rely on. The DXIL
+Op specification should be declarative - as much as possible - making it
+easy to comprehend and amenable to specification of constraints that refine
+DXIL Op properties.
+
+.. _DXIL Operation Attributes:
+
+DXIL Operation Attributes
+=========================
+
+Distilling the essential attributes of DXIL Op from the above, following
+attributes form the core of its specification.
+
+#. ``dxil_opid`` or ``OpCode``
+#. ``dxil_class`` or ``OpClass`` - this string is an integral part of the DXIL Op
+   function name and is constructed in the format ``dx.op.<class-name>.<overload-type>``.
+   The DXIL validator checks for any deviation from this for each of the DXIL Op call.
+#. ``ops`` - list of operands encapsulating the index and valid (fixed or overload) types
+#. ``oload_types`` - Valid overload types of the DXIL op
+#. Rest of the attributes represented using ``is_*`` booleans along with
+   ``shader_model_translated`` and ``shader_stages``
----------------
bogner wrote:

I find this list a bit confusing. You're trying to explain why some of the fields from the `hctdb.py` field descriptions above are necessary, but it comes off kind of like you're just repeating what the fields are for.

It'd probably be better to phrase this in terms of what we need in DXIL.td and refer back to how that covers the parts of `hctdb.py`'s implementation instead.

> To fully represent the needs of the DXIL Op mapping in LLVM we'll need the following:
> 
> 1. The DXIL operation ID (``dxil_opid`` from ``hctdb.py``)
> 2. The generic or HLSL-specific intrinsic that we're mapping from
> 3. The "operation class" for the op - that is, the name and function signature such that we can construct a function of the ``dx.op.<class-name>.<overload>`` kind that DXIL expects.
> 4. Constraints on overloads, so that we can avoid generating invalid operations that happen to match the operation class
> 5. Constraints on availability per shader model
> 6. Constraints on availability per shader stage (Note: not yet handled by this spec)
> 7. Constaints on XYZ

It would be nice to fill out the list of constraints we'll need to handle for the other `is_*` booleans in `hctdb.py` for completeness, though I am comfortable getting this in with notes saying where this will continue to evolve for now.

https://github.com/llvm/llvm-project/pull/85170


More information about the llvm-commits mailing list