diff --git a/llvm/docs/DirectX/DXILOpTableGenDesign.rst b/llvm/docs/DirectX/DXILOpTableGenDesign.rst new file mode 100644 index 0000000000000..2b1e0901b5061 --- /dev/null +++ b/llvm/docs/DirectX/DXILOpTableGenDesign.rst @@ -0,0 +1,160 @@ +============================================================== +Specification of DXIL Operations using TableGen Representation +============================================================== +.. contents:: + :local: + +.. toctree + :hidden + +Introduction +============ + +`DirectXShaderCompiler `_ +encapsulates, among other information, various DXIL Operations in +`hctdb.py `_. +DXIL Operations are represented in one of the following `two ways +`_: + +#. 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. + +A. Properties 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..``. 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 + 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``). + +Motivation +========== + +DXIL backend passes depend on various properties of DXIL Operations. For example, ``DXILLowering`` +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. + +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. + +Design +====== + +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 + + .. 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 OpSig> { + list OpSignature = OpSig; + } + + 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 + + .. code-block:: + + // Abstract class to represent major and minor version values + class Version { + int Major = major; + int Minor = minor; + } + +7. A documentation string for the operation. + + +A DXIL Operation is represented by the following TableGen class by encapsulating the various +TableGen representations of its properties 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 OpOverloadTypes = ?; // Valid overload type + // of DXIL Operation + Version DXILVer = ?; // Min DXIL version + string Doc = ""; // A short description of the operation + } + + +The following convenience class, definitions of ``unary`` and ``DXVer1_0`` are used to +illustrate the definitions of ``Sin`` and ``Cos`` operations: + + .. code-block:: + + class DXILOpProperties overloadTypes, + string doc> : DXILOpPropertiesBase { + int OpCode = opCode; + Intrinsic LLVMIntrinsic = intrinsic; + list OpOverloadTypes = overloadTypes; + string Doc = doc; + } + + def unary : DXILOpClass<[llvm_any_ty, LLVMMatchType<0>]>; + def DXVer1_0 : Version<1, 0>; + + 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.">; + } + +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 +backend passes.