From 6ae3fc135c689322671a3f520a372c9ef4b1e98b Mon Sep 17 00:00:00 2001 From: Justin Bogner Date: Thu, 15 Aug 2024 00:28:15 +0300 Subject: [PATCH 1/3] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?= =?UTF-8?q?anges=20to=20main=20this=20commit=20is=20based=20on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.5-bogner [skip ci] --- llvm/docs/DirectX/DXILOpTableGenDesign.rst | 28 +- llvm/include/llvm/Analysis/DXILResource.h | 8 + llvm/include/llvm/IR/IntrinsicsDirectX.td | 3 + llvm/include/llvm/Support/DXILABI.h | 17 -- llvm/lib/Target/DirectX/DXIL.td | 279 ++++++++++-------- llvm/lib/Target/DirectX/DXILConstants.h | 5 + llvm/lib/Target/DirectX/DXILOpBuilder.cpp | 132 ++++++--- llvm/lib/Target/DirectX/DXILOpBuilder.h | 34 ++- llvm/lib/Target/DirectX/DXILOpLowering.cpp | 260 ++++++++++++---- llvm/lib/Target/DirectX/DXILOpLowering.h | 27 ++ llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp | 42 +-- llvm/lib/Target/DirectX/DXILPrettyPrinter.h | 33 +++ .../lib/Target/DirectX/DXILResourceAnalysis.h | 4 + .../Target/DirectX/DXILTranslateMetadata.cpp | 78 ++--- .../Target/DirectX/DXILTranslateMetadata.h | 24 ++ llvm/lib/Target/DirectX/DirectX.h | 8 +- .../Target/DirectX/DirectXPassRegistry.def | 5 +- .../Target/DirectX/DirectXTargetMachine.cpp | 10 +- .../DXILResource/buffer-frombinding.ll | 6 +- llvm/test/CodeGen/DirectX/CreateHandle.ll | 59 ++++ .../DirectX/CreateHandleFromBinding.ll | 63 ++++ .../CodeGen/DirectX/Metadata/dxilVer-1.0.ll | 2 +- .../CodeGen/DirectX/Metadata/dxilVer-1.8.ll | 2 +- .../DirectX/Metadata/shaderModel-as.ll | 2 +- .../DirectX/Metadata/shaderModel-cs.ll | 2 +- .../DirectX/Metadata/shaderModel-gs.ll | 2 +- .../DirectX/Metadata/shaderModel-hs.ll | 2 +- .../DirectX/Metadata/shaderModel-lib.ll | 2 +- .../DirectX/Metadata/shaderModel-ms.ll | 2 +- .../DirectX/Metadata/shaderModel-ps.ll | 3 +- .../DirectX/Metadata/shaderModel-vs.ll | 2 +- llvm/test/CodeGen/DirectX/UAVMetadata.ll | 4 +- llvm/test/CodeGen/DirectX/any.ll | 2 +- llvm/test/CodeGen/DirectX/cbuf.ll | 4 +- llvm/test/CodeGen/DirectX/dxil_ver.ll | 2 +- llvm/test/CodeGen/DirectX/floor.ll | 2 +- .../CodeGen/DirectX/legacy_cb_layout_0.ll | 2 +- .../CodeGen/DirectX/legacy_cb_layout_1.ll | 2 +- .../CodeGen/DirectX/legacy_cb_layout_2.ll | 2 +- .../CodeGen/DirectX/legacy_cb_layout_3.ll | 2 +- llvm/test/CodeGen/DirectX/lib_entry.ll | 2 +- llvm/test/Frontend/HLSL/empty_cs_entry.ll | 2 +- llvm/utils/TableGen/DXILEmitter.cpp | 176 +++-------- 43 files changed, 859 insertions(+), 489 deletions(-) create mode 100644 llvm/lib/Target/DirectX/DXILOpLowering.h create mode 100644 llvm/lib/Target/DirectX/DXILPrettyPrinter.h create mode 100644 llvm/lib/Target/DirectX/DXILTranslateMetadata.h create mode 100644 llvm/test/CodeGen/DirectX/CreateHandle.ll create mode 100644 llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll diff --git a/llvm/docs/DirectX/DXILOpTableGenDesign.rst b/llvm/docs/DirectX/DXILOpTableGenDesign.rst index 50d801bd05efd..46106ee2a50f5 100644 --- a/llvm/docs/DirectX/DXILOpTableGenDesign.rst +++ b/llvm/docs/DirectX/DXILOpTableGenDesign.rst @@ -93,18 +93,14 @@ properties are specified as fields of the ``DXILOp`` class as described below. class DXILOpClass; Concrete operation records, such as ``unary`` are defined by inheriting from ``DXILOpClass``. -6. Return type of the operation is represented as ``LLVMType``. -7. Operation arguments are represented as a list of ``LLVMType`` with each type - corresponding to the argument position. An overload type, if supported by the operation, is - denoted as the positional type ``overloadTy`` in the argument or in the result, where - ``overloadTy`` is defined to be synonymous to ``llvm_any_ty``. - - .. code-block:: - - defvar overloadTy = llvm_any_ty - - Empty list, ``[]`` represents an operation with no arguments. - +6. A set of type names are defined that represent return and argument types, + which all inherit from ``DXILOpParamType``. These represent simple types + like ``int32Ty``, DXIL types like ``dx.types.Handle``, and a special + ``overloadTy`` which can be any type allowed by ``Overloads``, described + below. +7. Operation return type is represented as a ``DXILOpParamType``, and arguments + are represented as a list of the same. An operation with no return value + shall specify ``VoidTy`` as its return. 8. Valid operation overload types predicated on DXIL version are specified as a list of ``Overloads`` records. Representation of ``Overloads`` class is described in a later section. @@ -145,10 +141,10 @@ TableGen representations of its properties described above. Intrinsic LLVMIntrinsic = ?; // Result type of the op. - LLVMType result; + DXILOpParamType result; // List of argument types of the op. Default to 0 arguments. - list arguments = []; + list arguments = []; // List of valid overload types predicated by DXIL version list overloads; @@ -233,9 +229,9 @@ overloads predicated on DXIL version as list of records of the following class .. code-block:: - class Overloads ols> { + class Overloads ols> { Version dxil_version = minver; - list overload_types = ols; + list overload_types = ols; } Following is an example specification of valid overload types for ``DXIL1_0`` and diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h index 3ba0ae5de61d5..2ed508b28a908 100644 --- a/llvm/include/llvm/Analysis/DXILResource.h +++ b/llvm/include/llvm/Analysis/DXILResource.h @@ -23,6 +23,7 @@ class TargetExtType; namespace dxil { class ResourceInfo { +public: struct ResourceBinding { uint32_t RecordID; uint32_t Space; @@ -89,6 +90,7 @@ class ResourceInfo { bool operator!=(const FeedbackInfo &RHS) const { return !(*this == RHS); } }; +private: // Universal properties. Value *Symbol; StringRef Name; @@ -115,6 +117,10 @@ class ResourceInfo { MSInfo MultiSample; + // We need a default constructor if we want to insert this in a MapVector. + ResourceInfo() {} + friend class MapVector; + public: ResourceInfo(dxil::ResourceClass RC, dxil::ResourceKind Kind, Value *Symbol, StringRef Name) @@ -166,6 +172,8 @@ class ResourceInfo { MultiSample.Count = Count; } + dxil::ResourceClass getResourceClass() const { return RC; } + bool operator==(const ResourceInfo &RHS) const; static ResourceInfo SRV(Value *Symbol, StringRef Name, diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td index c9102aa3dd972..ca3682fa47767 100644 --- a/llvm/include/llvm/IR/IntrinsicsDirectX.td +++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td @@ -30,6 +30,9 @@ def int_dx_handle_fromBinding [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i1_ty], [IntrNoMem]>; +// Cast between target extension handle types and dxil-style opaque handles +def int_dx_cast_handle : Intrinsic<[llvm_any_ty], [llvm_any_ty]>; + def int_dx_all : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty]>; def int_dx_any : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty]>; def int_dx_clamp : DefaultAttrsIntrinsic<[llvm_any_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; diff --git a/llvm/include/llvm/Support/DXILABI.h b/llvm/include/llvm/Support/DXILABI.h index a2222eec09ba8..cf2c42c689889 100644 --- a/llvm/include/llvm/Support/DXILABI.h +++ b/llvm/include/llvm/Support/DXILABI.h @@ -22,23 +22,6 @@ namespace llvm { namespace dxil { -enum class ParameterKind : uint8_t { - Invalid = 0, - Void, - Half, - Float, - Double, - I1, - I8, - I16, - I32, - I64, - Overload, - CBufferRet, - ResourceRet, - DXILHandle, -}; - enum class ResourceClass : uint8_t { SRV = 0, UAV, diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td index 67015cff78a79..31fee04d82158 100644 --- a/llvm/lib/Target/DirectX/DXIL.td +++ b/llvm/lib/Target/DirectX/DXIL.td @@ -24,19 +24,26 @@ foreach i = 0...8 in { def DXIL1_ #i : Version<1, i>; } -// Overload type alias of llvm_any_ty -defvar overloadTy = llvm_any_ty; - -// Type aliases for DXIL Op types to LLVM Types. -// TODO: Define DXIL Types independent of LLVM types -defvar i1Ty = llvm_i1_ty; -defvar i8Ty = llvm_i8_ty; -defvar i16Ty = llvm_i16_ty; -defvar i32Ty = llvm_i32_ty; -defvar i64Ty = llvm_i64_ty; -defvar halfTy = llvm_half_ty; -defvar floatTy = llvm_float_ty; -defvar doubleTy = llvm_double_ty; +class DXILOpParamType { + int isOverload = 0; +} + +let isOverload = 1 in { + def OverloadTy : DXILOpParamType; +} +def VoidTy : DXILOpParamType; +def Int1Ty : DXILOpParamType; +def Int8Ty : DXILOpParamType; +def Int16Ty : DXILOpParamType; +def Int32Ty : DXILOpParamType; +def Int64Ty : DXILOpParamType; +def HalfTy : DXILOpParamType; +def FloatTy : DXILOpParamType; +def DoubleTy : DXILOpParamType; +def ResRetTy : DXILOpParamType; +def HandleTy : DXILOpParamType; +def ResBindTy : DXILOpParamType; +def ResPropsTy : DXILOpParamType; class DXILOpClass; @@ -268,9 +275,9 @@ def IsWave : DXILAttribute; def NeedsUniformInputs : DXILAttribute; def IsBarrier : DXILAttribute; -class Overloads ols> { +class Overloads ols> { Version dxil_version = ver; - list overload_types = ols; + list overload_types = ols; } class Stages st> { @@ -298,10 +305,10 @@ class DXILOp { Intrinsic LLVMIntrinsic = ?; // Result type of the op - LLVMType result; + DXILOpParamType result; // List of argument types of the op. Default to 0 arguments. - list arguments = []; + list arguments = []; // List of valid overload types predicated by DXIL version list overloads = []; @@ -318,9 +325,9 @@ class DXILOp { def Abs : DXILOp<6, unary> { let Doc = "Returns the absolute value of the input."; let LLVMIntrinsic = int_fabs; - let arguments = [overloadTy]; - let result = overloadTy; - let overloads = [Overloads]; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -328,9 +335,9 @@ def Abs : DXILOp<6, unary> { def IsInf : DXILOp<9, isSpecialFloat> { let Doc = "Determines if the specified value is infinite."; let LLVMIntrinsic = int_dx_isinf; - let arguments = [overloadTy]; - let result = i1Ty; - let overloads = [Overloads]; + let arguments = [OverloadTy]; + let result = Int1Ty; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -338,9 +345,9 @@ def IsInf : DXILOp<9, isSpecialFloat> { def Cos : DXILOp<12, unary> { let Doc = "Returns cosine(theta) for theta in radians."; let LLVMIntrinsic = int_cos; - let arguments = [overloadTy]; - let result = overloadTy; - let overloads = [Overloads]; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -348,9 +355,9 @@ def Cos : DXILOp<12, unary> { def Sin : DXILOp<13, unary> { let Doc = "Returns sine(theta) for theta in radians."; let LLVMIntrinsic = int_sin; - let arguments = [overloadTy]; - let result = overloadTy; - let overloads = [Overloads]; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -358,9 +365,9 @@ def Sin : DXILOp<13, unary> { def Tan : DXILOp<14, unary> { let Doc = "Returns tangent(theta) for theta in radians."; let LLVMIntrinsic = int_tan; - let arguments = [overloadTy]; - let result = overloadTy; - let overloads = [Overloads]; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -368,9 +375,9 @@ def Tan : DXILOp<14, unary> { def ACos : DXILOp<15, unary> { let Doc = "Returns the arccosine of the specified value."; let LLVMIntrinsic = int_acos; - let arguments = [overloadTy]; - let result = overloadTy; - let overloads = [Overloads]; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -378,9 +385,9 @@ def ACos : DXILOp<15, unary> { def ASin : DXILOp<16, unary> { let Doc = "Returns the arcsine of the specified value."; let LLVMIntrinsic = int_asin; - let arguments = [overloadTy]; - let result = overloadTy; - let overloads = [Overloads]; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -388,9 +395,9 @@ def ASin : DXILOp<16, unary> { def ATan : DXILOp<17, unary> { let Doc = "Returns the arctangent of the specified value."; let LLVMIntrinsic = int_atan; - let arguments = [overloadTy]; - let result = overloadTy; - let overloads = [Overloads]; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -398,9 +405,9 @@ def ATan : DXILOp<17, unary> { def HCos : DXILOp<18, unary> { let Doc = "Returns the hyperbolic cosine of the specified value."; let LLVMIntrinsic = int_cosh; - let arguments = [overloadTy]; - let result = overloadTy; - let overloads = [Overloads]; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -408,9 +415,9 @@ def HCos : DXILOp<18, unary> { def HSin : DXILOp<19, unary> { let Doc = "Returns the hyperbolic sine of the specified value."; let LLVMIntrinsic = int_sinh; - let arguments = [overloadTy]; - let result = overloadTy; - let overloads = [Overloads]; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -418,9 +425,9 @@ def HSin : DXILOp<19, unary> { def HTan : DXILOp<20, unary> { let Doc = "Returns the hyperbolic tan of the specified value."; let LLVMIntrinsic = int_tanh; - let arguments = [overloadTy]; - let result = overloadTy; - let overloads = [Overloads]; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -429,9 +436,9 @@ def Exp2 : DXILOp<21, unary> { let Doc = "Returns the base 2 exponential, or 2**x, of the specified value. " "exp2(x) = 2**x."; let LLVMIntrinsic = int_exp2; - let arguments = [overloadTy]; - let result = overloadTy; - let overloads = [Overloads]; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -440,9 +447,9 @@ def Frac : DXILOp<22, unary> { let Doc = "Returns a fraction from 0 to 1 that represents the decimal part " "of the input."; let LLVMIntrinsic = int_dx_frac; - let arguments = [overloadTy]; - let result = overloadTy; - let overloads = [Overloads]; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -450,9 +457,9 @@ def Frac : DXILOp<22, unary> { def Log2 : DXILOp<23, unary> { let Doc = "Returns the base-2 logarithm of the specified value."; let LLVMIntrinsic = int_log2; - let arguments = [overloadTy]; - let result = overloadTy; - let overloads = [Overloads]; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -461,9 +468,9 @@ def Sqrt : DXILOp<24, unary> { let Doc = "Returns the square root of the specified floating-point value, " "per component."; let LLVMIntrinsic = int_sqrt; - let arguments = [overloadTy]; - let result = overloadTy; - let overloads = [Overloads]; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -472,9 +479,9 @@ def RSqrt : DXILOp<25, unary> { let Doc = "Returns the reciprocal of the square root of the specified value. " "rsqrt(x) = 1 / sqrt(x)."; let LLVMIntrinsic = int_dx_rsqrt; - let arguments = [overloadTy]; - let result = overloadTy; - let overloads = [Overloads]; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -483,9 +490,9 @@ def Round : DXILOp<26, unary> { let Doc = "Returns the input rounded to the nearest integer within a " "floating-point type."; let LLVMIntrinsic = int_roundeven; - let arguments = [overloadTy]; - let result = overloadTy; - let overloads = [Overloads]; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -494,9 +501,9 @@ def Floor : DXILOp<27, unary> { let Doc = "Returns the largest integer that is less than or equal to the input."; let LLVMIntrinsic = int_floor; - let arguments = [overloadTy]; - let result = overloadTy; - let overloads = [Overloads]; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -505,9 +512,9 @@ def Ceil : DXILOp<28, unary> { let Doc = "Returns the smallest integer that is greater than or equal to the " "input."; let LLVMIntrinsic = int_ceil; - let arguments = [overloadTy]; - let result = overloadTy; - let overloads = [Overloads]; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -515,9 +522,9 @@ def Ceil : DXILOp<28, unary> { def Trunc : DXILOp<29, unary> { let Doc = "Returns the specified value truncated to the integer component."; let LLVMIntrinsic = int_trunc; - let arguments = [overloadTy]; - let result = overloadTy; - let overloads = [Overloads]; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -525,10 +532,10 @@ def Trunc : DXILOp<29, unary> { def Rbits : DXILOp<30, unary> { let Doc = "Returns the specified value with its bits reversed."; let LLVMIntrinsic = int_bitreverse; - let arguments = [overloadTy]; - let result = overloadTy; + let arguments = [OverloadTy]; + let result = OverloadTy; let overloads = - [Overloads]; + [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -536,10 +543,10 @@ def Rbits : DXILOp<30, unary> { def FMax : DXILOp<35, binary> { let Doc = "Float maximum. FMax(a,b) = a > b ? a : b"; let LLVMIntrinsic = int_maxnum; - let arguments = [overloadTy, overloadTy]; - let result = overloadTy; + let arguments = [OverloadTy, OverloadTy]; + let result = OverloadTy; let overloads = - [Overloads]; + [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -547,10 +554,10 @@ def FMax : DXILOp<35, binary> { def FMin : DXILOp<36, binary> { let Doc = "Float minimum. FMin(a,b) = a < b ? a : b"; let LLVMIntrinsic = int_minnum; - let arguments = [overloadTy, overloadTy]; - let result = overloadTy; + let arguments = [OverloadTy, OverloadTy]; + let result = OverloadTy; let overloads = - [Overloads]; + [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -558,10 +565,10 @@ def FMin : DXILOp<36, binary> { def SMax : DXILOp<37, binary> { let Doc = "Signed integer maximum. SMax(a,b) = a > b ? a : b"; let LLVMIntrinsic = int_smax; - let arguments = [overloadTy, overloadTy]; - let result = overloadTy; + let arguments = [OverloadTy, OverloadTy]; + let result = OverloadTy; let overloads = - [Overloads]; + [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -569,10 +576,10 @@ def SMax : DXILOp<37, binary> { def SMin : DXILOp<38, binary> { let Doc = "Signed integer minimum. SMin(a,b) = a < b ? a : b"; let LLVMIntrinsic = int_smin; - let arguments = [overloadTy, overloadTy]; - let result = overloadTy; + let arguments = [OverloadTy, OverloadTy]; + let result = OverloadTy; let overloads = - [Overloads]; + [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -580,10 +587,10 @@ def SMin : DXILOp<38, binary> { def UMax : DXILOp<39, binary> { let Doc = "Unsigned integer maximum. UMax(a,b) = a > b ? a : b"; let LLVMIntrinsic = int_umax; - let arguments = [overloadTy, overloadTy]; - let result = overloadTy; + let arguments = [OverloadTy, OverloadTy]; + let result = OverloadTy; let overloads = - [Overloads]; + [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -591,10 +598,10 @@ def UMax : DXILOp<39, binary> { def UMin : DXILOp<40, binary> { let Doc = "Unsigned integer minimum. UMin(a,b) = a < b ? a : b"; let LLVMIntrinsic = int_umin; - let arguments = [overloadTy, overloadTy]; - let result = overloadTy; + let arguments = [OverloadTy, OverloadTy]; + let result = OverloadTy; let overloads = - [Overloads]; + [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -603,10 +610,10 @@ def FMad : DXILOp<46, tertiary> { let Doc = "Floating point arithmetic multiply/add operation. fmad(m,a,b) = m " "* a + b."; let LLVMIntrinsic = int_fmuladd; - let arguments = [overloadTy, overloadTy, overloadTy]; - let result = overloadTy; + let arguments = [OverloadTy, OverloadTy, OverloadTy]; + let result = OverloadTy; let overloads = - [Overloads]; + [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -615,10 +622,10 @@ def IMad : DXILOp<48, tertiary> { let Doc = "Signed integer arithmetic multiply/add operation. imad(m,a,b) = m " "* a + b."; let LLVMIntrinsic = int_dx_imad; - let arguments = [overloadTy, overloadTy, overloadTy]; - let result = overloadTy; + let arguments = [OverloadTy, OverloadTy, OverloadTy]; + let result = OverloadTy; let overloads = - [Overloads]; + [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -627,10 +634,10 @@ def UMad : DXILOp<49, tertiary> { let Doc = "Unsigned integer arithmetic multiply/add operation. umad(m,a, = m " "* a + b."; let LLVMIntrinsic = int_dx_umad; - let arguments = [overloadTy, overloadTy, overloadTy]; - let result = overloadTy; + let arguments = [OverloadTy, OverloadTy, OverloadTy]; + let result = OverloadTy; let overloads = - [Overloads]; + [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -639,9 +646,9 @@ def Dot2 : DXILOp<54, dot2> { let Doc = "dot product of two float vectors Dot(a,b) = a[0]*b[0] + ... + " "a[n]*b[n] where n is between 0 and 1"; let LLVMIntrinsic = int_dx_dot2; - let arguments = !listsplat(overloadTy, 4); - let result = overloadTy; - let overloads = [Overloads]; + let arguments = !listsplat(OverloadTy, 4); + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -650,9 +657,9 @@ def Dot3 : DXILOp<55, dot3> { let Doc = "dot product of two float vectors Dot(a,b) = a[0]*b[0] + ... + " "a[n]*b[n] where n is between 0 and 2"; let LLVMIntrinsic = int_dx_dot3; - let arguments = !listsplat(overloadTy, 6); - let result = overloadTy; - let overloads = [Overloads]; + let arguments = !listsplat(OverloadTy, 6); + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -661,18 +668,27 @@ def Dot4 : DXILOp<56, dot4> { let Doc = "dot product of two float vectors Dot(a,b) = a[0]*b[0] + ... + " "a[n]*b[n] where n is between 0 and 3"; let LLVMIntrinsic = int_dx_dot4; - let arguments = !listsplat(overloadTy, 8); - let result = overloadTy; - let overloads = [Overloads]; + let arguments = !listsplat(OverloadTy, 8); + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } +def CreateHandle : DXILOp<57, createHandle> { + let Doc = "creates the handle to a resource"; + // ResourceClass, RangeID, Index, NonUniform + let arguments = [Int8Ty, Int32Ty, Int32Ty, Int1Ty]; + let result = HandleTy; + let stages = [Stages]; +} + def ThreadId : DXILOp<93, threadId> { let Doc = "Reads the thread ID"; let LLVMIntrinsic = int_dx_thread_id; - let arguments = [i32Ty]; - let result = i32Ty; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -680,8 +696,9 @@ def ThreadId : DXILOp<93, threadId> { def GroupId : DXILOp<94, groupId> { let Doc = "Reads the group ID (SV_GroupID)"; let LLVMIntrinsic = int_dx_group_id; - let arguments = [i32Ty]; - let result = i32Ty; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -689,8 +706,9 @@ def GroupId : DXILOp<94, groupId> { def ThreadIdInGroup : DXILOp<95, threadIdInGroup> { let Doc = "Reads the thread ID within the group (SV_GroupThreadID)"; let LLVMIntrinsic = int_dx_thread_id_in_group; - let arguments = [i32Ty]; - let result = i32Ty; + let arguments = [OverloadTy]; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } @@ -699,7 +717,22 @@ def FlattenedThreadIdInGroup : DXILOp<96, flattenedThreadIdInGroup> { let Doc = "Provides a flattened index for a given thread within a given " "group (SV_GroupIndex)"; let LLVMIntrinsic = int_dx_flattened_thread_id_in_group; - let result = i32Ty; + let result = OverloadTy; + let overloads = [Overloads]; let stages = [Stages]; let attributes = [Attributes]; } + +def AnnotateHandle : DXILOp<217, annotateHandle> { + let Doc = "annotate handle with resource properties"; + let arguments = [HandleTy, ResPropsTy]; + let result = HandleTy; + let stages = [Stages]; +} + +def CreateHandleFromBinding : DXILOp<218, createHandleFromBinding> { + let Doc = "create resource handle from binding"; + let arguments = [ResBindTy, Int32Ty, Int1Ty]; + let result = HandleTy; + let stages = [Stages]; +} diff --git a/llvm/lib/Target/DirectX/DXILConstants.h b/llvm/lib/Target/DirectX/DXILConstants.h index 0c9c1ac38fdbc..022cd57795a06 100644 --- a/llvm/lib/Target/DirectX/DXILConstants.h +++ b/llvm/lib/Target/DirectX/DXILConstants.h @@ -25,6 +25,11 @@ enum class OpCodeClass : unsigned { #include "DXILOperation.inc" }; +enum class OpParamType : unsigned { +#define DXIL_OP_PARAM_TYPE(Name) Name, +#include "DXILOperation.inc" +}; + } // namespace dxil } // namespace llvm diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp index 42df7c90cb337..692af1b359ced 100644 --- a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp +++ b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp @@ -11,7 +11,6 @@ #include "DXILOpBuilder.h" #include "DXILConstants.h" -#include "llvm/IR/IRBuilder.h" #include "llvm/IR/Module.h" #include "llvm/Support/DXILABI.h" #include "llvm/Support/ErrorHandling.h" @@ -87,6 +86,9 @@ static const char *getOverloadTypeName(OverloadKind Kind) { } static OverloadKind getOverloadKind(Type *Ty) { + if (!Ty) + return OverloadKind::VOID; + Type::TypeID T = Ty->getTypeID(); switch (T) { case Type::VoidTyID: @@ -156,8 +158,6 @@ struct OpCodeProperty { llvm::SmallVector Attributes; int OverloadParamIndex; // parameter index which control the overload. // When < 0, should be only 1 overload type. - unsigned NumOfParameters; // Number of parameters include return value. - unsigned ParameterTableOffset; // Offset in ParameterTable. }; // Include getOpCodeClassName getOpCodeProperty, getOpCodeName and @@ -208,35 +208,54 @@ static StructType *getHandleType(LLVMContext &Ctx) { Ctx); } -static Type *getTypeFromParameterKind(ParameterKind Kind, LLVMContext &Ctx, - Type *OverloadTy) { +static StructType *getResBindType(LLVMContext &Context) { + if (auto *ST = StructType::getTypeByName(Context, "dx.types.ResBind")) + return ST; + Type *Int32Ty = Type::getInt32Ty(Context); + Type *Int8Ty = Type::getInt8Ty(Context); + return StructType::create({Int32Ty, Int32Ty, Int32Ty, Int8Ty}, + "dx.types.ResBind"); +} + +static StructType *getResPropsType(LLVMContext &Context) { + if (auto *ST = + StructType::getTypeByName(Context, "dx.types.ResourceProperties")) + return ST; + Type *Int32Ty = Type::getInt32Ty(Context); + return StructType::create({Int32Ty, Int32Ty}, "dx.types.ResourceProperties"); +} + +static Type *getTypeFromOpParamType(OpParamType Kind, LLVMContext &Ctx, + Type *OverloadTy) { switch (Kind) { - case ParameterKind::Void: + case OpParamType::VoidTy: return Type::getVoidTy(Ctx); - case ParameterKind::Half: + case OpParamType::HalfTy: return Type::getHalfTy(Ctx); - case ParameterKind::Float: + case OpParamType::FloatTy: return Type::getFloatTy(Ctx); - case ParameterKind::Double: + case OpParamType::DoubleTy: return Type::getDoubleTy(Ctx); - case ParameterKind::I1: + case OpParamType::Int1Ty: return Type::getInt1Ty(Ctx); - case ParameterKind::I8: + case OpParamType::Int8Ty: return Type::getInt8Ty(Ctx); - case ParameterKind::I16: + case OpParamType::Int16Ty: return Type::getInt16Ty(Ctx); - case ParameterKind::I32: + case OpParamType::Int32Ty: return Type::getInt32Ty(Ctx); - case ParameterKind::I64: + case OpParamType::Int64Ty: return Type::getInt64Ty(Ctx); - case ParameterKind::Overload: + case OpParamType::OverloadTy: return OverloadTy; - case ParameterKind::ResourceRet: + case OpParamType::ResRetTy: return getResRetType(OverloadTy, Ctx); - case ParameterKind::DXILHandle: + case OpParamType::HandleTy: return getHandleType(Ctx); - default: - break; + case OpParamType::ResBindTy: + return getResBindType(Ctx); + case OpParamType::ResPropsTy: + return getResPropsType(Ctx); } llvm_unreachable("Invalid parameter kind"); return nullptr; @@ -281,30 +300,34 @@ static ShaderKind getShaderKindEnum(Triple::EnvironmentType EnvType) { "Shader Kind Not Found - Invalid DXIL Environment Specified"); } +static SmallVector +getArgTypesFromOpParamTypes(ArrayRef Types, + LLVMContext &Context, Type *OverloadTy) { + SmallVector ArgTys; + ArgTys.emplace_back(Type::getInt32Ty(Context)); + for (dxil::OpParamType Ty : Types) + ArgTys.emplace_back(getTypeFromOpParamType(Ty, Context, OverloadTy)); + return ArgTys; +} + /// Construct DXIL function type. This is the type of a function with /// the following prototype /// OverloadType dx.op..(int opcode, ) /// are constructed from types in Prop. -static FunctionType *getDXILOpFunctionType(const OpCodeProperty *Prop, +static FunctionType *getDXILOpFunctionType(dxil::OpCode OpCode, LLVMContext &Context, Type *OverloadTy) { - SmallVector ArgTys; - - const ParameterKind *ParamKinds = getOpCodeParameterKind(*Prop); - assert(Prop->NumOfParameters && "No return type?"); - // Add return type of the function - Type *ReturnTy = getTypeFromParameterKind(ParamKinds[0], Context, OverloadTy); - - // Add DXIL Opcode value type viz., Int32 as first argument - ArgTys.emplace_back(Type::getInt32Ty(Context)); - - // Add DXIL Operation parameter types as specified in DXIL properties - for (unsigned I = 1; I < Prop->NumOfParameters; ++I) { - ParameterKind Kind = ParamKinds[I]; - ArgTys.emplace_back(getTypeFromParameterKind(Kind, Context, OverloadTy)); + switch (OpCode) { +#define DXIL_OP_FUNCTION_TYPE(OpCode, RetType, ...) \ + case OpCode: \ + return FunctionType::get( \ + getTypeFromOpParamType(RetType, Context, OverloadTy), \ + getArgTypesFromOpParamTypes({__VA_ARGS__}, Context, OverloadTy), \ + /*isVarArg=*/false); +#include "DXILOperation.inc" } - return FunctionType::get(ReturnTy, ArgTys, /*isVarArg=*/false); + llvm_unreachable("Invalid OpCode?"); } /// Get index of the property from PropList valid for the most recent @@ -332,7 +355,7 @@ namespace dxil { // Triple is well-formed or that the target is supported since these checks // would have been done at the time the module M is constructed in the earlier // stages of compilation. -DXILOpBuilder::DXILOpBuilder(Module &M, IRBuilderBase &B) : M(M), B(B) { +DXILOpBuilder::DXILOpBuilder(Module &M) : M(M), IRB(M.getContext()) { Triple TT(Triple(M.getTargetTriple())); DXILVersion = TT.getDXILVersion(); ShaderStage = TT.getEnvironment(); @@ -369,7 +392,7 @@ Expected DXILOpBuilder::tryCreateOp(dxil::OpCode OpCode, OverloadTy = Args[ArgIndex]->getType(); } FunctionType *DXILOpFT = - getDXILOpFunctionType(Prop, M.getContext(), OverloadTy); + getDXILOpFunctionType(OpCode, M.getContext(), OverloadTy); std::optional OlIndexOrErr = getPropIndex(ArrayRef(Prop->Overloads), DXILVersion); @@ -379,11 +402,7 @@ Expected DXILOpBuilder::tryCreateOp(dxil::OpCode OpCode, uint16_t ValidTyMask = Prop->Overloads[*OlIndexOrErr].ValidTys; - // If we don't have an overload type, use the function's return type. This is - // a bit of a hack, but it's necessary to get the type suffix on unoverloaded - // DXIL ops correct, like `dx.op.threadId.i32`. - OverloadKind Kind = - getOverloadKind(OverloadTy ? OverloadTy : DXILOpFT->getReturnType()); + OverloadKind Kind = getOverloadKind(OverloadTy); // Check if the operation supports overload types and OverloadTy is valid // per the specified types for the operation @@ -418,13 +437,13 @@ Expected DXILOpBuilder::tryCreateOp(dxil::OpCode OpCode, // We need to inject the opcode as the first argument. SmallVector OpArgs; - OpArgs.push_back(B.getInt32(llvm::to_underlying(OpCode))); + OpArgs.push_back(IRB.getInt32(llvm::to_underlying(OpCode))); OpArgs.append(Args.begin(), Args.end()); - return B.CreateCall(DXILFn, OpArgs); + return IRB.CreateCall(DXILFn, OpArgs); } -CallInst *DXILOpBuilder::createOp(dxil::OpCode OpCode, ArrayRef &Args, +CallInst *DXILOpBuilder::createOp(dxil::OpCode OpCode, ArrayRef Args, Type *RetTy) { Expected Result = tryCreateOp(OpCode, Args, RetTy); if (Error E = Result.takeError()) @@ -432,6 +451,29 @@ CallInst *DXILOpBuilder::createOp(dxil::OpCode OpCode, ArrayRef &Args, return *Result; } +StructType *DXILOpBuilder::getHandleType() { + return ::getHandleType(IRB.getContext()); +} + +Constant *DXILOpBuilder::getResBind(uint32_t LowerBound, uint32_t UpperBound, + uint32_t SpaceID, dxil::ResourceClass RC) { + Type *Int32Ty = IRB.getInt32Ty(); + Type *Int8Ty = IRB.getInt8Ty(); + return ConstantStruct::get( + getResBindType(IRB.getContext()), + {ConstantInt::get(Int32Ty, LowerBound), + ConstantInt::get(Int32Ty, UpperBound), + ConstantInt::get(Int32Ty, SpaceID), + ConstantInt::get(Int8Ty, llvm::to_underlying(RC))}); +} + +Constant *DXILOpBuilder::getResProps(uint32_t Word0, uint32_t Word1) { + Type *Int32Ty = IRB.getInt32Ty(); + return ConstantStruct::get( + getResPropsType(IRB.getContext()), + {ConstantInt::get(Int32Ty, Word0), ConstantInt::get(Int32Ty, Word1)}); +} + const char *DXILOpBuilder::getOpCodeName(dxil::OpCode DXILOp) { return ::getOpCodeName(DXILOp); } diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.h b/llvm/lib/Target/DirectX/DXILOpBuilder.h index ff66f39a3ceb3..4a55a8ac9eadb 100644 --- a/llvm/lib/Target/DirectX/DXILOpBuilder.h +++ b/llvm/lib/Target/DirectX/DXILOpBuilder.h @@ -14,13 +14,16 @@ #include "DXILConstants.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/TargetParser/Triple.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/Support/DXILABI.h" #include "llvm/Support/Error.h" +#include "llvm/TargetParser/Triple.h" namespace llvm { class Module; class IRBuilderBase; class CallInst; +class Constant; class Value; class Type; class FunctionType; @@ -29,29 +32,28 @@ namespace dxil { class DXILOpBuilder { public: - DXILOpBuilder(Module &M, IRBuilderBase &B); + DXILOpBuilder(Module &M); + + IRBuilder<> &getIRB() { return IRB; } /// Create a call instruction for the given DXIL op. The arguments /// must be valid for an overload of the operation. - CallInst *createOp(dxil::OpCode Op, ArrayRef &Args, + CallInst *createOp(dxil::OpCode Op, ArrayRef Args, Type *RetTy = nullptr); -#define DXIL_OPCODE(Op, Name) \ - CallInst *create##Name##Op(ArrayRef &Args, Type *RetTy = nullptr) { \ - return createOp(dxil::OpCode(Op), Args, RetTy); \ - } -#include "DXILOperation.inc" - /// Try to create a call instruction for the given DXIL op. Fails if the /// overload is invalid. Expected tryCreateOp(dxil::OpCode Op, ArrayRef Args, Type *RetTy = nullptr); -#define DXIL_OPCODE(Op, Name) \ - Expected tryCreate##Name##Op(ArrayRef &Args, \ - Type *RetTy = nullptr) { \ - return tryCreateOp(dxil::OpCode(Op), Args, RetTy); \ - } -#include "DXILOperation.inc" + + /// Get the `%dx.types.Handle` type. + StructType *getHandleType(); + + /// Get a constant `%dx.types.ResBind` value. + Constant *getResBind(uint32_t LowerBound, uint32_t UpperBound, + uint32_t SpaceID, dxil::ResourceClass RC); + /// Get a constant `%dx.types.ResourceProperties` value. + Constant *getResProps(uint32_t Word0, uint32_t Word1); /// Return the name of the given opcode. static const char *getOpCodeName(dxil::OpCode DXILOp); @@ -63,7 +65,7 @@ class DXILOpBuilder { Type *OverloadType = nullptr); Module &M; - IRBuilderBase &B; + IRBuilder<> IRB; VersionTuple DXILVersion; Triple::EnvironmentType ShaderStage; }; diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index 5f84cdcfda6de..ab18c57efa307 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -1,20 +1,18 @@ -//===- DXILOpLower.cpp - Lowering LLVM intrinsic to DIXLOp function -------===// +//===- DXILOpLowering.cpp - Lowering to DXIL operations -------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// -/// -/// \file This file contains passes and utilities to lower llvm intrinsic call -/// to DXILOp function call. -//===----------------------------------------------------------------------===// +#include "DXILOpLowering.h" #include "DXILConstants.h" #include "DXILIntrinsicExpansion.h" #include "DXILOpBuilder.h" #include "DirectX.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/DXILResource.h" #include "llvm/CodeGen/Passes.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/IRBuilder.h" @@ -23,6 +21,7 @@ #include "llvm/IR/IntrinsicsDirectX.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" #include "llvm/Pass.h" #include "llvm/Support/ErrorHandling.h" @@ -73,84 +72,226 @@ static SmallVector argVectorFlatten(CallInst *Orig, return NewOperands; } -static void lowerIntrinsic(dxil::OpCode DXILOp, Function &F, Module &M) { - IRBuilder<> B(M.getContext()); - DXILOpBuilder OpBuilder(M, B); - for (User *U : make_early_inc_range(F.users())) { - CallInst *CI = dyn_cast(U); - if (!CI) - continue; - - SmallVector Args; - B.SetInsertPoint(CI); - if (isVectorArgExpansion(F)) { - SmallVector NewArgs = argVectorFlatten(CI, B); - Args.append(NewArgs.begin(), NewArgs.end()); - } else - Args.append(CI->arg_begin(), CI->arg_end()); - - Expected OpCallOrErr = OpBuilder.tryCreateOp(DXILOp, Args, - F.getReturnType()); - if (Error E = OpCallOrErr.takeError()) { - std::string Message(toString(std::move(E))); - DiagnosticInfoUnsupported Diag(*CI->getFunction(), Message, - CI->getDebugLoc()); - M.getContext().diagnose(Diag); - continue; +namespace { +class OpLowerer { + Module &M; + DXILOpBuilder OpBuilder; + DXILResourceMap &DRM; + SmallVector CleanupCasts; + +public: + OpLowerer(Module &M, DXILResourceMap &DRM) : M(M), OpBuilder(M), DRM(DRM) {} + + void replaceFunction(Function &F, + llvm::function_ref ReplaceCall) { + for (User *U : make_early_inc_range(F.users())) { + CallInst *CI = dyn_cast(U); + if (!CI) + continue; + + if (Error E = ReplaceCall(CI)) { + std::string Message(toString(std::move(E))); + DiagnosticInfoUnsupported Diag(*CI->getFunction(), Message, + CI->getDebugLoc()); + M.getContext().diagnose(Diag); + continue; + } } - CallInst *OpCall = *OpCallOrErr; + if (F.user_empty()) + F.eraseFromParent(); + } + + void replaceFunctionWithOp(Function &F, dxil::OpCode DXILOp) { + bool IsVectorArgExpansion = isVectorArgExpansion(F); + replaceFunction(F, [&](CallInst *CI) -> Error { + SmallVector Args; + OpBuilder.getIRB().SetInsertPoint(CI); + if (IsVectorArgExpansion) { + SmallVector NewArgs = argVectorFlatten(CI, OpBuilder.getIRB()); + Args.append(NewArgs.begin(), NewArgs.end()); + } else + Args.append(CI->arg_begin(), CI->arg_end()); + + Expected OpCall = + OpBuilder.tryCreateOp(DXILOp, Args, F.getReturnType()); + if (Error E = OpCall.takeError()) + return E; - CI->replaceAllUsesWith(OpCall); - CI->eraseFromParent(); + CI->replaceAllUsesWith(*OpCall); + CI->eraseFromParent(); + return Error::success(); + }); + } + + Value *createTmpHandleCast(Value *V, Type *Ty) { + Function *CastFn = Intrinsic::getDeclaration(&M, Intrinsic::dx_cast_handle, + {Ty, V->getType()}); + CallInst *Cast = OpBuilder.getIRB().CreateCall(CastFn, {V}); + CleanupCasts.push_back(Cast); + return Cast; } - if (F.user_empty()) - F.eraseFromParent(); -} -static bool lowerIntrinsics(Module &M) { - bool Updated = false; + void cleanupHandleCasts() { + SmallVector ToRemove; + SmallVector CastFns; + + for (CallInst *Cast : CleanupCasts) { + CastFns.push_back(Cast->getCalledFunction()); + // All of the ops should be using `dx.types.Handle` at this point, so if + // we're not producing that we should be part of a pair. Track this so we + // can remove it at the end. + if (Cast->getType() != OpBuilder.getHandleType()) { + ToRemove.push_back(Cast); + continue; + } + // Otherwise, we're the second handle in a pair. Forward the arguments and + // remove the (second) cast. + CallInst *Def = cast(Cast->getOperand(0)); + assert(Def->getIntrinsicID() == Intrinsic::dx_cast_handle && + "Unbalanced pair of temporary handle casts"); + Cast->replaceAllUsesWith(Def->getOperand(0)); + Cast->eraseFromParent(); + } + for (CallInst *Cast : ToRemove) { + assert(Cast->user_empty() && "Temporary handle cast still has users"); + Cast->eraseFromParent(); + } + llvm::sort(CastFns); + CastFns.erase(llvm::unique(CastFns), CastFns.end()); + for (Function *F : CastFns) + F->eraseFromParent(); + + CleanupCasts.clear(); + } + + void lowerToCreateHandle(Function &F) { + IRBuilder<> &IRB = OpBuilder.getIRB(); + Type *Int8Ty = IRB.getInt8Ty(); + Type *Int32Ty = IRB.getInt32Ty(); + + replaceFunction(F, [&](CallInst *CI) -> Error { + IRB.SetInsertPoint(CI); + + dxil::ResourceInfo &RI = DRM[CI]; + dxil::ResourceInfo::ResourceBinding Binding = RI.getBinding(); + + std::array Args{ + ConstantInt::get(Int8Ty, llvm::to_underlying(RI.getResourceClass())), + ConstantInt::get(Int32Ty, Binding.RecordID), CI->getArgOperand(3), + CI->getArgOperand(4)}; + Expected OpCall = + OpBuilder.tryCreateOp(OpCode::CreateHandle, Args); + if (Error E = OpCall.takeError()) + return E; + + Value *Cast = createTmpHandleCast(*OpCall, CI->getType()); + + CI->replaceAllUsesWith(Cast); + CI->eraseFromParent(); + return Error::success(); + }); + } - for (Function &F : make_early_inc_range(M.functions())) { - if (!F.isDeclaration()) - continue; - Intrinsic::ID ID = F.getIntrinsicID(); - switch (ID) { - default: - continue; + void lowerToBindAndAnnotateHandle(Function &F) { + IRBuilder<> &IRB = OpBuilder.getIRB(); + + replaceFunction(F, [&](CallInst *CI) -> Error { + IRB.SetInsertPoint(CI); + + dxil::ResourceInfo &RI = DRM[CI]; + dxil::ResourceInfo::ResourceBinding Binding = RI.getBinding(); + std::pair Props = RI.getAnnotateProps(); + + Constant *ResBind = OpBuilder.getResBind( + Binding.LowerBound, Binding.LowerBound + Binding.Size - 1, + Binding.Space, RI.getResourceClass()); + std::array BindArgs{ResBind, CI->getArgOperand(3), + CI->getArgOperand(4)}; + Expected OpBind = + OpBuilder.tryCreateOp(OpCode::CreateHandleFromBinding, BindArgs); + if (Error E = OpBind.takeError()) + return E; + + std::array AnnotateArgs{ + *OpBind, OpBuilder.getResProps(Props.first, Props.second)}; + Expected OpAnnotate = + OpBuilder.tryCreateOp(OpCode::AnnotateHandle, AnnotateArgs); + if (Error E = OpAnnotate.takeError()) + return E; + + Value *Cast = createTmpHandleCast(*OpAnnotate, CI->getType()); + + CI->replaceAllUsesWith(Cast); + CI->eraseFromParent(); + + return Error::success(); + }); + } + + void lowerHandleFromBinding(Function &F) { + Triple TT(Triple(M.getTargetTriple())); + if (TT.getDXILVersion() < VersionTuple(1, 6)) + lowerToCreateHandle(F); + else + lowerToBindAndAnnotateHandle(F); + } + + bool lowerIntrinsics() { + bool Updated = false; + + for (Function &F : make_early_inc_range(M.functions())) { + if (!F.isDeclaration()) + continue; + Intrinsic::ID ID = F.getIntrinsicID(); + switch (ID) { + default: + continue; #define DXIL_OP_INTRINSIC(OpCode, Intrin) \ case Intrin: \ - lowerIntrinsic(OpCode, F, M); \ + replaceFunctionWithOp(F, OpCode); \ break; #include "DXILOperation.inc" + case Intrinsic::dx_handle_fromBinding: + lowerHandleFromBinding(F); + } + Updated = true; } - Updated = true; - } - return Updated; -} + if (Updated) + cleanupHandleCasts(); -namespace { -/// A pass that transforms external global definitions into declarations. -class DXILOpLowering : public PassInfoMixin { -public: - PreservedAnalyses run(Module &M, ModuleAnalysisManager &) { - if (lowerIntrinsics(M)) - return PreservedAnalyses::none(); - return PreservedAnalyses::all(); + return Updated; } }; } // namespace +PreservedAnalyses DXILOpLowering::run(Module &M, ModuleAnalysisManager &MAM) { + DXILResourceMap &DRM = MAM.getResult(M); + + bool MadeChanges = OpLowerer(M, DRM).lowerIntrinsics(); + if (!MadeChanges) + return PreservedAnalyses::all(); + PreservedAnalyses PA; + PA.preserve(); + return PA; +} + namespace { class DXILOpLoweringLegacy : public ModulePass { public: - bool runOnModule(Module &M) override { return lowerIntrinsics(M); } + bool runOnModule(Module &M) override { + DXILResourceMap &DRM = + getAnalysis().getResourceMap(); + + return OpLowerer(M, DRM).lowerIntrinsics(); + } StringRef getPassName() const override { return "DXIL Op Lowering"; } DXILOpLoweringLegacy() : ModulePass(ID) {} static char ID; // Pass identification. void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { - // Specify the passes that your pass depends on AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); } }; char DXILOpLoweringLegacy::ID = 0; @@ -158,6 +299,7 @@ char DXILOpLoweringLegacy::ID = 0; INITIALIZE_PASS_BEGIN(DXILOpLoweringLegacy, DEBUG_TYPE, "DXIL Op Lowering", false, false) +INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass) INITIALIZE_PASS_END(DXILOpLoweringLegacy, DEBUG_TYPE, "DXIL Op Lowering", false, false) diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.h b/llvm/lib/Target/DirectX/DXILOpLowering.h new file mode 100644 index 0000000000000..fe357da7bb905 --- /dev/null +++ b/llvm/lib/Target/DirectX/DXILOpLowering.h @@ -0,0 +1,27 @@ +//===- DXILOpLowering.h - Lowering to DXIL operations -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// \file Pass for lowering llvm intrinsics into DXIL operations. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_DIRECTX_DXILOPLOWERING_H +#define LLVM_LIB_TARGET_DIRECTX_DXILOPLOWERING_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { + +class DXILOpLowering : public PassInfoMixin { +public: + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); +}; + +} // namespace llvm + +#endif // LLVM_LIB_TARGET_DIRECTX_DXILOPLOWERING_H diff --git a/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp b/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp index 99cc4067b1d62..7d2abb7078b8a 100644 --- a/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp +++ b/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp @@ -1,16 +1,12 @@ -//===- DXILPrettyPrinter.cpp - DXIL Resource helper objects ---------------===// +//===- DXILPrettyPrinter.cpp - Print resources for textual DXIL -----------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// -/// -/// \file This file contains a pass for pretty printing DXIL metadata into IR -/// comments when printing assembly output. -/// -//===----------------------------------------------------------------------===// +#include "DXILPrettyPrinter.h" #include "DXILResourceAnalysis.h" #include "DirectX.h" #include "llvm/ADT/StringRef.h" @@ -20,18 +16,30 @@ using namespace llvm; +static void prettyPrintResources(raw_ostream &OS, + const dxil::Resources &MDResources) { + MDResources.print(OS); +} + +PreservedAnalyses DXILPrettyPrinterPass::run(Module &M, + ModuleAnalysisManager &MAM) { + const dxil::Resources &MDResources = MAM.getResult(M); + prettyPrintResources(OS, MDResources); + return PreservedAnalyses::all(); +} + namespace { -class DXILPrettyPrinter : public llvm::ModulePass { +class DXILPrettyPrinterLegacy : public llvm::ModulePass { raw_ostream &OS; // raw_ostream to print to. public: static char ID; - DXILPrettyPrinter() : ModulePass(ID), OS(dbgs()) { - initializeDXILPrettyPrinterPass(*PassRegistry::getPassRegistry()); + DXILPrettyPrinterLegacy() : ModulePass(ID), OS(dbgs()) { + initializeDXILPrettyPrinterLegacyPass(*PassRegistry::getPassRegistry()); } - explicit DXILPrettyPrinter(raw_ostream &O) : ModulePass(ID), OS(O) { - initializeDXILPrettyPrinterPass(*PassRegistry::getPassRegistry()); + explicit DXILPrettyPrinterLegacy(raw_ostream &O) : ModulePass(ID), OS(O) { + initializeDXILPrettyPrinterLegacyPass(*PassRegistry::getPassRegistry()); } StringRef getPassName() const override { @@ -46,19 +54,19 @@ class DXILPrettyPrinter : public llvm::ModulePass { }; } // namespace -char DXILPrettyPrinter::ID = 0; -INITIALIZE_PASS_BEGIN(DXILPrettyPrinter, "dxil-pretty-printer", +char DXILPrettyPrinterLegacy::ID = 0; +INITIALIZE_PASS_BEGIN(DXILPrettyPrinterLegacy, "dxil-pretty-printer", "DXIL Metadata Pretty Printer", true, true) INITIALIZE_PASS_DEPENDENCY(DXILResourceMDWrapper) -INITIALIZE_PASS_END(DXILPrettyPrinter, "dxil-pretty-printer", +INITIALIZE_PASS_END(DXILPrettyPrinterLegacy, "dxil-pretty-printer", "DXIL Metadata Pretty Printer", true, true) -bool DXILPrettyPrinter::runOnModule(Module &M) { +bool DXILPrettyPrinterLegacy::runOnModule(Module &M) { dxil::Resources &Res = getAnalysis().getDXILResource(); Res.print(OS); return false; } -ModulePass *llvm::createDXILPrettyPrinterPass(raw_ostream &OS) { - return new DXILPrettyPrinter(OS); +ModulePass *llvm::createDXILPrettyPrinterLegacyPass(raw_ostream &OS) { + return new DXILPrettyPrinterLegacy(OS); } diff --git a/llvm/lib/Target/DirectX/DXILPrettyPrinter.h b/llvm/lib/Target/DirectX/DXILPrettyPrinter.h new file mode 100644 index 0000000000000..84e17ac0f2ec6 --- /dev/null +++ b/llvm/lib/Target/DirectX/DXILPrettyPrinter.h @@ -0,0 +1,33 @@ +//===- DXILPrettyPrinter.h - Print resources for textual DXIL ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// \file This file contains a pass for pretty printing DXIL metadata into IR +// comments when printing assembly output. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_DIRECTX_DXILPRETTYPRINTER_H +#define LLVM_TARGET_DIRECTX_DXILPRETTYPRINTER_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { + +/// A pass that prints resources in a format suitable for textual DXIL. +class DXILPrettyPrinterPass : public PassInfoMixin { + raw_ostream &OS; + +public: + explicit DXILPrettyPrinterPass(raw_ostream &OS) : OS(OS) {} + + PreservedAnalyses run(Module &M, ModuleAnalysisManager &); +}; + +} // namespace llvm + +#endif // LLVM_TARGET_DIRECTX_DXILPRETTYPRINTER_H diff --git a/llvm/lib/Target/DirectX/DXILResourceAnalysis.h b/llvm/lib/Target/DirectX/DXILResourceAnalysis.h index 3a2b8a9fd39d5..26d9237d51b49 100644 --- a/llvm/lib/Target/DirectX/DXILResourceAnalysis.h +++ b/llvm/lib/Target/DirectX/DXILResourceAnalysis.h @@ -57,6 +57,10 @@ class DXILResourceMDWrapper : public ModulePass { /// Calculate the DXILResource for the module. bool runOnModule(Module &M) override; + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } + void print(raw_ostream &O, const Module *M = nullptr) const override; }; } // namespace llvm diff --git a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp index 583bce0f50e70..55b3d94568426 100644 --- a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp +++ b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp @@ -1,13 +1,12 @@ -//===- DXILTranslateMetadata.cpp - Pass to emit DXIL metadata ---*- C++ -*-===// +//===- DXILTranslateMetadata.cpp - Pass to emit DXIL metadata -------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// -/// -//===----------------------------------------------------------------------===// +#include "DXILTranslateMetadata.h" #include "DXILMetadata.h" #include "DXILResource.h" #include "DXILResourceAnalysis.h" @@ -23,13 +22,37 @@ using namespace llvm; using namespace llvm::dxil; +static void translateMetadata(Module &M, const dxil::Resources &MDResources, + const ComputedShaderFlags &ShaderFlags) { + dxil::ValidatorVersionMD ValVerMD(M); + if (ValVerMD.isEmpty()) + ValVerMD.update(VersionTuple(1, 0)); + dxil::createShaderModelMD(M); + dxil::createDXILVersionMD(M); + + MDResources.write(M); + + dxil::createEntryMD(M, static_cast(ShaderFlags)); +} + +PreservedAnalyses DXILTranslateMetadata::run(Module &M, + ModuleAnalysisManager &MAM) { + const dxil::Resources &MDResources = MAM.getResult(M); + const ComputedShaderFlags &ShaderFlags = + MAM.getResult(M); + + translateMetadata(M, MDResources, ShaderFlags); + + return PreservedAnalyses::all(); +} + namespace { -class DXILTranslateMetadata : public ModulePass { +class DXILTranslateMetadataLegacy : public ModulePass { public: static char ID; // Pass identification, replacement for typeid - explicit DXILTranslateMetadata() : ModulePass(ID) {} + explicit DXILTranslateMetadataLegacy() : ModulePass(ID) {} - StringRef getPassName() const override { return "DXIL Metadata Emit"; } + StringRef getPassName() const override { return "DXIL Translate Metadata"; } void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); @@ -37,39 +60,28 @@ class DXILTranslateMetadata : public ModulePass { AU.addRequired(); } - bool runOnModule(Module &M) override; + bool runOnModule(Module &M) override { + const dxil::Resources &MDResources = + getAnalysis().getDXILResource(); + const ComputedShaderFlags &ShaderFlags = + getAnalysis().getShaderFlags(); + + translateMetadata(M, MDResources, ShaderFlags); + return true; + } }; } // namespace -bool DXILTranslateMetadata::runOnModule(Module &M) { - - dxil::ValidatorVersionMD ValVerMD(M); - if (ValVerMD.isEmpty()) - ValVerMD.update(VersionTuple(1, 0)); - dxil::createShaderModelMD(M); - dxil::createDXILVersionMD(M); - - const dxil::Resources &Res = - getAnalysis().getDXILResource(); - Res.write(M); - - const uint64_t Flags = static_cast( - getAnalysis().getShaderFlags()); - dxil::createEntryMD(M, Flags); - - return false; -} - -char DXILTranslateMetadata::ID = 0; +char DXILTranslateMetadataLegacy::ID = 0; -ModulePass *llvm::createDXILTranslateMetadataPass() { - return new DXILTranslateMetadata(); +ModulePass *llvm::createDXILTranslateMetadataLegacyPass() { + return new DXILTranslateMetadataLegacy(); } -INITIALIZE_PASS_BEGIN(DXILTranslateMetadata, "dxil-metadata-emit", - "DXIL Metadata Emit", false, false) +INITIALIZE_PASS_BEGIN(DXILTranslateMetadataLegacy, "dxil-translate-metadata", + "DXIL Translate Metadata", false, false) INITIALIZE_PASS_DEPENDENCY(DXILResourceMDWrapper) INITIALIZE_PASS_DEPENDENCY(ShaderFlagsAnalysisWrapper) -INITIALIZE_PASS_END(DXILTranslateMetadata, "dxil-metadata-emit", - "DXIL Metadata Emit", false, false) +INITIALIZE_PASS_END(DXILTranslateMetadataLegacy, "dxil-translate-metadata", + "DXIL Translate Metadata", false, false) diff --git a/llvm/lib/Target/DirectX/DXILTranslateMetadata.h b/llvm/lib/Target/DirectX/DXILTranslateMetadata.h new file mode 100644 index 0000000000000..f3f5eb1901406 --- /dev/null +++ b/llvm/lib/Target/DirectX/DXILTranslateMetadata.h @@ -0,0 +1,24 @@ +//===- DXILTranslateMetadata.h - Pass to emit DXIL metadata -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_DIRECTX_DXILTRANSLATEMETADATA_H +#define LLVM_TARGET_DIRECTX_DXILTRANSLATEMETADATA_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { + +/// A pass that transforms DXIL Intrinsics that don't have DXIL opCodes +class DXILTranslateMetadata : public PassInfoMixin { +public: + PreservedAnalyses run(Module &M, ModuleAnalysisManager &); +}; + +} // namespace llvm + +#endif // LLVM_TARGET_DIRECTX_DXILTRANSLATEMETADATA_H diff --git a/llvm/lib/Target/DirectX/DirectX.h b/llvm/lib/Target/DirectX/DirectX.h index d056ae2bc488e..963c39ace3af9 100644 --- a/llvm/lib/Target/DirectX/DirectX.h +++ b/llvm/lib/Target/DirectX/DirectX.h @@ -41,19 +41,19 @@ void initializeDXILOpLoweringLegacyPass(PassRegistry &); ModulePass *createDXILOpLoweringLegacyPass(); /// Initializer for DXILTranslateMetadata. -void initializeDXILTranslateMetadataPass(PassRegistry &); +void initializeDXILTranslateMetadataLegacyPass(PassRegistry &); /// Pass to emit metadata for DXIL. -ModulePass *createDXILTranslateMetadataPass(); +ModulePass *createDXILTranslateMetadataLegacyPass(); /// Initializer for DXILTranslateMetadata. void initializeDXILResourceMDWrapperPass(PassRegistry &); /// Pass to pretty print DXIL metadata. -ModulePass *createDXILPrettyPrinterPass(raw_ostream &OS); +ModulePass *createDXILPrettyPrinterLegacyPass(raw_ostream &OS); /// Initializer for DXILPrettyPrinter. -void initializeDXILPrettyPrinterPass(PassRegistry &); +void initializeDXILPrettyPrinterLegacyPass(PassRegistry &); /// Initializer for dxil::ShaderFlagsAnalysisWrapper pass. void initializeShaderFlagsAnalysisWrapperPass(PassRegistry &); diff --git a/llvm/lib/Target/DirectX/DirectXPassRegistry.def b/llvm/lib/Target/DirectX/DirectXPassRegistry.def index 7544172ab94e4..a3e051b173d89 100644 --- a/llvm/lib/Target/DirectX/DirectXPassRegistry.def +++ b/llvm/lib/Target/DirectX/DirectXPassRegistry.def @@ -23,7 +23,10 @@ MODULE_ANALYSIS("dxil-resource-md", DXILResourceMDAnalysis()) #ifndef MODULE_PASS #define MODULE_PASS(NAME, CREATE_PASS) #endif +MODULE_PASS("dxil-intrinsic-expansion", DXILIntrinsicExpansion()) +MODULE_PASS("dxil-op-lower", DXILOpLowering()) +MODULE_PASS("dxil-pretty-printer", DXILPrettyPrinterPass(dbgs())) +MODULE_PASS("dxil-translate-metadata", DXILTranslateMetadata()) // TODO: rename to print after NPM switch MODULE_PASS("print-dx-shader-flags", dxil::ShaderFlagsAnalysisPrinter(dbgs())) -MODULE_PASS("print-dxil-resource-md", DXILResourceMDPrinterPass(dbgs())) #undef MODULE_PASS diff --git a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp index 92bd69b69684f..a578ad1452560 100644 --- a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp +++ b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp @@ -12,8 +12,12 @@ //===----------------------------------------------------------------------===// #include "DirectXTargetMachine.h" +#include "DXILIntrinsicExpansion.h" +#include "DXILOpLowering.h" +#include "DXILPrettyPrinter.h" #include "DXILResourceAnalysis.h" #include "DXILShaderFlags.h" +#include "DXILTranslateMetadata.h" #include "DXILWriter/DXILWriterPass.h" #include "DirectX.h" #include "DirectXSubtarget.h" @@ -45,7 +49,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeDirectXTarget() { initializeWriteDXILPassPass(*PR); initializeDXContainerGlobalsPass(*PR); initializeDXILOpLoweringLegacyPass(*PR); - initializeDXILTranslateMetadataPass(*PR); + initializeDXILTranslateMetadataLegacyPass(*PR); initializeDXILResourceMDWrapperPass(*PR); initializeShaderFlagsAnalysisWrapperPass(*PR); } @@ -79,7 +83,7 @@ class DirectXPassConfig : public TargetPassConfig { void addCodeGenPrepare() override { addPass(createDXILIntrinsicExpansionLegacyPass()); addPass(createDXILOpLoweringLegacyPass()); - addPass(createDXILTranslateMetadataPass()); + addPass(createDXILTranslateMetadataLegacyPass()); addPass(createDXILPrepareModulePass()); } }; @@ -116,7 +120,7 @@ bool DirectXTargetMachine::addPassesToEmitFile( switch (FileType) { case CodeGenFileType::AssemblyFile: - PM.add(createDXILPrettyPrinterPass(Out)); + PM.add(createDXILPrettyPrinterLegacyPass(Out)); PM.add(createPrintModulePass(Out, "", true)); break; case CodeGenFileType::ObjectFile: diff --git a/llvm/test/Analysis/DXILResource/buffer-frombinding.ll b/llvm/test/Analysis/DXILResource/buffer-frombinding.ll index 4349adb8ef8eb..65802c6d1ff87 100644 --- a/llvm/test/Analysis/DXILResource/buffer-frombinding.ll +++ b/llvm/test/Analysis/DXILResource/buffer-frombinding.ll @@ -46,14 +46,14 @@ define void @test_typedbuffer() { ; Buffer Buf[24] : register(t3, space5) %typed2 = call target("dx.TypedBuffer", <4 x i32>, 0, 0, 0) @llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_0_0t( - i32 2, i32 7, i32 24, i32 0, i1 false) + i32 5, i32 3, i32 24, i32 0, i1 false) ; CHECK: Binding for %typed2 ; CHECK: Symbol: ptr undef ; CHECK: Name: "" ; CHECK: Binding: ; CHECK: Record ID: 0 - ; CHECK: Space: 2 - ; CHECK: Lower Bound: 7 + ; CHECK: Space: 5 + ; CHECK: Lower Bound: 3 ; CHECK: Size: 24 ; CHECK: Class: SRV ; CHECK: Kind: TypedBuffer diff --git a/llvm/test/CodeGen/DirectX/CreateHandle.ll b/llvm/test/CodeGen/DirectX/CreateHandle.ll new file mode 100644 index 0000000000000..ca4def78e73de --- /dev/null +++ b/llvm/test/CodeGen/DirectX/CreateHandle.ll @@ -0,0 +1,59 @@ +; RUN: opt -S -dxil-op-lower %s | FileCheck %s + +target triple = "dxil-pc-shadermodel6.0-compute" + +define void @test_buffers() { + ; RWBuffer Buf : register(u5, space3) + %typed0 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0) + @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_1_0_0( + i32 3, i32 5, i32 1, i32 4, i1 false) + ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 4, i1 false) + ; CHECK-NOT: @llvm.dx.cast.handle + + ; RWBuffer Buf : register(u7, space2) + %typed1 = call target("dx.TypedBuffer", i32, 1, 0, 1) + @llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_1_0_1t( + i32 2, i32 7, i32 1, i32 6, i1 false) + ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 1, i32 6, i1 false) + + ; Buffer Buf[24] : register(t3, space5) + %typed2 = call target("dx.TypedBuffer", <4 x i32>, 0, 0, 0) + @llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_0_0_0t( + i32 2, i32 7, i32 24, i32 8, i1 false) + ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 8, i1 false) + + ; struct S { float4 a; uint4 b; }; + ; StructuredBuffer Buf : register(t2, space4) + %struct0 = call target("dx.RawBuffer", {<4 x float>, <4 x i32>}, 0, 0) + @llvm.dx.handle.fromBinding.tdx.RawBuffer_sl_v4f32v4i32s_0_0t( + i32 4, i32 2, i32 1, i32 10, i1 true) + ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 1, i32 10, i1 true) + + ; ByteAddressBuffer Buf : register(t8, space1) + %byteaddr0 = call target("dx.RawBuffer", i8, 0, 0) + @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_0_0t( + i32 1, i32 8, i32 1, i32 12, i1 false) + ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 2, i32 12, i1 false) + + ret void +} + +; Note: We need declarations for each handle.fromBinding in the same order as +; they appear in source to force a deterministic ordering of record IDs. +declare target("dx.TypedBuffer", <4 x float>, 1, 0, 0) + @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_1_0_0t( + i32, i32, i32, i32, i1) #0 +declare target("dx.TypedBuffer", i32, 1, 0, 1) + @llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_1_0_1t( + i32, i32, i32, i32, i1) #0 +declare target("dx.TypedBuffer", <4 x i32>, 0, 0, 0) + @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4i32_0_0_0t( + i32, i32, i32, i32, i1) #0 +declare target("dx.RawBuffer", { <4 x float>, <4 x i32> }, 0, 0) + @llvm.dx.handle.fromBinding.tdx.RawBuffer_sl_v4f32v4i32s_0_0t( + i32, i32, i32, i32, i1) #0 +declare target("dx.RawBuffer", i8, 0, 0) + @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_0_0t( + i32, i32, i32, i32, i1) #0 + +attributes #0 = { nocallback nofree nosync nounwind willreturn memory(none) } diff --git a/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll b/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll new file mode 100644 index 0000000000000..9b6688cb11d54 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll @@ -0,0 +1,63 @@ +; RUN: opt -S -dxil-op-lower %s | FileCheck %s + +target triple = "dxil-pc-shadermodel6.6-compute" + +define void @test_bindings() { + ; RWBuffer Buf : register(u5, space3) + %typed0 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0) + @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_1_0_0( + i32 3, i32 5, i32 1, i32 4, i1 false) + ; CHECK: [[BUF0:%[0-9]*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 218, %dx.types.ResBind { i32 5, i32 5, i32 3, i8 1 }, i32 4, i1 false) + ; CHECK: call %dx.types.Handle @dx.op.annotateHandle(i32 217, %dx.types.Handle [[BUF0]], %dx.types.ResourceProperties { i32 4106, i32 1033 }) + + ; RWBuffer Buf : register(u7, space2) + %typed1 = call target("dx.TypedBuffer", i32, 1, 0, 1) + @llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_1_0_0t( + i32 2, i32 7, i32 1, i32 6, i1 false) + ; CHECK: [[BUF1:%[0-9]*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 218, %dx.types.ResBind { i32 7, i32 7, i32 2, i8 1 }, i32 6, i1 false) + ; CHECK: call %dx.types.Handle @dx.op.annotateHandle(i32 217, %dx.types.Handle [[BUF1]], %dx.types.ResourceProperties { i32 4106, i32 260 }) + + ; Buffer Buf[24] : register(t3, space5) + %typed2 = call target("dx.TypedBuffer", <4 x i32>, 0, 0, 0) + @llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_0_0_0t( + i32 2, i32 7, i32 24, i32 8, i1 false) + ; CHECK: [[BUF2:%[0-9]*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 218, %dx.types.ResBind { i32 7, i32 30, i32 2, i8 0 }, i32 8, i1 false) + ; CHECK: call %dx.types.Handle @dx.op.annotateHandle(i32 217, %dx.types.Handle [[BUF2]], %dx.types.ResourceProperties { i32 10, i32 1029 }) + + ; struct S { float4 a; uint4 b; }; + ; StructuredBuffer Buf : register(t2, space4) + %struct0 = call target("dx.RawBuffer", {<4 x float>, <4 x i32>}, 0, 0) + @llvm.dx.handle.fromBinding.tdx.RawBuffer_sl_v4f32v4i32s_0_0t( + i32 4, i32 2, i32 1, i32 10, i1 true) + ; CHECK: [[BUF3:%[0-9]*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 218, %dx.types.ResBind { i32 2, i32 2, i32 4, i8 0 }, i32 10, i1 true) + ; CHECK: = call %dx.types.Handle @dx.op.annotateHandle(i32 217, %dx.types.Handle [[BUF3]], %dx.types.ResourceProperties { i32 1036, i32 32 }) + + ; ByteAddressBuffer Buf : register(t8, space1) + %byteaddr0 = call target("dx.RawBuffer", i8, 0, 0) + @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_0_0t( + i32 1, i32 8, i32 1, i32 12, i1 false) + ; CHECK: [[BUF4:%[0-9]*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 218, %dx.types.ResBind { i32 8, i32 8, i32 1, i8 0 }, i32 12, i1 false) + ; CHECK: call %dx.types.Handle @dx.op.annotateHandle(i32 217, %dx.types.Handle [[BUF4]], %dx.types.ResourceProperties { i32 11, i32 0 }) + + ret void +} + +; Note: We need declarations for each handle.fromBinding in the same order as +; they appear in source to force a deterministic ordering of record IDs. +declare target("dx.TypedBuffer", <4 x float>, 1, 0, 0) + @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_1_0_0t( + i32, i32, i32, i32, i1) #0 +declare target("dx.TypedBuffer", i32, 1, 0, 1) + @llvm.dx.handle.fromBinding.tdx.TypedBuffer_i32_1_0_1t( + i32, i32, i32, i32, i1) #0 +declare target("dx.TypedBuffer", <4 x i32>, 0, 0, 0) + @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4i32_0_0_0t( + i32, i32, i32, i32, i1) #0 +declare target("dx.RawBuffer", { <4 x float>, <4 x i32> }, 0, 0) + @llvm.dx.handle.fromBinding.tdx.RawBuffer_sl_v4f32v4i32s_0_0t( + i32, i32, i32, i32, i1) #0 +declare target("dx.RawBuffer", i8, 0, 0) + @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_0_0t( + i32, i32, i32, i32, i1) #0 + +attributes #0 = { nocallback nofree nosync nounwind willreturn memory(none) } diff --git a/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.0.ll b/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.0.ll index b9a8e3e80567e..fb31833dd5139 100644 --- a/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.0.ll +++ b/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.0.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -dxil-metadata-emit %s | FileCheck %s +; RUN: opt -S -passes=dxil-translate-metadata %s | FileCheck %s ; RUN: opt -S -passes="print" -disable-output %s 2>&1 | FileCheck %s --check-prefix=ANALYSIS target triple = "dxil-pc-shadermodel6.0-vertex" diff --git a/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.8.ll b/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.8.ll index fdd21d627829b..5944acc3b5b4b 100644 --- a/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.8.ll +++ b/llvm/test/CodeGen/DirectX/Metadata/dxilVer-1.8.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -dxil-metadata-emit %s | FileCheck %s +; RUN: opt -S -passes=dxil-translate-metadata %s | FileCheck %s ; RUN: opt -S -passes="print" -disable-output %s 2>&1 | FileCheck %s --check-prefix=ANALYSIS target triple = "dxil-pc-shadermodel6.8-compute" diff --git a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-as.ll b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-as.ll index d2625fc8b96a9..96d04f948c9b8 100644 --- a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-as.ll +++ b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-as.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -dxil-metadata-emit %s | FileCheck %s +; RUN: opt -S -dxil-translate-metadata %s | FileCheck %s ; RUN: opt -S -passes="print" -disable-output %s 2>&1 | FileCheck %s --check-prefix=ANALYSIS target triple = "dxil-pc-shadermodel6-amplification" diff --git a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-cs.ll b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-cs.ll index 24eb0d608d8bb..8cba445bcb01e 100644 --- a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-cs.ll +++ b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-cs.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -dxil-metadata-emit %s | FileCheck %s +; RUN: opt -S -dxil-translate-metadata %s | FileCheck %s ; RUN: opt -S -dxil-prepare %s | FileCheck %s --check-prefix=REMOVE_EXTRA_ATTRIBUTE ; RUN: opt -S -passes="print" -disable-output %s 2>&1 | FileCheck %s --check-prefix=ANALYSIS diff --git a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-gs.ll b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-gs.ll index 5c28c9305f01b..662620cf9f95c 100644 --- a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-gs.ll +++ b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-gs.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -dxil-metadata-emit %s | FileCheck %s +; RUN: opt -S -dxil-translate-metadata %s | FileCheck %s ; RUN: opt -S -passes="print" -disable-output %s 2>&1 | FileCheck %s --check-prefix=ANALYSIS target triple = "dxil-pc-shadermodel6.6-geometry" diff --git a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-hs.ll b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-hs.ll index e60023d1b3a5f..b405f8e915a32 100644 --- a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-hs.ll +++ b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-hs.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -dxil-metadata-emit %s | FileCheck %s +; RUN: opt -S -dxil-translate-metadata %s | FileCheck %s ; RUN: opt -S -passes="print" -disable-output %s 2>&1 | FileCheck %s --check-prefix=ANALYSIS target triple = "dxil-pc-shadermodel6.6-hull" diff --git a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-lib.ll b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-lib.ll index 7f0bea95c0482..26f3d287242ed 100644 --- a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-lib.ll +++ b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-lib.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -dxil-metadata-emit %s | FileCheck %s +; RUN: opt -S -dxil-translate-metadata %s | FileCheck %s ; RUN: opt -S -passes="print" -disable-output %s 2>&1 | FileCheck %s --check-prefix=ANALYSIS target triple = "dxil-pc-shadermodel6.3-library" diff --git a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-ms.ll b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-ms.ll index dd033b9a9722b..422d4add912f3 100644 --- a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-ms.ll +++ b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-ms.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -dxil-metadata-emit %s | FileCheck %s +; RUN: opt -S -dxil-translate-metadata %s | FileCheck %s ; RUN: opt -S -passes="print" -disable-output %s 2>&1 | FileCheck %s --check-prefix=ANALYSIS target triple = "dxil-pc-shadermodel6.6-mesh" diff --git a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-ps.ll b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-ps.ll index 47da321df3e42..cdb9a6f0f6a4f 100644 --- a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-ps.ll +++ b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-ps.ll @@ -1,5 +1,4 @@ - -; RUN: opt -S -dxil-metadata-emit %s | FileCheck %s +; RUN: opt -S -dxil-translate-metadata %s | FileCheck %s ; RUN: opt -S -passes="print" -disable-output %s 2>&1 | FileCheck %s --check-prefix=ANALYSIS target triple = "dxil-pc-shadermodel5.0-pixel" diff --git a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-vs.ll b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-vs.ll index dcc68586dd4b9..6b3501cc1dbaf 100644 --- a/llvm/test/CodeGen/DirectX/Metadata/shaderModel-vs.ll +++ b/llvm/test/CodeGen/DirectX/Metadata/shaderModel-vs.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -dxil-metadata-emit %s | FileCheck %s +; RUN: opt -S -dxil-translate-metadata %s | FileCheck %s ; RUN: opt -S -passes="print" -disable-output %s 2>&1 | FileCheck %s --check-prefix=ANALYSIS target triple = "dxil-pc-shadermodel-vertex" diff --git a/llvm/test/CodeGen/DirectX/UAVMetadata.ll b/llvm/test/CodeGen/DirectX/UAVMetadata.ll index bdad9fd40c9bd..2c242ec08eda5 100644 --- a/llvm/test/CodeGen/DirectX/UAVMetadata.ll +++ b/llvm/test/CodeGen/DirectX/UAVMetadata.ll @@ -1,5 +1,5 @@ -; RUN: opt -S -dxil-metadata-emit < %s | FileCheck %s -; RUN: opt -S --passes="print-dxil-resource-md" < %s 2>&1 | FileCheck %s --check-prefix=PRINT +; RUN: opt -S -dxil-translate-metadata < %s | FileCheck %s +; RUN: opt -S --passes="dxil-pretty-printer" < %s 2>&1 | FileCheck %s --check-prefix=PRINT ; RUN: llc %s --filetype=asm -o - < %s 2>&1 | FileCheck %s --check-prefixes=CHECK,PRINT target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" diff --git a/llvm/test/CodeGen/DirectX/any.ll b/llvm/test/CodeGen/DirectX/any.ll index ceb8077af311d..e32aa389a81a5 100644 --- a/llvm/test/CodeGen/DirectX/any.ll +++ b/llvm/test/CodeGen/DirectX/any.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.0-library < %s | FileCheck %s +; RUN: opt -S -passes=dxil-intrinsic-expansion,dxil-op-lower -mtriple=dxil-pc-shadermodel6.0-library < %s | FileCheck %s ; Make sure dxil operation function calls for any are generated for float and half. diff --git a/llvm/test/CodeGen/DirectX/cbuf.ll b/llvm/test/CodeGen/DirectX/cbuf.ll index 38f08fad995d1..7589da5e15bd7 100644 --- a/llvm/test/CodeGen/DirectX/cbuf.ll +++ b/llvm/test/CodeGen/DirectX/cbuf.ll @@ -1,5 +1,5 @@ -; RUN: opt -S -dxil-metadata-emit < %s | FileCheck %s --check-prefix=DXILMD -; RUN: opt -S --passes="print-dxil-resource-md" < %s 2>&1 | FileCheck %s --check-prefix=PRINT +; RUN: opt -S -dxil-translate-metadata < %s | FileCheck %s --check-prefix=DXILMD +; RUN: opt -S --passes="dxil-pretty-printer" < %s 2>&1 | FileCheck %s --check-prefix=PRINT target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" target triple = "dxil-unknown-shadermodel6.7-library" diff --git a/llvm/test/CodeGen/DirectX/dxil_ver.ll b/llvm/test/CodeGen/DirectX/dxil_ver.ll index e9923a3abce02..3c1d2e8102009 100644 --- a/llvm/test/CodeGen/DirectX/dxil_ver.ll +++ b/llvm/test/CodeGen/DirectX/dxil_ver.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -dxil-metadata-emit < %s | FileCheck %s +; RUN: opt -S -dxil-translate-metadata < %s | FileCheck %s target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" target triple = "dxil-pc-shadermodel6.3-library" diff --git a/llvm/test/CodeGen/DirectX/floor.ll b/llvm/test/CodeGen/DirectX/floor.ll index f667cab4aa249..f79f160e51e3b 100644 --- a/llvm/test/CodeGen/DirectX/floor.ll +++ b/llvm/test/CodeGen/DirectX/floor.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s +; RUN: opt -S -passes=dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s ; Make sure dxil operation function calls for floor are generated for float and half. diff --git a/llvm/test/CodeGen/DirectX/legacy_cb_layout_0.ll b/llvm/test/CodeGen/DirectX/legacy_cb_layout_0.ll index 0cfb839746b93..1a618092c5fed 100644 --- a/llvm/test/CodeGen/DirectX/legacy_cb_layout_0.ll +++ b/llvm/test/CodeGen/DirectX/legacy_cb_layout_0.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -dxil-metadata-emit < %s | FileCheck %s --check-prefix=DXILMD +; RUN: opt -S -dxil-translate-metadata < %s | FileCheck %s --check-prefix=DXILMD target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" target triple = "dxil-unknown-shadermodel6.7-library" diff --git a/llvm/test/CodeGen/DirectX/legacy_cb_layout_1.ll b/llvm/test/CodeGen/DirectX/legacy_cb_layout_1.ll index b6d29f8d18d79..6886f2690209d 100644 --- a/llvm/test/CodeGen/DirectX/legacy_cb_layout_1.ll +++ b/llvm/test/CodeGen/DirectX/legacy_cb_layout_1.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -dxil-metadata-emit < %s | FileCheck %s --check-prefix=DXILMD +; RUN: opt -S -dxil-translate-metadata < %s | FileCheck %s --check-prefix=DXILMD target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" target triple = "dxil-unknown-shadermodel6.7-library" diff --git a/llvm/test/CodeGen/DirectX/legacy_cb_layout_2.ll b/llvm/test/CodeGen/DirectX/legacy_cb_layout_2.ll index d023d7906fdc5..3b08b25542201 100644 --- a/llvm/test/CodeGen/DirectX/legacy_cb_layout_2.ll +++ b/llvm/test/CodeGen/DirectX/legacy_cb_layout_2.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -dxil-metadata-emit < %s | FileCheck %s --check-prefix=DXILMD +; RUN: opt -S -dxil-translate-metadata < %s | FileCheck %s --check-prefix=DXILMD target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" target triple = "dxil-unknown-shadermodel6.7-library" diff --git a/llvm/test/CodeGen/DirectX/legacy_cb_layout_3.ll b/llvm/test/CodeGen/DirectX/legacy_cb_layout_3.ll index 38c2cd18b5ca1..f01afbdab9673 100644 --- a/llvm/test/CodeGen/DirectX/legacy_cb_layout_3.ll +++ b/llvm/test/CodeGen/DirectX/legacy_cb_layout_3.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -dxil-metadata-emit < %s | FileCheck %s --check-prefix=DXILMD +; RUN: opt -S -dxil-translate-metadata < %s | FileCheck %s --check-prefix=DXILMD target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" target triple = "dxil-unknown-shadermodel6.7-library" diff --git a/llvm/test/CodeGen/DirectX/lib_entry.ll b/llvm/test/CodeGen/DirectX/lib_entry.ll index 5254a08805588..9aa63c26ce845 100644 --- a/llvm/test/CodeGen/DirectX/lib_entry.ll +++ b/llvm/test/CodeGen/DirectX/lib_entry.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -dxil-metadata-emit < %s | FileCheck %s +; RUN: opt -S -dxil-translate-metadata < %s | FileCheck %s target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" target triple = "dxil-unknown-shadermodel6.7-library" diff --git a/llvm/test/Frontend/HLSL/empty_cs_entry.ll b/llvm/test/Frontend/HLSL/empty_cs_entry.ll index 45b0faeaa44d4..32736aeeb542c 100644 --- a/llvm/test/Frontend/HLSL/empty_cs_entry.ll +++ b/llvm/test/Frontend/HLSL/empty_cs_entry.ll @@ -1,4 +1,4 @@ -; RUN: %if directx-registered-target %{ opt -S -dxil-metadata-emit < %s | FileCheck %s --check-prefix=DXIL-CHECK %} +; RUN: %if directx-registered-target %{ opt -S -dxil-translate-metadata < %s | FileCheck %s --check-prefix=DXIL-CHECK %} ; RUN: %if spirv-registered-target %{ llc %s -mtriple=spirv-unknown-unknown -o - | FileCheck %s --check-prefix=SPIRV-CHECK %} target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" diff --git a/llvm/utils/TableGen/DXILEmitter.cpp b/llvm/utils/TableGen/DXILEmitter.cpp index 53791618e80fe..9cc1b5ccb8acb 100644 --- a/llvm/utils/TableGen/DXILEmitter.cpp +++ b/llvm/utils/TableGen/DXILEmitter.cpp @@ -18,7 +18,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSet.h" -#include "llvm/CodeGenTypes/MachineValueType.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/DXILABI.h" #include "llvm/Support/VersionTuple.h" #include "llvm/TableGen/Error.h" @@ -54,40 +54,6 @@ struct DXILOperationDesc { }; } // end anonymous namespace -/// Return dxil::ParameterKind corresponding to input LLVMType record -/// -/// \param R TableGen def record of class LLVMType -/// \return ParameterKind As defined in llvm/Support/DXILABI.h - -static ParameterKind getParameterKind(const Record *R) { - auto VTRec = R->getValueAsDef("VT"); - switch (getValueType(VTRec)) { - case MVT::isVoid: - return ParameterKind::Void; - case MVT::f16: - return ParameterKind::Half; - case MVT::f32: - return ParameterKind::Float; - case MVT::f64: - return ParameterKind::Double; - case MVT::i1: - return ParameterKind::I1; - case MVT::i8: - return ParameterKind::I8; - case MVT::i16: - return ParameterKind::I16; - case MVT::i32: - return ParameterKind::I32; - case MVT::fAny: - case MVT::iAny: - case MVT::Any: - return ParameterKind::Overload; - default: - llvm_unreachable( - "Support for specified parameter type not yet implemented"); - } -} - /// In-place sort TableGen records of class with a field /// Version dxil_version /// in the ascending version order. @@ -134,10 +100,9 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) { // llvm/IR/Intrinsics.td OverloadParamIndex = -1; // A sigil meaning none. for (unsigned i = 0; i < ParamTypeRecsSize; i++) { - auto TR = ParamTypeRecs[i]; + Record *TR = ParamTypeRecs[i]; // Track operation parameter indices of any overload types - auto isAny = TR->getValueAsInt("isAny"); - if (isAny == 1) { + if (TR->getValueAsInt("isOverload")) { if (OverloadParamIndex != -1) { assert(TR == ParamTypeRecs[OverloadParamIndex] && "Specification of multiple differing overload parameter types " @@ -148,8 +113,6 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) { if (OverloadParamIndex <= 0) OverloadParamIndex = i; } - if (TR->isAnonymous()) - PrintFatalError(TR, "Only concrete types are allowed here"); OpTypes.emplace_back(TR); } @@ -208,71 +171,23 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) { } } -/// Return a string representation of ParameterKind enum -/// \param Kind Parameter Kind enum value -/// \return std::string string representation of input Kind -static std::string getParameterKindStr(ParameterKind Kind) { - switch (Kind) { - case ParameterKind::Invalid: - return "Invalid"; - case ParameterKind::Void: - return "Void"; - case ParameterKind::Half: - return "Half"; - case ParameterKind::Float: - return "Float"; - case ParameterKind::Double: - return "Double"; - case ParameterKind::I1: - return "I1"; - case ParameterKind::I8: - return "I8"; - case ParameterKind::I16: - return "I16"; - case ParameterKind::I32: - return "I32"; - case ParameterKind::I64: - return "I64"; - case ParameterKind::Overload: - return "Overload"; - case ParameterKind::CBufferRet: - return "CBufferRet"; - case ParameterKind::ResourceRet: - return "ResourceRet"; - case ParameterKind::DXILHandle: - return "DXILHandle"; - } - llvm_unreachable("Unknown llvm::dxil::ParameterKind enum"); -} - /// Return a string representation of OverloadKind enum that maps to /// input LLVMType record /// \param R TableGen def record of class LLVMType /// \return std::string string representation of OverloadKind -static std::string getOverloadKindStr(const Record *R) { - Record *VTRec = R->getValueAsDef("VT"); - switch (getValueType(VTRec)) { - case MVT::f16: - return "OverloadKind::HALF"; - case MVT::f32: - return "OverloadKind::FLOAT"; - case MVT::f64: - return "OverloadKind::DOUBLE"; - case MVT::i1: - return "OverloadKind::I1"; - case MVT::i8: - return "OverloadKind::I8"; - case MVT::i16: - return "OverloadKind::I16"; - case MVT::i32: - return "OverloadKind::I32"; - case MVT::i64: - return "OverloadKind::I64"; - default: - llvm_unreachable("Support for specified fixed type option for overload " - "type not supported"); - } +static StringRef getOverloadKindStr(const Record *R) { + // TODO: This is a hack. We need to rework how we're handling the set of + // overloads to avoid this business with the separate OverloadKind enum. + return StringSwitch(R->getName()) + .Case("HalfTy", "OverloadKind::HALF") + .Case("FloatTy", "OverloadKind::FLOAT") + .Case("DoubleTy", "OverloadKind::DOUBLE") + .Case("Int1Ty", "OverloadKind::I1") + .Case("Int8Ty", "OverloadKind::I8") + .Case("Int16Ty", "OverloadKind::I16") + .Case("Int32Ty", "OverloadKind::I32") + .Case("Int64Ty", "OverloadKind::I64"); } /// Return a string representation of valid overload information denoted @@ -417,8 +332,7 @@ static void emitDXILOpCodes(std::vector &Ops, } /// Emit a list of DXIL op classes -static void emitDXILOpClasses(RecordKeeper &Records, - raw_ostream &OS) { +static void emitDXILOpClasses(RecordKeeper &Records, raw_ostream &OS) { OS << "#ifdef DXIL_OPCLASS\n"; std::vector OpClasses = Records.getAllDerivedDefinitions("DXILOpClass"); @@ -428,6 +342,35 @@ static void emitDXILOpClasses(RecordKeeper &Records, OS << "#endif\n\n"; } +/// Emit a list of DXIL op parameter types +static void emitDXILOpParamTypes(RecordKeeper &Records, raw_ostream &OS) { + OS << "#ifdef DXIL_OP_PARAM_TYPE\n"; + std::vector OpClasses = + Records.getAllDerivedDefinitions("DXILOpParamType"); + for (Record *OpClass : OpClasses) + OS << "DXIL_OP_PARAM_TYPE(" << OpClass->getName() << ")\n"; + OS << "#undef DXIL_OP_PARAM_TYPE\n"; + OS << "#endif\n\n"; +} + +/// Emit a list of DXIL op function types +static void emitDXILOpFunctionTypes(ArrayRef Ops, + raw_ostream &OS) { + OS << "#ifndef DXIL_OP_FUNCTION_TYPE\n"; + OS << "#define DXIL_OP_FUNCTION_TYPE(OpCode, RetType, ...)\n"; + OS << "#endif\n"; + for (const DXILOperationDesc &Op : Ops) { + OS << "DXIL_OP_FUNCTION_TYPE(dxil::OpCode::" << Op.OpName; + for (const Record *Rec : Op.OpTypes) + OS << ", dxil::OpParamType::" << Rec->getName(); + // If there are no arguments, we need an empty comma for the varargs + if (Op.OpTypes.size() == 1) + OS << ", "; + OS << ")\n"; + } + OS << "#undef DXIL_OP_FUNCTION_TYPE\n"; +} + /// Emit map of DXIL operation to LLVM or DirectX intrinsic /// \param A vector of DXIL Ops /// \param Output stream @@ -454,9 +397,7 @@ static void emitDXILOperationTable(std::vector &Ops, // Collect Names. SequenceToOffsetTable OpClassStrings; SequenceToOffsetTable OpStrings; - SequenceToOffsetTable> Parameters; - StringMap> ParameterMap; StringSet<> ClassSet; for (auto &Op : Ops) { OpStrings.add(Op.OpName); @@ -465,18 +406,11 @@ static void emitDXILOperationTable(std::vector &Ops, continue; ClassSet.insert(Op.OpClass); OpClassStrings.add(Op.OpClass.data()); - SmallVector ParamKindVec; - for (unsigned i = 0; i < Op.OpTypes.size(); i++) { - ParamKindVec.emplace_back(getParameterKind(Op.OpTypes[i])); - } - ParameterMap[Op.OpClass] = ParamKindVec; - Parameters.add(ParamKindVec); } // Layout names. OpStrings.layout(); OpClassStrings.layout(); - Parameters.layout(); // Emit access function getOpcodeProperty() that embeds DXIL Operation table // with entries of type struct OpcodeProperty. @@ -492,8 +426,7 @@ static void emitDXILOperationTable(std::vector &Ops, << getOverloadMaskString(Op.OverloadRecs) << ", " << getStageMaskString(Op.StageRecs) << ", " << getAttributeMaskString(Op.AttrRecs) << ", " << Op.OverloadParamIndex - << ", " << Op.OpTypes.size() << ", " - << Parameters.get(ParameterMap[Op.OpClass]) << " }"; + << " }"; Prefix = ",\n"; } OS << " };\n"; @@ -531,21 +464,6 @@ static void emitDXILOperationTable(std::vector &Ops, OS << " unsigned Index = Prop.OpCodeClassNameOffset;\n"; OS << " return DXILOpCodeClassNameTable + Index;\n"; - OS << "}\n "; - - OS << "static const ParameterKind *getOpCodeParameterKind(const " - "OpCodeProperty &Prop) " - "{\n\n"; - OS << " static const ParameterKind DXILOpParameterKindTable[] = {\n"; - Parameters.emit( - OS, - [](raw_ostream &ParamOS, ParameterKind Kind) { - ParamOS << "ParameterKind::" << getParameterKindStr(Kind); - }, - "ParameterKind::Invalid"); - OS << " };\n\n"; - OS << " unsigned Index = Prop.ParameterTableOffset;\n"; - OS << " return DXILOpParameterKindTable + Index;\n"; OS << "}\n\n"; } @@ -611,6 +529,8 @@ static void EmitDXILOperation(RecordKeeper &Records, raw_ostream &OS) { emitDXILOpCodes(DXILOps, OS); emitDXILOpClasses(Records, OS); + emitDXILOpParamTypes(Records, OS); + emitDXILOpFunctionTypes(DXILOps, OS); emitDXILIntrinsicMap(DXILOps, OS); OS << "#ifdef DXIL_OP_OPERATION_TABLE\n\n"; emitDXILOperationTableDataStructs(Records, OS); From 2f317012985068f7130cdf4976d8821924d404c3 Mon Sep 17 00:00:00 2001 From: Justin Bogner Date: Mon, 9 Sep 2024 12:16:36 -0700 Subject: [PATCH 2/3] Improve comments, move code for clarity Created using spr 1.3.5-bogner --- llvm/docs/DirectX/DXILResources.rst | 2 +- llvm/lib/Target/DirectX/DXILOpLowering.cpp | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/llvm/docs/DirectX/DXILResources.rst b/llvm/docs/DirectX/DXILResources.rst index 07fba4ac644ec..8e43bfaaaf32e 100644 --- a/llvm/docs/DirectX/DXILResources.rst +++ b/llvm/docs/DirectX/DXILResources.rst @@ -277,7 +277,7 @@ return 1 to 4 elements from the given resource, to a maximum of 16 bytes of data. DXIL's modeling of this is influenced by DirectX and DXBC's history and it generally treats these operations as returning 4 32-bit values. For 16-bit elements the values are 16-bit values, and for 64-bit values the operations -return 4 32-bit integers and combine them with further operations. +return 4 32-bit integers and emit further code to construct the double. In DXIL, these operations return `ResRet`_ and `CBufRet`_ values, are structs containing 4 elements of the same type, and in the case of `ResRet` a 5th diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index 9db18a8476b07..409a1987709d5 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -259,23 +259,21 @@ class OpLowerer { lowerToBindAndAnnotateHandle(F); } - /// Replace uses of \c V with the values in the `dx.ResRet` of \c Op. Since we - /// expect to be post-scalarization, make an effort to avoid vectors. + /// Replace uses of \c Intrin with the values in the `dx.ResRet` of \c Op. + /// Since we expect to be post-scalarization, make an effort to avoid vectors. Error replaceResRetUses(CallInst *Intrin, CallInst *Op) { IRBuilder<> &IRB = OpBuilder.getIRB(); - Type *OldRetTy = Intrin->getType(); + Type *OldTy = Intrin->getType(); // For scalars, we just extract the first element. - if (!isa(OldRetTy)) { + if (!isa(OldTy)) { Value *EVI = IRB.CreateExtractValue(Op, 0); Intrin->replaceAllUsesWith(EVI); Intrin->eraseFromParent(); return Error::success(); } - auto *VecTy = cast(OldRetTy); - unsigned N = VecTy->getNumElements(); std::array Extracts = {}; SmallVector DynamicAccesses; @@ -296,6 +294,9 @@ class OpLowerer { } } + auto *VecTy = cast(OldTy); + unsigned N = VecTy->getNumElements(); + // If there's a dynamic access we need to round trip through stack memory so // that we don't leave vectors around. if (!DynamicAccesses.empty()) { @@ -331,7 +332,7 @@ class OpLowerer { if (!Extracts[I]) Extracts[I] = IRB.CreateExtractValue(Op, I); - Value *Vec = UndefValue::get(OldRetTy); + Value *Vec = UndefValue::get(OldTy); for (int I = 0, E = N; I != E; ++I) Vec = IRB.CreateInsertElement(Vec, Extracts[I], I); Intrin->replaceAllUsesWith(Vec); From 94a48e9e7cd9b4d135015114f21d5f030f0808ca Mon Sep 17 00:00:00 2001 From: Justin Bogner Date: Mon, 9 Sep 2024 12:20:52 -0700 Subject: [PATCH 3/3] Make VecTy and N const for clarity Created using spr 1.3.5-bogner --- llvm/lib/Target/DirectX/DXILOpLowering.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index 409a1987709d5..df2751d99576a 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -294,8 +294,8 @@ class OpLowerer { } } - auto *VecTy = cast(OldTy); - unsigned N = VecTy->getNumElements(); + const auto *VecTy = cast(OldTy); + const unsigned N = VecTy->getNumElements(); // If there's a dynamic access we need to round trip through stack memory so // that we don't leave vectors around.