[llvm] d857061 - [DirectX][DXIL] Update DXIL Op TableGen Specification (#95807)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 19 11:41:32 PDT 2024


Author: S. Bharadwaj Yadavalli
Date: 2024-06-19T14:41:28-04:00
New Revision: d85706198bfbc838d204f86e53e9a534166644b8

URL: https://github.com/llvm/llvm-project/commit/d85706198bfbc838d204f86e53e9a534166644b8
DIFF: https://github.com/llvm/llvm-project/commit/d85706198bfbc838d204f86e53e9a534166644b8.diff

LOG: [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.

Added: 
    

Modified: 
    llvm/docs/DirectX/DXILOpTableGenDesign.rst

Removed: 
    


################################################################################
diff  --git a/llvm/docs/DirectX/DXILOpTableGenDesign.rst b/llvm/docs/DirectX/DXILOpTableGenDesign.rst
index 2b1e0901b5061..5f3ac75e82494 100644
--- a/llvm/docs/DirectX/DXILOpTableGenDesign.rst
+++ b/llvm/docs/DirectX/DXILOpTableGenDesign.rst
@@ -14,147 +14,274 @@ Introduction
 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>`_:
+<https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#operations>`_:
 
 #. 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.
 
-Following is the complete list of properties of DXIL Ops with the corresponding field name
-as used in ``hctdb.py``. A DXIL Op is represented by a set of associated properties. These
-are categorized into two groups - viz., those that are (1) consumed in DXIL backend passes
-and (2) consumed in other usage scenarios such as validation, DXIL reader, etc.
+Following is the complete list of attributes of DXIL Ops with the corresponding field name
+as used in ``hctdb.py``. A DXIL Op is represented by a set of associated attributes. These
+are consumed in DXIL backend passes as well as in other usage scenarios such as validation, 
+DXIL reader, etc.
 
-A. Properties consumed in DXIL backend passes
+A. Attributes consumed in DXIL backend passes
 
    1. Name of operation (``dxil_op``)
-   2. The generic or HLSL-specific intrinsic that maps to the operation (``llvm_name``).
-   3. Unique Integer ID (``dxil_opid``)
-   4. Operation Class signifying the name and function signature of the operation (``dxil_class``).
-      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.
-   5. List of valid overload types for the operation (``oload_types``).
-   6. Required DXIL Version with support for the operation.
-   7. A string that documents the operation (``doc``) - This is not strictly necessary but is included
+   2. A string that documents the operation (``doc``) - This is not strictly necessary but is included
       for readability and documentation of the operation.
-
-B. Properties consumed in other usage scenarios
-
-   1. Required minimum Shader Model (``shader_model``).
-   2. Minimum shader model required with translation by linker (``shader_model_translated``)
-   3.  List of shader stages applicable to (``shader_stages``), empty for all.
-   4.  Memory access attributes of the operation (``fn_attr``).
-   5.  Boolean attributes of operation to indicate if it
-
-       * is some kind of a derivative (``is_derivative``)
-       * requires gradient calculation (``is_gradient``)
-       * is a sampler feedback (``is_feedback``)
-       * requires in-wave, cross-lane functionality (``is_wave``)
-       * requires that all of its inputs are uniform across the wave (``requires_uniform_inputs``).
-       * is a barrier operation (``is_barrier``).
+   3. The generic or HLSL-specific intrinsic that maps to the operation (``llvm_name``).
+   4. Unique Integer ID (``dxil_opid``)
+   5. Operation Class signifying the name and function signature of the operation (``dxil_class``).
+      This string is an integral part of the DXIL Op function name and is constructed in
+      the format ``dx.op.<class-name>.<overload-type>``. Each DXIL Op call target function name 
+      is required to conform to this format per existing contract with the driver.
+   6. List of valid overload types for the operation (``oload_types``).
+   7. Required DXIL Version with support for the operation.
+   8. Required minimum Shader Model (``shader_model``).
+   9. Minimum shader model required with translation by linker (``shader_model_translated``)
+   10.  List of shader stages applicable to (``shader_stages``), empty, if applicable to all stages.
+   11.  Memory access attributes of the operation (``fn_attr``).
+   12.  Boolean attributes of operation to indicate if it
+
+        * is some kind of a derivative (``is_derivative``)
+        * requires gradient calculation (``is_gradient``)
+        * is a sampler feedback (``is_feedback``)
+        * requires in-wave, cross-lane functionality (``is_wave``)
+        * requires that all of its inputs are uniform across the wave (``requires_uniform_inputs``).
+        * is a barrier operation (``is_barrier``).
 
 Motivation
 ==========
 
-DXIL backend passes depend on various properties of DXIL Operations. For example, ``DXILLowering``
+DXIL backend passes depend on various attributes of DXIL Operations. For example, ``DXILOpLowering``
 pass will need information such as the DXIL operation an LLVM intrinsic is to be lowered to,
 along with valid overload and parameter types etc. The TableGen file -
 ``llvm/lib/Target/DirectX/DXIL.td`` - is used to represent DXIL Operations
-by specifying their properties listed above. ``DXIL.td`` is designed to be the single source
-of reference of DXIL Operations for DXIL backend implementation in ``llvm-project`` repo -
-analogous to ``hctdb.py`` for ``DirectXShadeCompiler`` repo. It needs to have a rich
-representation capabilities that TableGen backends (such as ``DXILEmitter``) can rely on.
-Additionally, the DXIL Op specification should be easy to read and comprehend.
+by specifying their attributes listed above. ``DXIL.td`` is designed to be the single source
+of reference of DXIL Operations primarily for the implementation of passes in DXIL backend in 
+``llvm-project`` repo - analogous to ``hctdb.py`` for ``DirectXShadeCompiler`` repo. However, 
+the current design does not intend to encapsulate various validation rules, present in ``hctdb.py``, 
+but do not pertain to DXIL Operations. It needs to have a rich representation capabilities that 
+TableGen backends (such as ``DXILEmitter``) can rely on. Additionally, the DXIL Op specification 
+should be easy to read and comprehend.
 
-This note focuses on specification of the set of properties consumed by DXIL backend
-passes identified above in category A. Any of the properties from category B are expected to be
-included as deemed necessary during implementation.
+This note provides the design of the specification DXIL Ops as TableGen class ``DXILOp``
+by specifying its attributes identified above.
 
-Design
-======
+DXIL Operation Specification
+============================
+
+The DXIL Operation is represented using the TableGen class ``DXILOp``. The DXIL operation
+attributes are specified as fields of the ``DXILOp`` class as described below.
 
 1. Each DXIL Operation is represented as a TableGen record. The name of each of the records
    signifies operation name.
-2. The LLVM Intrinsic that maps to the operation is represented using ``Intrinsic::*``.
-3. The unique operation id is represented by an integer.
-4. DXIL Operation Class is represented as follows
+2. A documentation string for the operation.
+3. The LLVM Intrinsic that maps to the operation is represented as ``Intrinsic`` defined in
+   `Intrinsics.td <https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/IR/Intrinsics.td>`_.
+4. The unique operation id is represented by an integer.
+5. DXIL Operation Class is represented as follows
 
    .. code-block::
 
         // Abstraction of DXIL Operation class.
-        // It encapsulates an associated function signature viz.,
-        // returnTy(param1Ty, param2Ty, ...) represented as a list of LLVMTypes.
-        // DXIL Ops that belong to a DXILOpClass record the signature of that DXILOpClass
-
-        class DXILOpClass<list<LLVMType> OpSig> {
-          list<LLVMType> OpSignature = OpSig;
-        }
+        class DXILOpClass;
 
-   Concrete operation classes, such as ``unary`` are defined inheriting from ``DXILOpClass``.
-5. Valid overload types are represented as a list of ``LLVMType``.
-6. Concrete records of DXIL versions and are defined by inheriting from the class
+   Concrete operation records, such as ``unary`` are defined by inheriting from ``DXILOpClass``.
+6. Return and argument types of the operation are represented as ``dag``s using the
+   special markers ``out`` and ``ins``. An overload type, if supported by the operation, is
+   denoted as the positional type ``dxil_overload_ty`` in the argument or in the result, where
+   ``dxil_overload_ty`` is defined to be synonymous to ``llvm_any_ty``.
 
    .. code-block::
 
-        // Abstract class to represent major and minor version values
-        class Version<int major, int minor> {
-          int Major = major;
-          int Minor = minor;
-        }
+      defvar dxil_overload_ty = llvm_any_ty
 
-7. A documentation string for the operation.
 
+7. Valid overload types and shader stages predicated on Shader Model version are specified
+   as a list of ``Constraint`` records. Representation of ``Constraints`` class is described
+   a later section.
+8. Various attributes of the DXIL Operation that are not predicated on Shader Model version
+   are represented as a ``dag`` using the special marker ``attrs``. Representation of ``Attributes`` 
+   class is described in a later section.
 
 A DXIL Operation is represented by the following TableGen class by encapsulating the various
-TableGen representations of its properties described above.
+TableGen representations of its attributes described above.
 
 .. code-block::
 
-  // Abstraction DXIL Operation
-  class DXILOpPropertiesBase {
-    int OpCode = 0;                           // Opcode of DXIL Operation
-    DXILOpClass OpClass = UnknownOpClass;     // Class of DXIL Operation.
-    Intrinsic LLVMIntrinsic = ?;              // LLVM Intrinsic DXIL Operation maps to
-    list<LLVMType> OpOverloadTypes = ?; // Valid overload type
-                                              // of DXIL Operation
-    Version DXILVer = ?;                      // Min DXIL version
-    string Doc = "";                          // A short description of the operation
-  }
+   // Abstraction DXIL Operation
+   class DXILOp {
+     // A short description of the operation
+     string Doc = "";
+
+     // Opcode of DXIL Operation
+     int OpCode = 0;
+
+     // Class of DXIL Operation.
+     DXILOpClass OpClass = UnknownOpClass;
+
+     // LLVM Intrinsic DXIL Operation maps to
+     Intrinsic LLVMIntrinsic = ?;
 
+     // Dag containing the arguments of the op. Default to 0 arguments.
+     dag arguments = (ins);
 
-The following convenience class, definitions of ``unary`` and ``DXVer1_0`` are used to
-illustrate the definitions of ``Sin`` and ``Cos`` operations:
+     // Results of the op. Default to 0 results.
+     dag result = (out);
 
-  .. code-block::
+     // List of constraints predicated on Shader Model version
+     list<SMVersionConstraints> sm_constraints;
 
-      class DXILOpProperties<int opCode,
-                    Intrinsic intrinsic,
-                    list<LLVMType> overloadTypes,
-                    string doc> : DXILOpPropertiesBase {
-        int OpCode = opCode;
-        Intrinsic LLVMIntrinsic = intrinsic;
-        list<LLVMType> OpOverloadTypes = overloadTypes;
-        string Doc = doc;
-      }
+     // Non-predicated operation attributes
+     dag attrtibutes = (attrs);
+     Version DXILVersion = ?;
+   }
 
-      def unary : DXILOpClass<[llvm_any_ty, LLVMMatchType<0>]>;
-      def DXVer1_0 : Version<1, 0>;
+Constraint Specification
+========================
+
+DXIL Operation attributes such as valid overload types and valid shader stages are
+predicated on Shader Model version. These are represented as list of constrained
+attributes.
+
+Following is the definition of a generic constraint and the associated predicate
+
+.. code-block::
+
+   // Primitive predicate
+   class Pred;
+
+   // Generic constraint
+   class Constraint<Pred pred> {
+     Pred predicate = pred;
+   }
+
+Shader Model version is represented as follows:
+
+.. code-block::
+
+   // Abstract class to represent major and minor version values
+   class Version<int major, int minor> {
+     int Major = major;
+     int Minor = minor;
+   }
+
+   // Valid Shader model version records
+
+   // Definition of Shader Model 6.0 - 6.8 and DXIL Version 1.0 - 1.8
+   foreach i = 0...8 in {
+     def SM6_#i : Version<6, i>;
+     def DX1_#i : Version<1, i>;
+   }
+
+A shader model version predicate class is defined as
+
+.. code-block::
+
+   class SMVersion<Version ver> : Pred {
+     Version SMVersion = ver;
+   }
+
+A constraint class to represent overload types and shader stages predicated on shader
+model version is defined as
+
+.. code-block::
 
-      let OpClass = unary, DXILVer = DXVer1_0 in {
-        def Cos  : DXILOpProperties<12, int_cos, [llvm_half_ty, llvm_float_ty],
-                                   "Returns cosine(theta) for theta in radians.">;
-        def Sin  : DXILOpProperties<13, int_sin, [llvm_half_ty, llvm_float_ty],
-                                   "Returns sine(theta) for theta in radians.">;
-      }
+   class SMVersionConstraints<SMVersion smver, dag oloads, dag stages> : Constraint<smver> {
+     dag overload_types = oloads;
+     dag stage_kinds = stages;
+   }
+
+The ``dag overload_types`` and ``dag shader_kinds`` use a special markers ``overloads``
+and ``stages``, respectively.
+
+Examples of Constraints
+-----------------------
+
+Consider a DXIL Operation that is valid in Shader Model 6.2 and later,
+
+1. with valid overload types ``half``, ``float``, ``i16`` and ``i32``
+2. is valid for stages ``pixel`` and ``compute``
+3. with valid overload types ``double`` and ``i614`` if Shader Model version 6.3 and later
+4. is valid for all stages if Shader Model version 6.3 and later
+
+This is represented as
+
+.. code-block::
+
+   [SMVersionConstraints<SMVersion<SM6_2>,
+                          (overloads llvm_half_ty, llvm_float_ty, llvm_i16_ty, llvm_i32_ty),
+                          (stages pixel, compute)>,
+    SMVersionConstraints<SMVersion<SM6_3>,
+                          (overloads llvm_half_ty, llvm_float_ty, llvm_double_ty,
+                                 llvm_i16_ty, llvm_i32_ty, llvm_i64_ty),
+                          (stages allKinds)>];
+
+Consider a DXIL operation that is valid in Shader Model version 6.2 and later,
+
+1. with no overload types, i.e., all argument typess and result type are fixed.
+2. is valid for all stages.
+
+This is represented as
+
+.. code-block::
+
+     [SMVersionConstraints<SMVersion<SM6_2>, (overloads), (stages allKinds)>];
+
+
+Specifying attributes predicated on Shader Model version using the single field 
+``sm_constraints`` not only allows for all of them to be specified together but
+also allows for a single place to specify minimum shader model version that supports
+the operation. Thus, a separate fiels is not needed to specify minimum shader model 
+version.
+
+Attribute Specification
+=======================
+
+DXIL Operation attributes that are not predicated on any constraint, are represented as
+a ``dag`` of Attribute records of the following abstract ``DXILAttributes`` class.
+
+.. code-block::
+
+  class DXILAttributes;
+
+Following example records represent memory attributes 
+
+.. code-block::
+
+  def ReadOnly : DXILOpAttributes;
+  def ReadNone : DXILOpAttributes;
+
+DXIL Operation Specification Example
+====================================
+Following illustrates the specification of the DXIL Op ``Sin``
+
+.. code-block::
+
+  def Sin  : DXILOp {
+    let Doc ="Returns sine(theta) for theta in radians.";
+    let OpCode = 13;
+    let OpClass = unary;
+    let LLVMIntrinsic = int_sin;
+    let arguments = (ins LLVMMatchType<0>);
+    let result = (out dxil_overload_ty);
+    let sm_constraints = [SMVersionConstraints<SMVersion<SM6_0>,
+                          (overloads llvm_half_ty, llvm_float_ty),
+                          (stages allKinds)>];
+    let attributes = (attrs ReadNone);
+    let DXILVersion = DX1_0;
+  }
 
 Summary
 =======
 
 This note sketches the design of a readable and maintainable TableGen specification of
 DXIL Ops in ``DXIL.td`` intended to serve as a single source of reference for TableGen
-backends (such as ``DXILEmitter``) that generates C++ representations used in DXIL
+backends (such as ``DXILEmitter``) that generate C++ representations used in DXIL
 backend passes.


        


More information about the llvm-commits mailing list