[llvm] [DXIL] Add constraint specification and backend implementation of DXIL Ops (PR #97593)
S. Bharadwaj Yadavalli via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 3 08:43:33 PDT 2024
https://github.com/bharadwajy created https://github.com/llvm/llvm-project/pull/97593
Update TableGen specification of DXIL Op records in DXIL.td per the currentdesign document.
- Facilitate specification of overload and shader stage constraints on DXIL Ops predicated on Shader Model version.
- Facilitate specification of unconstrained attributes, if needed.
- Delete class DXILType and its concrete records as they are no longer needed.
Implement functionality to consume in TableGen backend, DXILEmitter, the above specification enhancements, and generate C++ code (in (DXILOperations.inc) that represents properties of DXIL Ops, associated type declarations and corresponding accessor functions.
Add mtriple with the required shader model version to commandline of tests.
>From b98b2f17ac2b92b5743ca67e5c05e039d83d52f0 Mon Sep 17 00:00:00 2001
From: Bharadwaj Yadavalli <Bharadwaj.Yadavalli at microsoft.com>
Date: Fri, 29 Mar 2024 12:11:35 -0400
Subject: [PATCH] Update TableGen specification of DXIL Op records in DXIL.td
per the current design document. - Facilitate specification of overload and
shader stage constraints on DXIL Ops predicated on Shader Model version.
- Facilitate specification of unconstrained attributes, if needed. -
Delete class DXILType and its concrete records as they are no longer
needed.
Implement functionality to consume in TableGen backend, DXILEmitter, the
above specification enhancements, and generate C++ code (in (DXILOperations.inc)
that represents properties of DXIL Ops, associated type declarations and
corresponding accessor functions.
Add mtriple with the required shader model version to commandline of tests.
---
llvm/lib/Target/DirectX/DXIL.td | 768 ++++++++++++++++-----
llvm/lib/Target/DirectX/DXILOpBuilder.cpp | 144 ++--
llvm/lib/Target/DirectX/DXILOpBuilder.h | 19 +-
llvm/lib/Target/DirectX/DXILOpLowering.cpp | 38 +-
llvm/test/CodeGen/DirectX/abs.ll | 4 +-
llvm/test/CodeGen/DirectX/acos.ll | 2 +-
llvm/test/CodeGen/DirectX/acos_error.ll | 2 +-
llvm/test/CodeGen/DirectX/asin.ll | 2 +-
llvm/test/CodeGen/DirectX/asin_error.ll | 2 +-
llvm/test/CodeGen/DirectX/atan.ll | 2 +-
llvm/test/CodeGen/DirectX/atan_error.ll | 2 +-
llvm/test/CodeGen/DirectX/ceil.ll | 2 +-
llvm/test/CodeGen/DirectX/ceil_error.ll | 2 +-
llvm/test/CodeGen/DirectX/clamp.ll | 2 +-
llvm/test/CodeGen/DirectX/cos.ll | 2 +-
llvm/test/CodeGen/DirectX/cos_error.ll | 2 +-
llvm/test/CodeGen/DirectX/cosh.ll | 2 +-
llvm/test/CodeGen/DirectX/cosh_error.ll | 2 +-
llvm/test/CodeGen/DirectX/dot2_error.ll | 2 +-
llvm/test/CodeGen/DirectX/dot3_error.ll | 2 +-
llvm/test/CodeGen/DirectX/dot4_error.ll | 2 +-
llvm/test/CodeGen/DirectX/exp.ll | 2 +-
llvm/test/CodeGen/DirectX/exp2_error.ll | 2 +-
llvm/test/CodeGen/DirectX/fabs.ll | 2 +-
llvm/test/CodeGen/DirectX/fdot.ll | 2 +-
llvm/test/CodeGen/DirectX/floor.ll | 2 +-
llvm/test/CodeGen/DirectX/floor_error.ll | 2 +-
llvm/test/CodeGen/DirectX/fmax.ll | 2 +-
llvm/test/CodeGen/DirectX/fmin.ll | 2 +-
llvm/test/CodeGen/DirectX/frac_error.ll | 2 +-
llvm/test/CodeGen/DirectX/idot.ll | 4 +-
llvm/test/CodeGen/DirectX/isinf.ll | 2 +-
llvm/test/CodeGen/DirectX/isinf_error.ll | 2 +-
llvm/test/CodeGen/DirectX/log.ll | 4 +-
llvm/test/CodeGen/DirectX/log10.ll | 4 +-
llvm/test/CodeGen/DirectX/log2.ll | 2 +-
llvm/test/CodeGen/DirectX/log2_error.ll | 2 +-
llvm/test/CodeGen/DirectX/pow.ll | 4 +-
llvm/test/CodeGen/DirectX/reversebits.ll | 2 +-
llvm/test/CodeGen/DirectX/round.ll | 2 +-
llvm/test/CodeGen/DirectX/round_error.ll | 2 +-
llvm/test/CodeGen/DirectX/rsqrt.ll | 2 +-
llvm/test/CodeGen/DirectX/rsqrt_error.ll | 2 +-
llvm/test/CodeGen/DirectX/sin.ll | 2 +-
llvm/test/CodeGen/DirectX/sin_error.ll | 2 +-
llvm/test/CodeGen/DirectX/sinh.ll | 2 +-
llvm/test/CodeGen/DirectX/sinh_error.ll | 2 +-
llvm/test/CodeGen/DirectX/smax.ll | 2 +-
llvm/test/CodeGen/DirectX/smin.ll | 2 +-
llvm/test/CodeGen/DirectX/sqrt.ll | 2 +-
llvm/test/CodeGen/DirectX/sqrt_error.ll | 2 +-
llvm/test/CodeGen/DirectX/tan.ll | 2 +-
llvm/test/CodeGen/DirectX/tan_error.ll | 2 +-
llvm/test/CodeGen/DirectX/tanh.ll | 2 +-
llvm/test/CodeGen/DirectX/tanh_error.ll | 2 +-
llvm/test/CodeGen/DirectX/trunc.ll | 2 +-
llvm/test/CodeGen/DirectX/trunc_error.ll | 2 +-
llvm/test/CodeGen/DirectX/umax.ll | 2 +-
llvm/test/CodeGen/DirectX/umin.ll | 2 +-
llvm/utils/TableGen/DXILEmitter.cpp | 342 ++++++---
60 files changed, 1039 insertions(+), 392 deletions(-)
diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td
index adaaa2a6e0d4e..c78bd9ae81661 100644
--- a/llvm/lib/Target/DirectX/DXIL.td
+++ b/llvm/lib/Target/DirectX/DXIL.td
@@ -13,15 +13,45 @@
include "llvm/IR/Intrinsics.td"
-class DXILOpClass;
+// Abstract class to represent major and minor version values
+class Version<int major, int minor> {
+ int Major = major;
+ int Minor = minor;
+}
+
+// Valid Shader model version records
+
+// Shader Model 6.0 - 6.8 and DXIL Version 1.0 - 1.8
+foreach i = 0...8 in {
+ def SM6_#i : Version<6, i>;
+ def DX1_#i : Version<1, i>;
+}
+
+// Resource ValueType - has no size or value
+def resourceVT : ValueType<-1, -1>;
+
+// Resource type
+def dxil_resource_ty : LLVMType<resourceVT>;
+// Overload type alias of llvm_any_ty
+defvar dxil_overload_ty = llvm_any_ty;
-// Following is a set of DXIL Operation classes whose names appear to be
-// arbitrary, yet need to be a substring of the function name used during
-// lowering to DXIL Operation calls. These class name strings are specified
-// as the third argument of add_dixil_op in utils/hct/hctdb.py and case converted
-// in utils/hct/hctdb_instrhelp.py of DirectXShaderCompiler repo. The function
-// name has the format "dx.op.<class-name>.<return-type>".
+// DXIL Op attribute
+class DXILOpAttr;
+defset list<DXILOpAttr> OpAttributes = {
+ def ReadOnly : DXILOpAttr;
+ def ReadNone : DXILOpAttr;
+ def IsDerivative : DXILOpAttr;
+ def IsGradient : DXILOpAttr;
+ def IsFeedback : DXILOpAttr;
+ def IsWave : DXILOpAttr;
+ def NeedsUniformInputs : DXILOpAttr;
+ def IsBarrier : DXILOpAttr;
+}
+
+class DXILOpClass;
+
+// Concrete definitions of DXIL Op Classes
defset list<DXILOpClass> OpClasses = {
def acceptHitAndEndSearch : DXILOpClass;
def allocateNodeOutputRecords : DXILOpClass;
@@ -212,154 +242,576 @@ defset list<DXILOpClass> OpClasses = {
def UnknownOpClass: DXILOpClass;
}
-// Several of the overloaded DXIL Operations support for data types
-// that are a subset of the overloaded LLVM intrinsics that they map to.
-// For e.g., llvm.sin.* intrinsic operates on any floating-point type and
-// maps for lowering to DXIL Op Sin. However, valid overloads of DXIL Sin
-// operation overloads are half (f16) and float (f32) only.
-//
-// The following abstracts overload types specific to DXIL operations.
-
-class DXILType : LLVMType<OtherVT> {
- let isAny = 1;
- int isI16OrI32 = 0;
- int isHalfOrFloat = 0;
-}
-
-// Concrete records for various overload types supported specifically by
-// DXIL Operations.
-let isI16OrI32 = 1 in
- def llvm_i16ori32_ty : DXILType;
-
-let isHalfOrFloat = 1 in
- def llvm_halforfloat_ty : DXILType;
-
-// Abstraction DXIL Operation to LLVM intrinsic
-class DXILOpMappingBase {
- int OpCode = 0; // Opcode of DXIL Operation
- DXILOpClass OpClass = UnknownOpClass;// Class of DXIL Operation.
- Intrinsic LLVMIntrinsic = ?; // LLVM Intrinsic DXIL Operation maps to
- string Doc = ""; // A short description of the operation
- list<LLVMType> OpTypes = ?; // Valid types of DXIL Operation in the
- // format [returnTy, param1ty, ...]
-}
-
-class DXILOpMapping<int opCode, DXILOpClass opClass,
- Intrinsic intrinsic, string doc,
- list<LLVMType> opTys = []> : DXILOpMappingBase {
- int OpCode = opCode; // Opcode corresponding to DXIL Operation
- DXILOpClass OpClass = opClass; // Class of DXIL Operation.
- Intrinsic LLVMIntrinsic = intrinsic; // LLVM Intrinsic the DXIL Operation maps
- string Doc = doc; // to a short description of the operation
- list<LLVMType> OpTypes = !if(!eq(!size(opTys), 0), LLVMIntrinsic.Types, opTys);
-}
-
-// Concrete definition of DXIL Operation mapping to corresponding LLVM intrinsic
-def Abs : DXILOpMapping<6, unary, int_fabs,
- "Returns the absolute value of the input.">;
-def IsInf : DXILOpMapping<9, isSpecialFloat, int_dx_isinf,
- "Determines if the specified value is infinite.",
- [llvm_i1_ty, llvm_halforfloat_ty]>;
-def Cos : DXILOpMapping<12, unary, int_cos,
- "Returns cosine(theta) for theta in radians.",
- [llvm_halforfloat_ty, LLVMMatchType<0>]>;
-def Sin : DXILOpMapping<13, unary, int_sin,
- "Returns sine(theta) for theta in radians.",
- [llvm_halforfloat_ty, LLVMMatchType<0>]>;
-def Tan : DXILOpMapping<14, unary, int_tan,
- "Returns tangent(theta) for theta in radians.",
- [llvm_halforfloat_ty, LLVMMatchType<0>]>;
-def ACos : DXILOpMapping<15, unary, int_acos,
- "Returns the arccosine of each component of input.",
- [llvm_halforfloat_ty, LLVMMatchType<0>]>;
-def ASin : DXILOpMapping<16, unary, int_asin,
- "Returns the arcsine of each component of input.",
- [llvm_halforfloat_ty, LLVMMatchType<0>]>;
-def ATan : DXILOpMapping<17, unary, int_atan,
- "Returns the arctangent of each component of input.",
- [llvm_halforfloat_ty, LLVMMatchType<0>]>;
-def HCos : DXILOpMapping<18, unary, int_cosh,
- "Returns the hyperbolic cosine of the specified value.",
- [llvm_halforfloat_ty, LLVMMatchType<0>]>;
-def HSin : DXILOpMapping<19, unary, int_sinh,
- "Returns the hyperbolic sine of the specified value.",
- [llvm_halforfloat_ty, LLVMMatchType<0>]>;
-def HTan : DXILOpMapping<20, unary, int_tanh,
- "Returns the hyperbolic tan of the specified value.",
- [llvm_halforfloat_ty, LLVMMatchType<0>]>;
-
-def Exp2 : DXILOpMapping<21, unary, int_exp2,
- "Returns the base 2 exponential, or 2**x, of the specified value."
- "exp2(x) = 2**x.",
- [llvm_halforfloat_ty, LLVMMatchType<0>]>;
-def Frac : DXILOpMapping<22, unary, int_dx_frac,
- "Returns a fraction from 0 to 1 that represents the "
- "decimal part of the input.",
- [llvm_halforfloat_ty, LLVMMatchType<0>]>;
-def Log2 : DXILOpMapping<23, unary, int_log2,
- "Returns the base-2 logarithm of the specified value.",
- [llvm_halforfloat_ty, LLVMMatchType<0>]>;
-def Sqrt : DXILOpMapping<24, unary, int_sqrt,
- "Returns the square root of the specified floating-point"
- "value, per component.",
- [llvm_halforfloat_ty, LLVMMatchType<0>]>;
-def RSqrt : DXILOpMapping<25, unary, int_dx_rsqrt,
- "Returns the reciprocal of the square root of the specified value."
- "rsqrt(x) = 1 / sqrt(x).",
- [llvm_halforfloat_ty, LLVMMatchType<0>]>;
-def Round : DXILOpMapping<26, unary, int_roundeven,
- "Returns the input rounded to the nearest integer"
- "within a floating-point type.",
- [llvm_halforfloat_ty, LLVMMatchType<0>]>;
-def Floor : DXILOpMapping<27, unary, int_floor,
- "Returns the largest integer that is less than or equal to the input.",
- [llvm_halforfloat_ty, LLVMMatchType<0>]>;
-def Ceil : DXILOpMapping<28, unary, int_ceil,
- "Returns the smallest integer that is greater than or equal to the input.",
- [llvm_halforfloat_ty, LLVMMatchType<0>]>;
-def Trunc : DXILOpMapping<29, unary, int_trunc,
- "Returns the specified value truncated to the integer component.",
- [llvm_halforfloat_ty, LLVMMatchType<0>]>;
-def Rbits : DXILOpMapping<30, unary, int_bitreverse,
- "Returns the specified value with its bits reversed.",
- [llvm_anyint_ty, LLVMMatchType<0>]>;
-def FMax : DXILOpMapping<35, binary, int_maxnum,
- "Float maximum. FMax(a,b) = a > b ? a : b">;
-def FMin : DXILOpMapping<36, binary, int_minnum,
- "Float minimum. FMin(a,b) = a < b ? a : b">;
-def SMax : DXILOpMapping<37, binary, int_smax,
- "Signed integer maximum. SMax(a,b) = a > b ? a : b">;
-def SMin : DXILOpMapping<38, binary, int_smin,
- "Signed integer minimum. SMin(a,b) = a < b ? a : b">;
-def UMax : DXILOpMapping<39, binary, int_umax,
- "Unsigned integer maximum. UMax(a,b) = a > b ? a : b">;
-def UMin : DXILOpMapping<40, binary, int_umin,
- "Unsigned integer minimum. UMin(a,b) = a < b ? a : b">;
-def FMad : DXILOpMapping<46, tertiary, int_fmuladd,
- "Floating point arithmetic multiply/add operation. fmad(m,a,b) = m * a + b.">;
-def IMad : DXILOpMapping<48, tertiary, int_dx_imad,
- "Signed integer arithmetic multiply/add operation. imad(m,a,b) = m * a + b.">;
-def UMad : DXILOpMapping<49, tertiary, int_dx_umad,
- "Unsigned integer arithmetic multiply/add operation. umad(m,a,b) = m * a + b.">;
-let OpTypes = !listconcat([llvm_halforfloat_ty], !listsplat(llvm_halforfloat_ty, 4)) in
- def Dot2 : DXILOpMapping<54, dot2, int_dx_dot2,
- "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 OpTypes = !listconcat([llvm_halforfloat_ty], !listsplat(llvm_halforfloat_ty, 6)) in
- def Dot3 : DXILOpMapping<55, dot3, int_dx_dot3,
- "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 OpTypes = !listconcat([llvm_halforfloat_ty], !listsplat(llvm_halforfloat_ty, 8)) in
- def Dot4 : DXILOpMapping<56, dot4, int_dx_dot4,
- "dot product of two float vectors Dot(a,b) = a[0]*b[0] + ... + a[n]*b[n] where n is between 0 and 3">;
-def ThreadId : DXILOpMapping<93, threadId, int_dx_thread_id,
- "Reads the thread ID">;
-def GroupId : DXILOpMapping<94, groupId, int_dx_group_id,
- "Reads the group ID (SV_GroupID)">;
-def ThreadIdInGroup : DXILOpMapping<95, threadIdInGroup,
- int_dx_thread_id_in_group,
- "Reads the thread ID within the group "
- "(SV_GroupThreadID)">;
-def FlattenedThreadIdInGroup : DXILOpMapping<96, flattenedThreadIdInGroup,
- int_dx_flattened_thread_id_in_group,
- "Provides a flattened index for a "
- "given thread within a given "
- "group (SV_GroupIndex)">;
+// Shader stages
+class ShaderStage;
+
+defset list<ShaderStage> ShaderStages = {
+ def compute : ShaderStage;
+ def domain : ShaderStage;
+ def hull : ShaderStage;
+ def pixel : ShaderStage;
+ def vertex : ShaderStage;
+ def geometry : ShaderStage;
+ def library : ShaderStage;
+ def amplification : ShaderStage;
+ def mesh : ShaderStage;
+ def node : ShaderStage;
+ def raygeneration : ShaderStage;
+ def intersection : ShaderStage;
+ def allKinds : ShaderStage;
+}
+
+// Primitive predicate
+class Pred;
+
+// Shader Model version predicate. This translates to
+// a check for specified shader model version
+class SMVersion<Version ver> : Pred {
+ Version sm_version = ver;
+}
+
+// Class abstraction of constraints predicated on Shader Model version
+class SMVersionConstraints<Version ver, dag oloads, dag stages> : SMVersion<ver> {
+ dag overload_types = oloads;
+ dag stage_kinds = stages;
+}
+
+// Marker used to identify argument list.
+def ins;
+
+// Marker used to identify result list.
+def out;
+
+// Marker used to identify list of shader model based attributes.
+def sm_attrs;
+
+// Marker used to identify overload types list.
+def overloads;
+
+// Marker used to identify stage kinds list.
+def stages;
+
+// Marker used to identify attribute list.
+def attrs;
+
+// Abstraction DXIL Operation
+class DXILOp {
+ // A short description of the operation
+ string Doc = "";
+
+ // Opcode of DXIL Operation
+ int OpCode = 0;
+
+ // Class of DXIL Operation.
+ DXILOpClass OpClass = UnknownOpClass;
+
+ // LLVM Intrinsic DXIL Operation maps to
+ Intrinsic LLVMIntrinsic = ?;
+
+ // TODO : DELETE THIS once support in DXILEmitter is added to consume
+ // overload_types and generate appropriate code.
+ // Valid overload type of DXIL Operation
+ list<LLVMType> OpOverloadTypes = ?;
+
+ // Dag containing the arguments of the op. Default to 0 arguments.
+ dag arguments = (ins);
+
+ // Results of the op. Default to 0 results.
+ dag result = (out);
+
+ // List of constraints predicated on Shader Model version
+ // This field is required to be specified. If a DXIL Op has no
+ // overloads or stages predicated on Shader Model version, the
+ // minimum Shader Model version the DXIL Op is supported it
+ // should be specified as a single list item
+ // [SMVersionConstraints<SMX_Y, (overloads), (stages allKinds)]
+ // If the DXIL Op is a DXIL Op that is not predicted on Shader
+ // Model version, it should be specified as an empty list.
+
+ list<SMVersionConstraints> sm_constraints;
+
+ // Non-predicated operation attributes
+ dag attributes = (attrs);
+ Version DXILVersion = ?;
+}
+
+// Concrete definitions of DXIL Operations
+
+def IsInf : DXILOp {
+ let Doc = "Determines if the specified value is infinite.";
+ let OpCode = 9;
+ let OpClass = isSpecialFloat;
+ let LLVMIntrinsic = int_dx_isinf;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = (ins llvm_anyfloat_ty);
+ let result = (out llvm_i1_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+}
+
+def Abs : DXILOp {
+ let Doc = "Returns the absolute value of the input.";
+ let OpCode = 6;
+ let OpClass = unary;
+ let LLVMIntrinsic = int_fabs;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty, llvm_double_ty];
+ let arguments = (ins LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty, llvm_double_ty),
+ (stages allKinds)>];
+}
+
+def Cos : DXILOp {
+ let Doc ="Returns cosine(theta) for theta in radians.";
+ let OpCode = 12;
+ let OpClass = unary;
+ let LLVMIntrinsic = int_cos;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = (ins LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+}
+
+def Sin : DXILOp {
+ let Doc ="Returns sine(theta) for theta in radians.";
+ let OpCode = 13;
+ let OpClass = unary;
+ let LLVMIntrinsic = int_sin;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = (ins LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+ let attributes = (attrs ReadNone);
+ let DXILVersion = DX1_0;
+}
+
+def Tan : DXILOp {
+ let Doc = "Returns tangent(theta) for theta in radians.";
+ let OpCode = 14;
+ let OpClass = unary;
+ let LLVMIntrinsic = int_tan;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = (ins LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+}
+
+def ACos : DXILOp {
+ let Doc = "Returns the arccosine of the specified value.";
+ let OpCode = 15;
+ let OpClass = unary;
+ let LLVMIntrinsic = int_acos;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = (ins LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+}
+
+def ASin : DXILOp {
+ let Doc = "Returns the arcsine of the specified value.";
+ let OpCode = 16;
+ let OpClass = unary;
+ let LLVMIntrinsic = int_asin;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = (ins LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+}
+
+def ATan : DXILOp {
+ let Doc = "Returns the arctangent of the specified value.";
+ let OpCode = 17;
+ let OpClass = unary;
+ let LLVMIntrinsic = int_atan;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = (ins LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+}
+
+def HCos : DXILOp {
+ let Doc = "Returns the hyperbolic cosine of the specified value.";
+ let OpCode = 18;
+ let OpClass = unary;
+ let LLVMIntrinsic = int_cosh;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = (ins LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+}
+
+def HSin : DXILOp {
+ let Doc = "Returns the hyperbolic sine of the specified value.";
+ let OpCode = 19;
+ let OpClass = unary;
+ let LLVMIntrinsic = int_sinh;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = (ins LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+}
+
+def HTan : DXILOp {
+ let Doc = "Returns the hyperbolic tan of the specified value.";
+ let OpCode = 20;
+ let OpClass = unary;
+ let LLVMIntrinsic = int_tanh;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = (ins LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+}
+
+def Exp2 : DXILOp {
+ let Doc = "Returns the base 2 exponential, or 2**x, of the specified value. exp2(x) = 2**x.";
+ let OpCode = 21;
+ let OpClass = unary;
+ let LLVMIntrinsic = int_exp2;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = (ins LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+}
+
+def Frac : DXILOp {
+ let Doc = "Returns a fraction from 0 to 1 that represents the decimal part of the input.";
+ let OpCode = 22;
+ let OpClass = unary;
+ let LLVMIntrinsic = int_dx_frac;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = (ins LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+}
+
+def Log2 : DXILOp {
+ let Doc = "Returns the base-2 logarithm of the specified value.";
+ let OpCode = 23;
+ let OpClass = unary;
+ let LLVMIntrinsic = int_log2;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = (ins LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+}
+
+def Sqrt : DXILOp {
+ let Doc = "Returns the square root of the specified floating-point value, per component.";
+ let OpCode = 24;
+ let OpClass = unary;
+ let LLVMIntrinsic = int_sqrt;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = (ins LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+}
+
+def RSqrt : DXILOp {
+ let Doc = "Returns the reciprocal of the square root of the specified value. rsqrt(x) = 1 / sqrt(x).";
+ let OpCode = 25;
+ let OpClass = unary;
+ let LLVMIntrinsic = int_dx_rsqrt;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = (ins LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+}
+
+def Round : DXILOp {
+ let Doc = "Returns the input rounded to the nearest integer within a floating-point type.";
+ let OpCode = 26;
+ let OpClass = unary;
+ let LLVMIntrinsic = int_roundeven;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = (ins LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+}
+
+def Floor : DXILOp {
+ let Doc = "Returns the largest integer that is less than or equal to the input.";
+ let OpCode = 27;
+ let OpClass = unary;
+ let LLVMIntrinsic = int_floor;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = (ins LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+}
+
+def Ceil : DXILOp {
+ let Doc = "Returns the smallest integer that is greater than or equal to the input.";
+ let OpCode = 28;
+ let OpClass = unary;
+ let LLVMIntrinsic = int_ceil;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = (ins LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+}
+
+def Trunc : DXILOp {
+ let Doc = "Returns the specified value truncated to the integer component.";
+ let OpCode = 29;
+ let OpClass = unary;
+ let LLVMIntrinsic = int_trunc;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = (ins LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+}
+
+def Rbits : DXILOp {
+ let Doc = "Returns the specified value with its bits reversed.";
+ let OpCode = 30;
+ let OpClass = unary;
+ let LLVMIntrinsic = int_bitreverse;
+ let OpOverloadTypes = [llvm_i16_ty, llvm_i32_ty, llvm_i64_ty];
+ let arguments = (ins LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_i16_ty, llvm_i32_ty, llvm_i64_ty),
+ (stages allKinds)>];
+}
+
+def FMax : DXILOp {
+ let Doc = "Float maximum. FMax(a,b) = a > b ? a : b";
+ let OpCode = 35;
+ let OpClass = binary;
+ let LLVMIntrinsic = int_maxnum;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty, llvm_double_ty];
+ let arguments = (ins LLVMMatchType<0>, LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty, llvm_double_ty),
+ (stages allKinds)>];
+}
+
+def FMin : DXILOp {
+ let Doc = "Float minimum. FMin(a,b) = a < b ? a : b";
+ let OpCode = 36;
+ let OpClass = binary;
+ let LLVMIntrinsic = int_minnum;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty, llvm_double_ty];
+ let arguments = (ins LLVMMatchType<0>, LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty, llvm_double_ty),
+ (stages allKinds)>];
+}
+
+def SMax : DXILOp {
+ let Doc = "Signed integer maximum. SMax(a,b) = a > b ? a : b";
+ let OpCode = 37;
+ let OpClass = binary;
+ let LLVMIntrinsic = int_smax;
+ let OpOverloadTypes = [llvm_i16_ty, llvm_i32_ty, llvm_i64_ty];
+ let arguments = (ins LLVMMatchType<0>, LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_i16_ty, llvm_i32_ty, llvm_i64_ty),
+ (stages allKinds)>];
+}
+
+def SMin : DXILOp {
+ let Doc = "Signed integer minimum. SMin(a,b) = a < b ? a : b";
+ let OpCode = 38;
+ let OpClass = binary;
+ let LLVMIntrinsic = int_smin;
+ let OpOverloadTypes = [llvm_i16_ty, llvm_i32_ty, llvm_i64_ty];
+ let arguments = (ins LLVMMatchType<0>, LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_i16_ty, llvm_i32_ty, llvm_i64_ty),
+ (stages allKinds)>];
+}
+
+def UMax : DXILOp {
+ let Doc = "Unsigned integer maximum. UMax(a,b) = a > b ? a : b";
+ let OpCode = 39;
+ let OpClass = binary;
+ let LLVMIntrinsic = int_umax;
+ let OpOverloadTypes = [llvm_i16_ty, llvm_i32_ty, llvm_i64_ty];
+ let arguments = (ins LLVMMatchType<0>, LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_i16_ty, llvm_i32_ty, llvm_i64_ty),
+ (stages allKinds)>];
+}
+
+def UMin : DXILOp {
+ let Doc = "Unsigned integer minimum. UMin(a,b) = a < b ? a : b";
+ let OpCode = 40;
+ let OpClass = binary;
+ let LLVMIntrinsic = int_umin;
+ let OpOverloadTypes = [llvm_i16_ty, llvm_i32_ty, llvm_i64_ty];
+ let arguments = (ins LLVMMatchType<0>, LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_i16_ty, llvm_i32_ty, llvm_i64_ty),
+ (stages allKinds)>];
+}
+
+def FMad : DXILOp {
+ let Doc = "Floating point arithmetic multiply/add operation. fmad(m,a,b) = m * a + b.";
+ let OpCode = 46;
+ let OpClass = tertiary;
+ let LLVMIntrinsic = int_fmuladd;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty, llvm_double_ty];
+ let arguments = (ins LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty, llvm_double_ty),
+ (stages allKinds)>];
+}
+
+def IMad : DXILOp {
+ let OpCode = 48;
+ let OpClass = tertiary;
+ let LLVMIntrinsic = int_dx_imad;
+ let OpOverloadTypes = [llvm_i16_ty, llvm_i32_ty, llvm_i64_ty];
+ let Doc = "Signed integer arithmetic multiply/add operation. imad(m,a,b) = m * a + b.";
+ let arguments = (ins LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_i16_ty, llvm_i32_ty, llvm_i64_ty),
+ (stages allKinds)>];
+}
+
+def UMad : DXILOp {
+ let OpCode = 49;
+ let OpClass = tertiary;
+ let LLVMIntrinsic = int_dx_umad;
+ let OpOverloadTypes = [llvm_i16_ty, llvm_i32_ty, llvm_i64_ty];
+ let Doc = "Unsigned integer arithmetic multiply/add operation. umad(m,a, = m * a + b.";
+ let arguments = (ins LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>);
+ let result = (out dxil_overload_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_i16_ty, llvm_i32_ty, llvm_i64_ty),
+ (stages allKinds)>];
+}
+
+def Dot2 : DXILOp {
+ 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 OpCode = 54;
+ let OpClass = dot2;
+ let LLVMIntrinsic = int_dx_dot2;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = !dag(ins, !listsplat(llvm_anyfloat_ty, 4), !listsplat("", 4));
+ let result = (out llvm_anyfloat_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+}
+
+def Dot3 : DXILOp {
+ 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 OpCode = 55;
+ let OpClass = dot3;
+ let LLVMIntrinsic = int_dx_dot3;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = !dag(ins, !listsplat(llvm_anyfloat_ty, 6), !listsplat("", 6));
+ let result = (out llvm_anyfloat_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+}
+
+def Dot4 : DXILOp {
+ 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 OpCode = 56;
+ let OpClass = dot4;
+ let LLVMIntrinsic = int_dx_dot4;
+ let OpOverloadTypes = [llvm_half_ty, llvm_float_ty];
+ let arguments = !dag(ins, !listsplat(llvm_anyfloat_ty, 8), !listsplat("", 8));
+ let result = (out llvm_anyfloat_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0,
+ (overloads llvm_half_ty, llvm_float_ty),
+ (stages allKinds)>];
+}
+
+def ThreadId : DXILOp {
+ let Doc = "Reads the thread ID";
+ let OpCode = 93;
+ let OpClass = threadId;
+ let LLVMIntrinsic = int_dx_thread_id;
+ let OpOverloadTypes = [llvm_i32_ty];
+ let arguments = (ins llvm_i32_ty);
+ let result = (out llvm_i32_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0, (overloads llvm_i32_ty),
+ (stages compute, mesh, amplification, node)>];
+}
+
+def GroupId : DXILOp {
+ let Doc = "Reads the group ID (SV_GroupID)";
+ let OpCode = 94;
+ let OpClass = groupId;
+ let LLVMIntrinsic = int_dx_group_id;
+ let OpOverloadTypes = [llvm_i32_ty];
+ let arguments = (ins llvm_i32_ty);
+ let result = (out llvm_i32_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0, (overloads llvm_i32_ty),
+ (stages compute, mesh, amplification, node)>];
+}
+
+def ThreadIdInGroup : DXILOp {
+ let Doc = "Reads the thread ID within the group (SV_GroupThreadID)";
+ let OpCode = 95;
+ let OpClass = threadIdInGroup;
+ let LLVMIntrinsic = int_dx_thread_id_in_group;
+ let OpOverloadTypes = [llvm_i32_ty];
+ let arguments = (ins llvm_i32_ty);
+ let result = (out llvm_i32_ty);
+ let sm_constraints = [SMVersionConstraints<SM6_0, (overloads llvm_i32_ty),
+ (stages compute, mesh, amplification, node)>];
+}
+
+def FlattenedThreadIdInGroup : DXILOp {
+ let Doc = "Provides a flattened index for a given thread within a given group (SV_GroupIndex)";
+ let OpCode = 96;
+ let OpClass = flattenedThreadIdInGroup;
+ let LLVMIntrinsic = int_dx_flattened_thread_id_in_group;
+ let OpOverloadTypes =[llvm_i32_ty];
+ let arguments = (ins llvm_i32_ty);
+ let result = (out);
+ let sm_constraints = [SMVersionConstraints<SM6_0, (overloads llvm_i32_ty),
+ (stages compute, mesh, amplification, node)>];
+}
diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
index 0b3982ea0f438..f90eb21122eba 100644
--- a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
@@ -11,6 +11,7 @@
#include "DXILOpBuilder.h"
#include "DXILConstants.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/DXILABI.h"
@@ -21,50 +22,13 @@ using namespace llvm::dxil;
constexpr StringLiteral DXILOpNamePrefix = "dx.op.";
-namespace {
-
-enum OverloadKind : uint16_t {
- VOID = 1,
- HALF = 1 << 1,
- FLOAT = 1 << 2,
- DOUBLE = 1 << 3,
- I1 = 1 << 4,
- I8 = 1 << 5,
- I16 = 1 << 6,
- I32 = 1 << 7,
- I64 = 1 << 8,
- UserDefineType = 1 << 9,
- ObjectType = 1 << 10,
-};
-
-} // namespace
-
-static const char *getOverloadTypeName(OverloadKind Kind) {
- switch (Kind) {
- case OverloadKind::HALF:
- return "f16";
- case OverloadKind::FLOAT:
- return "f32";
- case OverloadKind::DOUBLE:
- return "f64";
- case OverloadKind::I1:
- return "i1";
- case OverloadKind::I8:
- return "i8";
- case OverloadKind::I16:
- return "i16";
- case OverloadKind::I32:
- return "i32";
- case OverloadKind::I64:
- return "i64";
- case OverloadKind::VOID:
- case OverloadKind::ObjectType:
- case OverloadKind::UserDefineType:
- break;
- }
- llvm_unreachable("invalid overload type for name");
- return "void";
-}
+// Include DXIL Operation data and corresponding access functions
+// generated by the TableGen backend DXILEmitter.
+#define DXIL_OP_OPERATION_TABLE
+#define SHADER_KIND_ENUM
+#include "DXILOperation.inc"
+#undef SHADER_KIND_ENUM
+#undef DXIL_OP_OPERATION_TABLE
static OverloadKind getOverloadKind(Type *Ty) {
Type::TypeID T = Ty->getTypeID();
@@ -97,7 +61,7 @@ static OverloadKind getOverloadKind(Type *Ty) {
}
}
case Type::PointerTyID:
- return OverloadKind::UserDefineType;
+ return OverloadKind::UserDefinedType;
case Type::StructTyID:
return OverloadKind::ObjectType;
default:
@@ -107,9 +71,9 @@ static OverloadKind getOverloadKind(Type *Ty) {
}
static std::string getTypeName(OverloadKind Kind, Type *Ty) {
- if (Kind < OverloadKind::UserDefineType) {
+ if (Kind < OverloadKind::UserDefinedType) {
return getOverloadTypeName(Kind);
- } else if (Kind == OverloadKind::UserDefineType) {
+ } else if (Kind == OverloadKind::UserDefinedType) {
StructType *ST = cast<StructType>(Ty);
return ST->getStructName().str();
} else if (Kind == OverloadKind::ObjectType) {
@@ -123,28 +87,6 @@ static std::string getTypeName(OverloadKind Kind, Type *Ty) {
}
}
-// Static properties.
-struct OpCodeProperty {
- dxil::OpCode OpCode;
- // Offset in DXILOpCodeNameTable.
- unsigned OpCodeNameOffset;
- dxil::OpCodeClass OpCodeClass;
- // Offset in DXILOpCodeClassNameTable.
- unsigned OpCodeClassNameOffset;
- uint16_t OverloadTys;
- llvm::Attribute::AttrKind FuncAttr;
- 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
-// getOpCodeParameterKind which generated by tableGen.
-#define DXIL_OP_OPERATION_TABLE
-#include "DXILOperation.inc"
-#undef DXIL_OP_OPERATION_TABLE
-
static std::string constructOverloadName(OverloadKind Kind, Type *Ty,
const OpCodeProperty &Prop) {
if (Kind == OverloadKind::VOID) {
@@ -160,7 +102,7 @@ static std::string constructOverloadTypeName(OverloadKind Kind,
if (Kind == OverloadKind::VOID)
return TypeName.str();
- assert(Kind < OverloadKind::UserDefineType && "invalid overload kind");
+ assert(Kind < OverloadKind::UserDefinedType && "invalid overload kind");
return (Twine(TypeName) + getOverloadTypeName(Kind)).str();
}
@@ -249,19 +191,59 @@ static FunctionType *getDXILOpFunctionType(const OpCodeProperty *Prop,
ArgTys[0], ArrayRef<Type *>(&ArgTys[1], ArgTys.size() - 1), false);
}
+static int getValidConstraintIndex(const OpCodeProperty *Prop,
+ const VersionTuple SMVer) {
+ // std::vector Prop->SMConstraints is in ascending order of SM Version
+ // Overloads of highest SM version that is not greater than SMVer
+ // are the ones that are valid for SMVer.
+ auto Size = Prop->SMConstraints.size();
+ for (unsigned I = Size - 1; I >= 0; I--) {
+ auto OL = Prop->SMConstraints[I];
+ if (VersionTuple(OL.ShaderModelVer.Major, OL.ShaderModelVer.Minor) <=
+ SMVer) {
+ return I;
+ }
+ }
+ report_fatal_error(
+ StringRef(SMVer.getAsString().append(": Unhandled Shader Model Version")),
+ /*gen_crash_diag*/ false);
+
+ return -1;
+}
+
namespace llvm {
namespace dxil {
-CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode, Type *ReturnTy,
+CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode,
+ VersionTuple SMVer,
+ StringRef StageKind, Type *ReturnTy,
Type *OverloadTy,
SmallVector<Value *> Args) {
const OpCodeProperty *Prop = getOpCodeProperty(OpCode);
+ int Index = getValidConstraintIndex(Prop, SMVer);
+ uint16_t ValidTyMask = Prop->SMConstraints[Index].ValidTys;
OverloadKind Kind = getOverloadKind(OverloadTy);
- if ((Prop->OverloadTys & (uint16_t)Kind) == 0) {
+ if ((ValidTyMask & (uint16_t)Kind) == 0) {
report_fatal_error("Invalid Overload Type", /* gen_crash_diag=*/false);
}
+ // Ensure Opcode is valid in the targetted shader kind
+
+ uint16_t ValidShaderKindMask = Prop->SMConstraints[Index].ValidShaderKinds;
+
+ if (ValidShaderKindMask == ShaderKind::Unknown) {
+ report_fatal_error(
+ StringRef(SMVer.getAsString().append(": Unhandled Shader Kind")),
+ /*gen_crash_diag*/ false);
+ }
+
+ if (!(ValidShaderKindMask | getShaderkKindEnum(StageKind))) {
+ report_fatal_error(StringRef(std::string(StageKind).append(
+ " : Invalid stage for operation")),
+ /*gen_crash_diag*/ false);
+ }
+
std::string DXILFnName = constructOverloadName(Kind, OverloadTy, *Prop);
FunctionCallee DXILFn;
// Get the function with name DXILFnName, if one exists
@@ -276,14 +258,23 @@ CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode, Type *ReturnTy,
return B.CreateCall(DXILFn, Args);
}
-Type *DXILOpBuilder::getOverloadTy(dxil::OpCode OpCode, FunctionType *FT) {
+Type *DXILOpBuilder::getOverloadTy(dxil::OpCode OpCode, VersionTuple SMVer,
+ FunctionType *FT) {
const OpCodeProperty *Prop = getOpCodeProperty(OpCode);
// If DXIL Op has no overload parameter, just return the
// precise return type specified.
if (Prop->OverloadParamIndex < 0) {
auto &Ctx = FT->getContext();
- switch (Prop->OverloadTys) {
+ int Index = getValidConstraintIndex(Prop, SMVer);
+ uint16_t ValidTyMask = Prop->SMConstraints[Index].ValidTys;
+
+ if (ValidTyMask == 0) {
+ report_fatal_error(StringRef(SMVer.getAsString().append(
+ ": Unhandled Shader Model Version")),
+ /*gen_crash_diag*/ false);
+ }
+ switch (ValidTyMask) {
case OverloadKind::VOID:
return Type::getVoidTy(Ctx);
case OverloadKind::HALF:
@@ -308,14 +299,15 @@ Type *DXILOpBuilder::getOverloadTy(dxil::OpCode OpCode, FunctionType *FT) {
}
}
- // Prop->OverloadParamIndex is 0, overload type is FT->getReturnType().
+ // Consider FT->getReturnType() as default overload type, unless
+ // Prop->OverloadParamIndex != 0.
Type *OverloadType = FT->getReturnType();
if (Prop->OverloadParamIndex != 0) {
// Skip Return Type.
OverloadType = FT->getParamType(Prop->OverloadParamIndex - 1);
}
- auto ParamKinds = getOpCodeParameterKind(*Prop);
+ const auto *ParamKinds = getOpCodeParameterKind(*Prop);
auto Kind = ParamKinds[Prop->OverloadParamIndex];
// For ResRet and CBufferRet, OverloadTy is in field of StructType.
if (Kind == ParameterKind::CBufferRet ||
diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.h b/llvm/lib/Target/DirectX/DXILOpBuilder.h
index 5babeae470178..1abb7da7cb1b6 100644
--- a/llvm/lib/Target/DirectX/DXILOpBuilder.h
+++ b/llvm/lib/Target/DirectX/DXILOpBuilder.h
@@ -14,7 +14,8 @@
#include "DXILConstants.h"
#include "llvm/ADT/SmallVector.h"
-
+#include "llvm/Support/DXILABI.h"
+#include "llvm/Support/VersionTuple.h"
namespace llvm {
class Module;
class IRBuilderBase;
@@ -30,13 +31,21 @@ class DXILOpBuilder {
public:
DXILOpBuilder(Module &M, IRBuilderBase &B) : M(M), B(B) {}
/// Create an instruction that calls DXIL Op with return type, specified
- /// opcode, and call arguments. \param OpCode Opcode of the DXIL Op call
- /// constructed \param ReturnTy Return type of the DXIL Op call constructed
+ /// opcode, and call arguments.
+ ///
+ /// \param OpCode Opcode of the DXIL Op call constructed
+ /// \param SMVer Shader Model Version of DXIL Module being constructed.
+ /// \param StageKind Shader Stage for DXIL Module being constructed.
+ /// \param ReturnTy Return type of the DXIL Op call constructed
/// \param OverloadTy Overload type of the DXIL Op call constructed
+ /// \param Args Arguments for the DXIL Op call constructed
/// \return DXIL Op call constructed
- CallInst *createDXILOpCall(dxil::OpCode OpCode, Type *ReturnTy,
+ CallInst *createDXILOpCall(dxil::OpCode OpCode, VersionTuple SMVer,
+ StringRef StageKind, Type *ReturnTy,
Type *OverloadTy, SmallVector<Value *> Args);
- Type *getOverloadTy(dxil::OpCode OpCode, FunctionType *FT);
+
+ Type *getOverloadTy(dxil::OpCode OpCode, VersionTuple SMVer,
+ FunctionType *FT);
static const char *getOpCodeName(dxil::OpCode DXILOp);
private:
diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
index 1329308ffec26..eb55a661279c2 100644
--- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
@@ -22,9 +22,12 @@
#include "llvm/IR/IntrinsicsDirectX.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
+#include "llvm/MC/TargetRegistry.h"
#include "llvm/Pass.h"
#include "llvm/Support/ErrorHandling.h"
+#include "iostream"
+
#define DEBUG_TYPE "dxil-op-lower"
using namespace llvm;
@@ -72,10 +75,39 @@ static SmallVector<Value *> argVectorFlatten(CallInst *Orig,
return NewOperands;
}
+static VersionTuple getShaderModelVer(Module &M) {
+ std::string TTStr = M.getTargetTriple();
+ std::string Error;
+ auto Target = TargetRegistry::lookupTarget(TTStr, Error);
+ if (!Target) {
+ if (TTStr.empty()) {
+ report_fatal_error(StringRef(Error), /*gen_crash_diag*/ false);
+ }
+ }
+ auto Major = Triple(TTStr).getOSVersion().getMajor();
+ auto MinorOrErr = Triple(TTStr).getOSVersion().getMinor();
+ uint32_t Minor = MinorOrErr.has_value() ? *MinorOrErr : 0;
+ return VersionTuple(Major, Minor);
+}
+
+static StringRef getShaderKind(Module &M) {
+ std::string TTStr = M.getTargetTriple();
+ std::string Error;
+ auto Target = TargetRegistry::lookupTarget(TTStr, Error);
+ if (!Target) {
+ if (TTStr.empty()) {
+ report_fatal_error(StringRef(Error), /*gen_crash_diag*/ false);
+ }
+ }
+ return Triple(TTStr).getEnvironmentName();
+}
+
static void lowerIntrinsic(dxil::OpCode DXILOp, Function &F, Module &M) {
IRBuilder<> B(M.getContext());
DXILOpBuilder DXILB(M, B);
- Type *OverloadTy = DXILB.getOverloadTy(DXILOp, F.getFunctionType());
+ VersionTuple SMVer = getShaderModelVer(M);
+ StringRef Stagekind = getShaderKind(M);
+ Type *OverloadTy = DXILB.getOverloadTy(DXILOp, SMVer, F.getFunctionType());
for (User *U : make_early_inc_range(F.users())) {
CallInst *CI = dyn_cast<CallInst>(U);
if (!CI)
@@ -91,8 +123,8 @@ static void lowerIntrinsic(dxil::OpCode DXILOp, Function &F, Module &M) {
} else
Args.append(CI->arg_begin(), CI->arg_end());
- CallInst *DXILCI =
- DXILB.createDXILOpCall(DXILOp, F.getReturnType(), OverloadTy, Args);
+ CallInst *DXILCI = DXILB.createDXILOpCall(
+ DXILOp, SMVer, Stagekind, F.getReturnType(), OverloadTy, Args);
CI->replaceAllUsesWith(DXILCI);
CI->eraseFromParent();
diff --git a/llvm/test/CodeGen/DirectX/abs.ll b/llvm/test/CodeGen/DirectX/abs.ll
index 822580e8c089a..85090a51c55a4 100644
--- a/llvm/test/CodeGen/DirectX/abs.ll
+++ b/llvm/test/CodeGen/DirectX/abs.ll
@@ -1,5 +1,5 @@
-; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
+; RUN: opt -S -dxil-intrinsic-expansion -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
; Make sure dxil operation function calls for abs are generated for int16_t/int/int64_t.
diff --git a/llvm/test/CodeGen/DirectX/acos.ll b/llvm/test/CodeGen/DirectX/acos.ll
index 31b08833f45a1..cc32182395627 100644
--- a/llvm/test/CodeGen/DirectX/acos.ll
+++ b/llvm/test/CodeGen/DirectX/acos.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for acos are generated for float and half.
diff --git a/llvm/test/CodeGen/DirectX/acos_error.ll b/llvm/test/CodeGen/DirectX/acos_error.ll
index e0474e9b758e7..4125709a57e7a 100644
--- a/llvm/test/CodeGen/DirectX/acos_error.ll
+++ b/llvm/test/CodeGen/DirectX/acos_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
; DXIL operation acos does not support double overload type
; CHECK: LLVM ERROR: Invalid Overload
diff --git a/llvm/test/CodeGen/DirectX/asin.ll b/llvm/test/CodeGen/DirectX/asin.ll
index 56c2d86be3547..06e3bab545a6a 100644
--- a/llvm/test/CodeGen/DirectX/asin.ll
+++ b/llvm/test/CodeGen/DirectX/asin.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for asin are generated for float and half.
diff --git a/llvm/test/CodeGen/DirectX/asin_error.ll b/llvm/test/CodeGen/DirectX/asin_error.ll
index ddd4b2e424f62..de63b0d6be027 100644
--- a/llvm/test/CodeGen/DirectX/asin_error.ll
+++ b/llvm/test/CodeGen/DirectX/asin_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
; DXIL operation asin does not support double overload type
; CHECK: LLVM ERROR: Invalid Overload
diff --git a/llvm/test/CodeGen/DirectX/atan.ll b/llvm/test/CodeGen/DirectX/atan.ll
index 7aa4418a59813..d7c4cd00e286a 100644
--- a/llvm/test/CodeGen/DirectX/atan.ll
+++ b/llvm/test/CodeGen/DirectX/atan.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for atan are generated for float and half.
diff --git a/llvm/test/CodeGen/DirectX/atan_error.ll b/llvm/test/CodeGen/DirectX/atan_error.ll
index 1880b1d38ba3c..c320868ef4e57 100644
--- a/llvm/test/CodeGen/DirectX/atan_error.ll
+++ b/llvm/test/CodeGen/DirectX/atan_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
; DXIL operation atan does not support double overload type
; CHECK: LLVM ERROR: Invalid Overload
diff --git a/llvm/test/CodeGen/DirectX/ceil.ll b/llvm/test/CodeGen/DirectX/ceil.ll
index 1585471467801..48bc5495a8e05 100644
--- a/llvm/test/CodeGen/DirectX/ceil.ll
+++ b/llvm/test/CodeGen/DirectX/ceil.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for ceil are generated for float and half.
diff --git a/llvm/test/CodeGen/DirectX/ceil_error.ll b/llvm/test/CodeGen/DirectX/ceil_error.ll
index 1b554d8715566..da6f083550186 100644
--- a/llvm/test/CodeGen/DirectX/ceil_error.ll
+++ b/llvm/test/CodeGen/DirectX/ceil_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
; DXIL operation ceil does not support double overload type
; CHECK: LLVM ERROR: Invalid Overload Type
diff --git a/llvm/test/CodeGen/DirectX/clamp.ll b/llvm/test/CodeGen/DirectX/clamp.ll
index f122313b8d7dc..2f29e4479f9ca 100644
--- a/llvm/test/CodeGen/DirectX/clamp.ll
+++ b/llvm/test/CodeGen/DirectX/clamp.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for clamp/uclamp are generated for half/float/double/i16/i32/i64.
diff --git a/llvm/test/CodeGen/DirectX/cos.ll b/llvm/test/CodeGen/DirectX/cos.ll
index 00f2e2c3f6e5a..72f4bfca23f9d 100644
--- a/llvm/test/CodeGen/DirectX/cos.ll
+++ b/llvm/test/CodeGen/DirectX/cos.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for cos are generated for float and half.
diff --git a/llvm/test/CodeGen/DirectX/cos_error.ll b/llvm/test/CodeGen/DirectX/cos_error.ll
index a074f5b493dfd..6bb85a7cec1e3 100644
--- a/llvm/test/CodeGen/DirectX/cos_error.ll
+++ b/llvm/test/CodeGen/DirectX/cos_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
; DXIL operation cos does not support double overload type
; CHECK: LLVM ERROR: Invalid Overload Type
diff --git a/llvm/test/CodeGen/DirectX/cosh.ll b/llvm/test/CodeGen/DirectX/cosh.ll
index 4fe22f0a38ce1..91aaf893f3997 100644
--- a/llvm/test/CodeGen/DirectX/cosh.ll
+++ b/llvm/test/CodeGen/DirectX/cosh.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for cosh are generated for float and half.
diff --git a/llvm/test/CodeGen/DirectX/cosh_error.ll b/llvm/test/CodeGen/DirectX/cosh_error.ll
index cf66c54db1a08..4c5f0c7146ab5 100644
--- a/llvm/test/CodeGen/DirectX/cosh_error.ll
+++ b/llvm/test/CodeGen/DirectX/cosh_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
; DXIL operation cosh does not support double overload type
; CHECK: LLVM ERROR: Invalid Overload
diff --git a/llvm/test/CodeGen/DirectX/dot2_error.ll b/llvm/test/CodeGen/DirectX/dot2_error.ll
index a27bfaedacd57..54780d18e71fb 100644
--- a/llvm/test/CodeGen/DirectX/dot2_error.ll
+++ b/llvm/test/CodeGen/DirectX/dot2_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
; DXIL operation dot2 does not support double overload type
; CHECK: LLVM ERROR: Invalid Overload
diff --git a/llvm/test/CodeGen/DirectX/dot3_error.ll b/llvm/test/CodeGen/DirectX/dot3_error.ll
index eb69fb145038a..242716b0b71ba 100644
--- a/llvm/test/CodeGen/DirectX/dot3_error.ll
+++ b/llvm/test/CodeGen/DirectX/dot3_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
; DXIL operation dot3 does not support double overload type
; CHECK: LLVM ERROR: Invalid Overload
diff --git a/llvm/test/CodeGen/DirectX/dot4_error.ll b/llvm/test/CodeGen/DirectX/dot4_error.ll
index 5cd632684c0c0..731adda153def 100644
--- a/llvm/test/CodeGen/DirectX/dot4_error.ll
+++ b/llvm/test/CodeGen/DirectX/dot4_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
; DXIL operation dot4 does not support double overload type
; CHECK: LLVM ERROR: Invalid Overload
diff --git a/llvm/test/CodeGen/DirectX/exp.ll b/llvm/test/CodeGen/DirectX/exp.ll
index fdafc1438cf0e..f67e2744c4ee3 100644
--- a/llvm/test/CodeGen/DirectX/exp.ll
+++ b/llvm/test/CodeGen/DirectX/exp.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for exp are generated for float and half.
diff --git a/llvm/test/CodeGen/DirectX/exp2_error.ll b/llvm/test/CodeGen/DirectX/exp2_error.ll
index 6b9126785fd4b..4d13f936eb6be 100644
--- a/llvm/test/CodeGen/DirectX/exp2_error.ll
+++ b/llvm/test/CodeGen/DirectX/exp2_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
; DXIL operation exp2 does not support double overload type
; CHECK: LLVM ERROR: Invalid Overload
diff --git a/llvm/test/CodeGen/DirectX/fabs.ll b/llvm/test/CodeGen/DirectX/fabs.ll
index 3b3f8aa9a4a92..becbdf8d68aeb 100644
--- a/llvm/test/CodeGen/DirectX/fabs.ll
+++ b/llvm/test/CodeGen/DirectX/fabs.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for abs are generated for float, half, and double.
diff --git a/llvm/test/CodeGen/DirectX/fdot.ll b/llvm/test/CodeGen/DirectX/fdot.ll
index 3e13b2ad2650c..56817a172ff9e 100644
--- a/llvm/test/CodeGen/DirectX/fdot.ll
+++ b/llvm/test/CodeGen/DirectX/fdot.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for dot are generated for int/uint vectors.
diff --git a/llvm/test/CodeGen/DirectX/floor.ll b/llvm/test/CodeGen/DirectX/floor.ll
index b033e2eaa491e..f667cab4aa249 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 < %s | FileCheck %s
+; RUN: opt -S -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/floor_error.ll b/llvm/test/CodeGen/DirectX/floor_error.ll
index 3b51a4b543b7f..e3190e5afb63f 100644
--- a/llvm/test/CodeGen/DirectX/floor_error.ll
+++ b/llvm/test/CodeGen/DirectX/floor_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
; DXIL operation floor does not support double overload type
; CHECK: LLVM ERROR: Invalid Overload Type
diff --git a/llvm/test/CodeGen/DirectX/fmax.ll b/llvm/test/CodeGen/DirectX/fmax.ll
index aff722c29309c..05852ee33486d 100644
--- a/llvm/test/CodeGen/DirectX/fmax.ll
+++ b/llvm/test/CodeGen/DirectX/fmax.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for fmax are generated for half/float/double.
diff --git a/llvm/test/CodeGen/DirectX/fmin.ll b/llvm/test/CodeGen/DirectX/fmin.ll
index 2f7c209f0278a..1c6c7ca3f2e38 100644
--- a/llvm/test/CodeGen/DirectX/fmin.ll
+++ b/llvm/test/CodeGen/DirectX/fmin.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for fmin are generated for half/float/double.
diff --git a/llvm/test/CodeGen/DirectX/frac_error.ll b/llvm/test/CodeGen/DirectX/frac_error.ll
index ebce76105ad4d..1bc3558ab0c9a 100644
--- a/llvm/test/CodeGen/DirectX/frac_error.ll
+++ b/llvm/test/CodeGen/DirectX/frac_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
; DXIL operation frac does not support double overload type
; CHECK: LLVM ERROR: Invalid Overload Type
diff --git a/llvm/test/CodeGen/DirectX/idot.ll b/llvm/test/CodeGen/DirectX/idot.ll
index 9f89a8d6d340d..eac1b91106dde 100644
--- a/llvm/test/CodeGen/DirectX/idot.ll
+++ b/llvm/test/CodeGen/DirectX/idot.ll
@@ -1,5 +1,5 @@
-; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
+; RUN: opt -S -dxil-intrinsic-expansion -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
; Make sure dxil operation function calls for dot are generated for int/uint vectors.
diff --git a/llvm/test/CodeGen/DirectX/isinf.ll b/llvm/test/CodeGen/DirectX/isinf.ll
index e2975da90bfc1..295776b089347 100644
--- a/llvm/test/CodeGen/DirectX/isinf.ll
+++ b/llvm/test/CodeGen/DirectX/isinf.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for isinf are generated for float and half.
; CHECK: call i1 @dx.op.isSpecialFloat.f32(i32 9, float %{{.*}})
diff --git a/llvm/test/CodeGen/DirectX/isinf_error.ll b/llvm/test/CodeGen/DirectX/isinf_error.ll
index 95b2d0cabcc43..39b83554d74d0 100644
--- a/llvm/test/CodeGen/DirectX/isinf_error.ll
+++ b/llvm/test/CodeGen/DirectX/isinf_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
; DXIL operation isinf does not support double overload type
; CHECK: LLVM ERROR: Invalid Overload Type
diff --git a/llvm/test/CodeGen/DirectX/log.ll b/llvm/test/CodeGen/DirectX/log.ll
index 172c3bfed3b77..ee289088d243b 100644
--- a/llvm/test/CodeGen/DirectX/log.ll
+++ b/llvm/test/CodeGen/DirectX/log.ll
@@ -1,5 +1,5 @@
-; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
+; RUN: opt -S -dxil-intrinsic-expansion -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
; Make sure dxil operation function calls for log are generated.
diff --git a/llvm/test/CodeGen/DirectX/log10.ll b/llvm/test/CodeGen/DirectX/log10.ll
index d4f827a0d1af8..a69f270f9dc88 100644
--- a/llvm/test/CodeGen/DirectX/log10.ll
+++ b/llvm/test/CodeGen/DirectX/log10.ll
@@ -1,5 +1,5 @@
-; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
+; RUN: opt -S -dxil-intrinsic-expansion -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
; Make sure dxil operation function calls for log10 are generated.
diff --git a/llvm/test/CodeGen/DirectX/log2.ll b/llvm/test/CodeGen/DirectX/log2.ll
index 2164d4db9396d..d6a7ba0b7dda7 100644
--- a/llvm/test/CodeGen/DirectX/log2.ll
+++ b/llvm/test/CodeGen/DirectX/log2.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for log2 are generated for float and half.
diff --git a/llvm/test/CodeGen/DirectX/log2_error.ll b/llvm/test/CodeGen/DirectX/log2_error.ll
index a26f6e8c3117f..b8876854d389f 100644
--- a/llvm/test/CodeGen/DirectX/log2_error.ll
+++ b/llvm/test/CodeGen/DirectX/log2_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
; DXIL operation log2 does not support double overload type
; CHECK: LLVM ERROR: Invalid Overload Type
diff --git a/llvm/test/CodeGen/DirectX/pow.ll b/llvm/test/CodeGen/DirectX/pow.ll
index 25ce0fe731d0b..0e83c4ff8add6 100644
--- a/llvm/test/CodeGen/DirectX/pow.ll
+++ b/llvm/test/CodeGen/DirectX/pow.ll
@@ -1,5 +1,5 @@
-; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
+; RUN: opt -S -dxil-intrinsic-expansion -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
; Make sure dxil operation function calls for pow are generated.
diff --git a/llvm/test/CodeGen/DirectX/reversebits.ll b/llvm/test/CodeGen/DirectX/reversebits.ll
index b6a7a1bc6152e..1ade57b40100f 100644
--- a/llvm/test/CodeGen/DirectX/reversebits.ll
+++ b/llvm/test/CodeGen/DirectX/reversebits.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for reversebits are generated for all integer types.
diff --git a/llvm/test/CodeGen/DirectX/round.ll b/llvm/test/CodeGen/DirectX/round.ll
index e0a3772ebca8f..db953fb29c204 100644
--- a/llvm/test/CodeGen/DirectX/round.ll
+++ b/llvm/test/CodeGen/DirectX/round.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for round are generated for float and half.
diff --git a/llvm/test/CodeGen/DirectX/round_error.ll b/llvm/test/CodeGen/DirectX/round_error.ll
index 2d27fbb5ee20d..9d2a4e778a924 100644
--- a/llvm/test/CodeGen/DirectX/round_error.ll
+++ b/llvm/test/CodeGen/DirectX/round_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
; This test is expected to fail with the following error
; CHECK: LLVM ERROR: Invalid Overload Type
diff --git a/llvm/test/CodeGen/DirectX/rsqrt.ll b/llvm/test/CodeGen/DirectX/rsqrt.ll
index 52af0e62220b3..054c84483ef82 100644
--- a/llvm/test/CodeGen/DirectX/rsqrt.ll
+++ b/llvm/test/CodeGen/DirectX/rsqrt.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for rsqrt are generated for float and half.
diff --git a/llvm/test/CodeGen/DirectX/rsqrt_error.ll b/llvm/test/CodeGen/DirectX/rsqrt_error.ll
index 9cd5002c20f7e..5e29e37113d19 100644
--- a/llvm/test/CodeGen/DirectX/rsqrt_error.ll
+++ b/llvm/test/CodeGen/DirectX/rsqrt_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
; DXIL operation rsqrt does not support double overload type
; CHECK: LLVM ERROR: Invalid Overload Type
diff --git a/llvm/test/CodeGen/DirectX/sin.ll b/llvm/test/CodeGen/DirectX/sin.ll
index 1f285c433581c..f309a36c6b8e6 100644
--- a/llvm/test/CodeGen/DirectX/sin.ll
+++ b/llvm/test/CodeGen/DirectX/sin.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for sin are generated for float and half.
; CHECK:call float @dx.op.unary.f32(i32 13, float %{{.*}})
diff --git a/llvm/test/CodeGen/DirectX/sin_error.ll b/llvm/test/CodeGen/DirectX/sin_error.ll
index ece0e530315b2..0e20031501365 100644
--- a/llvm/test/CodeGen/DirectX/sin_error.ll
+++ b/llvm/test/CodeGen/DirectX/sin_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.0-library %s 2>&1 | FileCheck %s
; DXIL operation sin does not support double overload type
; CHECK: LLVM ERROR: Invalid Overload
diff --git a/llvm/test/CodeGen/DirectX/sinh.ll b/llvm/test/CodeGen/DirectX/sinh.ll
index 76d189836f393..d4d3eda9eccb6 100644
--- a/llvm/test/CodeGen/DirectX/sinh.ll
+++ b/llvm/test/CodeGen/DirectX/sinh.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for sinh are generated for float and half.
diff --git a/llvm/test/CodeGen/DirectX/sinh_error.ll b/llvm/test/CodeGen/DirectX/sinh_error.ll
index 6a021ce88eb3b..06aeca0339261 100644
--- a/llvm/test/CodeGen/DirectX/sinh_error.ll
+++ b/llvm/test/CodeGen/DirectX/sinh_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
; DXIL operation sinh does not support double overload type
; CHECK: LLVM ERROR: Invalid Overload
diff --git a/llvm/test/CodeGen/DirectX/smax.ll b/llvm/test/CodeGen/DirectX/smax.ll
index 8b2406782c093..bcda51cb0bfba 100644
--- a/llvm/test/CodeGen/DirectX/smax.ll
+++ b/llvm/test/CodeGen/DirectX/smax.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for smax are generated for i16/i32/i64.
diff --git a/llvm/test/CodeGen/DirectX/smin.ll b/llvm/test/CodeGen/DirectX/smin.ll
index b2b40a1b62433..8d4884704df21 100644
--- a/llvm/test/CodeGen/DirectX/smin.ll
+++ b/llvm/test/CodeGen/DirectX/smin.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for smin are generated for i16/i32/i64.
diff --git a/llvm/test/CodeGen/DirectX/sqrt.ll b/llvm/test/CodeGen/DirectX/sqrt.ll
index 76a572efd2055..792fbc8d0614d 100644
--- a/llvm/test/CodeGen/DirectX/sqrt.ll
+++ b/llvm/test/CodeGen/DirectX/sqrt.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for sqrt are generated for float and half.
diff --git a/llvm/test/CodeGen/DirectX/sqrt_error.ll b/llvm/test/CodeGen/DirectX/sqrt_error.ll
index fffa2e19b80fa..1477abc62c13a 100644
--- a/llvm/test/CodeGen/DirectX/sqrt_error.ll
+++ b/llvm/test/CodeGen/DirectX/sqrt_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
; DXIL operation sqrt does not support double overload type
; CHECK: LLVM ERROR: Invalid Overload Type
diff --git a/llvm/test/CodeGen/DirectX/tan.ll b/llvm/test/CodeGen/DirectX/tan.ll
index 567ab02d40f91..6f7beb592339a 100644
--- a/llvm/test/CodeGen/DirectX/tan.ll
+++ b/llvm/test/CodeGen/DirectX/tan.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for tan are generated for float and half.
diff --git a/llvm/test/CodeGen/DirectX/tan_error.ll b/llvm/test/CodeGen/DirectX/tan_error.ll
index c870c36f54925..fa03e531bd672 100644
--- a/llvm/test/CodeGen/DirectX/tan_error.ll
+++ b/llvm/test/CodeGen/DirectX/tan_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
; DXIL operation tan does not support double overload type
; CHECK: LLVM ERROR: Invalid Overload
diff --git a/llvm/test/CodeGen/DirectX/tanh.ll b/llvm/test/CodeGen/DirectX/tanh.ll
index d0313178c7ac3..e6642d9a74c8a 100644
--- a/llvm/test/CodeGen/DirectX/tanh.ll
+++ b/llvm/test/CodeGen/DirectX/tanh.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for tanh are generated for float and half.
diff --git a/llvm/test/CodeGen/DirectX/tanh_error.ll b/llvm/test/CodeGen/DirectX/tanh_error.ll
index a1b8cbf0e13bc..933ffbc87e23f 100644
--- a/llvm/test/CodeGen/DirectX/tanh_error.ll
+++ b/llvm/test/CodeGen/DirectX/tanh_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
; DXIL operation tanh does not support double overload type
; CHECK: LLVM ERROR: Invalid Overload
diff --git a/llvm/test/CodeGen/DirectX/trunc.ll b/llvm/test/CodeGen/DirectX/trunc.ll
index 2072f28cef50a..f00b737da4dbb 100644
--- a/llvm/test/CodeGen/DirectX/trunc.ll
+++ b/llvm/test/CodeGen/DirectX/trunc.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for trunc are generated for float and half.
diff --git a/llvm/test/CodeGen/DirectX/trunc_error.ll b/llvm/test/CodeGen/DirectX/trunc_error.ll
index 751b0b94c280d..ccc7b1df879ee 100644
--- a/llvm/test/CodeGen/DirectX/trunc_error.ll
+++ b/llvm/test/CodeGen/DirectX/trunc_error.ll
@@ -1,4 +1,4 @@
-; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
; DXIL operation trunc does not support double overload type
; CHECK: LLVM ERROR: Invalid Overload Type
diff --git a/llvm/test/CodeGen/DirectX/umax.ll b/llvm/test/CodeGen/DirectX/umax.ll
index be0f557fc8da6..a4bd66ef0bd6c 100644
--- a/llvm/test/CodeGen/DirectX/umax.ll
+++ b/llvm/test/CodeGen/DirectX/umax.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for umax are generated for i16/i32/i64.
diff --git a/llvm/test/CodeGen/DirectX/umin.ll b/llvm/test/CodeGen/DirectX/umin.ll
index 5051c71174489..a551f8ff3bfa9 100644
--- a/llvm/test/CodeGen/DirectX/umin.ll
+++ b/llvm/test/CodeGen/DirectX/umin.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Make sure dxil operation function calls for umin are generated for i16/i32/i64.
diff --git a/llvm/utils/TableGen/DXILEmitter.cpp b/llvm/utils/TableGen/DXILEmitter.cpp
index 0439df8067ede..24b94f68791f7 100644
--- a/llvm/utils/TableGen/DXILEmitter.cpp
+++ b/llvm/utils/TableGen/DXILEmitter.cpp
@@ -16,48 +16,40 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSet.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/CodeGenTypes/MachineValueType.h"
#include "llvm/Support/DXILABI.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/VersionTuple.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
+
#include <string>
+#include <vector>
using namespace llvm;
using namespace llvm::dxil;
namespace {
-struct DXILShaderModel {
- int Major = 0;
- int Minor = 0;
-};
-
struct DXILOperationDesc {
std::string OpName; // name of DXIL operation
int OpCode; // ID of DXIL operation
StringRef OpClass; // name of the opcode class
StringRef Doc; // the documentation description of this instruction
- SmallVector<Record *> OpTypes; // Vector of operand type records -
- // return type is at index 0
+ // Vector of operand type records - return type is at index 0
+ SmallVector<Record *> OpTypes;
+ // Vector of fixed types valid for operation overloads
+ // SmallVector<Record *> OpOverloads;
+ // Vector of constraints based on Shader Model version
+ SmallVector<Record *> SMConstraints;
SmallVector<std::string>
OpAttributes; // operation attribute represented as strings
StringRef Intrinsic; // The llvm intrinsic map to OpName. Default is "" which
// means no map exists
- bool IsDeriv = false; // whether this is some kind of derivative
- bool IsGradient = false; // whether this requires a gradient calculation
- bool IsFeedback = false; // whether this is a sampler feedback op
- bool IsWave =
- false; // whether this requires in-wave, cross-lane functionality
- bool RequiresUniformInputs = false; // whether this operation requires that
- // all of its inputs are uniform across
- // the wave
SmallVector<StringRef, 4>
ShaderStages; // shader stages to which this applies, empty for all.
- DXILShaderModel ShaderModel; // minimum shader model required
- DXILShaderModel ShaderModelTranslated; // minimum shader model required with
- // translation by linker
int OverloadParamIndex; // Index of parameter with overload type.
// -1 : no overload types
SmallVector<StringRef, 4> counters; // counters for this inst.
@@ -91,15 +83,11 @@ static ParameterKind getParameterKind(const Record *R) {
return ParameterKind::I32;
case MVT::fAny:
case MVT::iAny:
+ case MVT::Any:
return ParameterKind::Overload;
- case MVT::Other:
- // Handle DXIL-specific overload types
- if (R->getValueAsInt("isHalfOrFloat") || R->getValueAsInt("isI16OrI32")) {
- return ParameterKind::Overload;
- }
- [[fallthrough]];
default:
- llvm_unreachable("Support for specified DXIL Type not yet implemented");
+ llvm_unreachable(
+ "Support for specified parameter type not yet implemented");
}
}
@@ -113,9 +101,16 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) {
OpCode = R->getValueAsInt("OpCode");
Doc = R->getValueAsString("Doc");
-
- auto TypeRecs = R->getValueAsListOfDefs("OpTypes");
- unsigned TypeRecsSize = TypeRecs.size();
+ SmallVector<Record *> ParamTypeRecs;
+ DagInit *OutDag = R->getValueAsDag("result");
+ for (const Init *Arg : OutDag->getArgs()) {
+ ParamTypeRecs.push_back(cast<DefInit>(Arg)->getDef());
+ }
+ DagInit *InDag = R->getValueAsDag("arguments");
+ for (const Init *Arg : InDag->getArgs()) {
+ ParamTypeRecs.push_back(cast<DefInit>(Arg)->getDef());
+ }
+ unsigned ParamTypeRecsSize = ParamTypeRecs.size();
// Populate OpTypes with return type and parameter types
// Parameter indices of overloaded parameters.
@@ -124,32 +119,29 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) {
// the comment before the definition of class LLVMMatchType in
// llvm/IR/Intrinsics.td
SmallVector<int> OverloadParamIndices;
- for (unsigned i = 0; i < TypeRecsSize; i++) {
- auto TR = TypeRecs[i];
+ for (unsigned I = 0; I < ParamTypeRecsSize; I++) {
+ auto TR = ParamTypeRecs[I];
// Track operation parameter indices of any overload types
- auto isAny = TR->getValueAsInt("isAny");
- if (isAny == 1) {
+ auto IsAny = TR->getValueAsInt("isAny");
+ if (IsAny == 1) {
// TODO: At present it is expected that all overload types in a DXIL Op
// are of the same type. Hence, OverloadParamIndices will have only one
// element. This implies we do not need a vector. However, until more
// (all?) DXIL Ops are added in DXIL.td, a vector is being used to flag
// cases this assumption would not hold.
if (!OverloadParamIndices.empty()) {
- bool knownType = true;
+ bool KnownType = true;
// Ensure that the same overload type registered earlier is being used
for (auto Idx : OverloadParamIndices) {
- if (TR != TypeRecs[Idx]) {
- knownType = false;
+ if (TR != ParamTypeRecs[Idx]) {
+ KnownType = false;
break;
}
}
- if (!knownType) {
- report_fatal_error("Specification of multiple differing overload "
- "parameter types not yet supported",
- false);
- }
+ assert(KnownType && "Specification of multiple differing overload "
+ "parameter types not yet supported");
} else {
- OverloadParamIndices.push_back(i);
+ OverloadParamIndices.push_back(I);
}
}
// Populate OpTypes array according to the type specification
@@ -160,7 +152,7 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) {
// Get the parameter index of anonymous type, TR, references
auto OLParamIndex = TR->getValueAsInt("Number");
// Resolve and insert the type to that at OLParamIndex
- OpTypes.emplace_back(TypeRecs[OLParamIndex]);
+ OpTypes.emplace_back(ParamTypeRecs[OLParamIndex]);
} else {
// A non-anonymous type. Just record it in OpTypes
OpTypes.emplace_back(TR);
@@ -170,11 +162,35 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) {
// Set the index of the overload parameter, if any.
OverloadParamIndex = -1; // default; indicating none
if (!OverloadParamIndices.empty()) {
- if (OverloadParamIndices.size() > 1)
- report_fatal_error("Multiple overload type specification not supported",
- false);
+ assert(OverloadParamIndices.size() == 1 &&
+ "Multiple overload type specification not supported");
OverloadParamIndex = OverloadParamIndices[0];
}
+
+ // Get Shader Model Constraint Records
+ std::vector<Record *> SMConstrintRecs =
+ R->getValueAsListOfDefs("sm_constraints");
+
+ // Sort records in ascending order of Shader Model version
+ std::sort(SMConstrintRecs.begin(), SMConstrintRecs.end(),
+ [](Record *RecA, Record *RecB) {
+ unsigned RecAMaj =
+ RecA->getValueAsDef("sm_version")->getValueAsInt("Major");
+ unsigned RecAMin =
+ RecA->getValueAsDef("sm_version")->getValueAsInt("Minor");
+ unsigned RecBMaj =
+ RecB->getValueAsDef("sm_version")->getValueAsInt("Major");
+ unsigned RecBMin =
+ RecB->getValueAsDef("sm_version")->getValueAsInt("Minor");
+
+ return (VersionTuple(RecAMaj, RecAMin) <
+ VersionTuple(RecBMaj, RecBMin));
+ });
+
+ for (Record *SMCR : SMConstrintRecs) {
+ SMConstraints.push_back(SMCR);
+ }
+
// Get the operation class
OpClass = R->getValueAsDef("OpClass")->getName();
@@ -188,10 +204,10 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) {
// that of the intrinsic. Deviations are expected to be encoded in TableGen
// record specification and handled accordingly here. Support to be added
// as needed.
- auto IntrPropList = IntrinsicDef->getValueAsListInit("IntrProperties");
+ ListInit *IntrPropList = IntrinsicDef->getValueAsListInit("IntrProperties");
auto IntrPropListSize = IntrPropList->size();
- for (unsigned i = 0; i < IntrPropListSize; i++) {
- OpAttributes.emplace_back(IntrPropList->getElement(i)->getAsString());
+ for (unsigned I = 0; I < IntrPropListSize; I++) {
+ OpAttributes.emplace_back(IntrPropList->getElement(I)->getAsString());
}
}
}
@@ -239,10 +255,8 @@ static std::string getParameterKindStr(ParameterKind Kind) {
/// \return std::string string representation of OverloadKind
static std::string getOverloadKindStr(const Record *R) {
- auto VTRec = R->getValueAsDef("VT");
+ Record *VTRec = R->getValueAsDef("VT");
switch (getValueType(VTRec)) {
- case MVT::isVoid:
- return "OverloadKind::VOID";
case MVT::f16:
return "OverloadKind::HALF";
case MVT::f32:
@@ -259,24 +273,53 @@ static std::string getOverloadKindStr(const Record *R) {
return "OverloadKind::I32";
case MVT::i64:
return "OverloadKind::I64";
- case MVT::iAny:
- return "OverloadKind::I16 | OverloadKind::I32 | OverloadKind::I64";
- case MVT::fAny:
- return "OverloadKind::HALF | OverloadKind::FLOAT | OverloadKind::DOUBLE";
- case MVT::Other:
- // Handle DXIL-specific overload types
- {
- if (R->getValueAsInt("isHalfOrFloat")) {
- return "OverloadKind::HALF | OverloadKind::FLOAT";
- } else if (R->getValueAsInt("isI16OrI32")) {
- return "OverloadKind::I16 | OverloadKind::I32";
- }
- }
- [[fallthrough]];
default:
- llvm_unreachable(
- "Support for specified parameter OverloadKind not yet implemented");
+ llvm_unreachable("Support for specified fixed type option for overload "
+ "type not supported");
+ }
+}
+
+/// Return a string representation of OverloadKind enum that maps to
+/// input LLVMType record
+/// \param Recs A vector of records of TableGen class type DXILShaderModel
+/// \return std::string string representation of OverloadKind
+static std::string
+getOverloadKindStrsFromConstraint(const SmallVector<Record *> Recs) {
+ std::string OverloadString = "";
+ std::string Prefix = "";
+ OverloadString.append("{");
+ for (auto SMConstrRec : Recs) {
+ OverloadString.append(Prefix).append("{");
+ unsigned Major =
+ SMConstrRec->getValueAsDef("sm_version")->getValueAsInt("Major");
+ unsigned Minor =
+ SMConstrRec->getValueAsDef("sm_version")->getValueAsInt("Minor");
+ OverloadString.append("{")
+ .append(std::to_string(Major))
+ .append(", ")
+ .append(std::to_string(Minor).append("}, "));
+ auto OvDag = SMConstrRec->getValueAsDag("overload_types");
+ std::string PipePrefix = "";
+ for (const Init *Arg : OvDag->getArgs()) {
+ OverloadString.append(PipePrefix)
+ .append(getOverloadKindStr(cast<DefInit>(Arg)->getDef()));
+ PipePrefix = " | ";
+ }
+ // Shader Kind mask
+ OverloadString.append(", ");
+ auto SKDag = SMConstrRec->getValueAsDag("stage_kinds");
+ PipePrefix = "";
+ for (const Init *Arg : SKDag->getArgs()) {
+ OverloadString.append(PipePrefix)
+ .append(" ShaderKind::")
+ .append(cast<DefInit>(Arg)->getDef()->getName());
+ PipePrefix = " | ";
+ }
+ OverloadString.append("}");
+ Prefix = ", ";
}
+ OverloadString.append("}");
+ return OverloadString;
}
/// Emit Enums of DXIL Ops
@@ -289,6 +332,7 @@ static void emitDXILEnums(std::vector<DXILOperationDesc> &Ops,
return A.OpCode < B.OpCode;
});
+ OS << "#ifdef DXIL_OP_ENUM\n";
OS << "// Enumeration for operations specified by DXIL\n";
OS << "enum class OpCode : unsigned {\n";
@@ -310,6 +354,7 @@ static void emitDXILEnums(std::vector<DXILOperationDesc> &Ops,
OS << C << ",\n";
}
OS << "\n};\n\n";
+ OS << "#endif // DXIL_OP_ENUM\n";
}
/// Emit map of DXIL operation to LLVM or DirectX intrinsic
@@ -317,7 +362,8 @@ static void emitDXILEnums(std::vector<DXILOperationDesc> &Ops,
/// \param Output stream
static void emitDXILIntrinsicMap(std::vector<DXILOperationDesc> &Ops,
raw_ostream &OS) {
- OS << "\n";
+ OS << "\n#ifdef DXIL_OP_INTRINSIC_MAP\n";
+
// FIXME: use array instead of SmallDenseMap.
OS << "static const SmallDenseMap<Intrinsic::ID, dxil::OpCode> LowerMap = "
"{\n";
@@ -328,8 +374,8 @@ static void emitDXILIntrinsicMap(std::vector<DXILOperationDesc> &Ops,
OS << " { Intrinsic::" << Op.Intrinsic << ", dxil::OpCode::" << Op.OpName
<< "},\n";
}
- OS << "};\n";
- OS << "\n";
+ OS << "};\n\n";
+ OS << "#endif // DXIL_OP_INTRINSIC_MAP\n";
}
/// Convert operation attribute string to Attribute enum
@@ -355,6 +401,7 @@ static std::string emitDXILOperationAttr(SmallVector<std::string> Attrs) {
/// \param Output stream
static void emitDXILOperationTable(std::vector<DXILOperationDesc> &Ops,
raw_ostream &OS) {
+ OS << "#ifdef DXIL_OP_OPERATION_TABLE\n";
// Sort by OpCode.
llvm::sort(Ops, [](DXILOperationDesc &A, DXILOperationDesc &B) {
return A.OpCode < B.OpCode;
@@ -388,15 +435,91 @@ static void emitDXILOperationTable(std::vector<DXILOperationDesc> &Ops,
OpClassStrings.layout();
Parameters.layout();
- // Emit the DXIL operation table.
- //{dxil::OpCode::Sin, OpCodeNameIndex, OpCodeClass::unary,
- // OpCodeClassNameIndex,
- // OverloadKind::FLOAT | OverloadKind::HALF, Attribute::AttrKind::ReadNone, 0,
- // 3, ParameterTableOffset},
+ // Emit definitions of various data types used to define DXIL Operation table
+ // entries.
+
+ // Emit enum OverloadKind with valid overload types.
+ const SmallVector<std::string> OverloadKindList = {
+ "VOID", "HALF", "FLOAT", "DOUBLE", "I1", "I8",
+ "I16", "I32", "I64", "UserDefinedType", "ObjectType"};
+ // Choose the type of enum OverloadKind based on the number of valid types in
+ // OverloadKindList. This gives the flexibility to just add new supported
+ // types to the list above, if needed, with no need to change this backend
+ // code.
+ unsigned TypeSz = PowerOf2Ceil(OverloadKindList.size());
+ OS << "enum OverloadKind : uint" << TypeSz << "_t {\n";
+ int shiftVal = 1;
+ for (auto TyStr : OverloadKindList) {
+ OS << " " << TyStr << " = 1 << " << shiftVal++ << ",\n";
+ }
+ OS << " }; \n";
+
+ // Emit a convenience struct Version to encode Shader Model version specified
+ // in constraints
+ OS << "struct Version { \n \
+ unsigned Major = 0; \n \
+ unsigned Minor = 0; \n \
+ };\n\n";
+
+ // Emit struct SMConstraints that encapsulates overload and shader kind
+ // constraints predicated on shader model version, if any.
+ OS << "struct OpSMConstraints { \n \
+ Version ShaderModelVer; \n \
+ uint16_t ValidTys; \n \
+ uint16_t ValidShaderKinds; \n \
+ };\n\n";
+
+ // Emit struct OpCodeProperty record that encapsulates DXIL Op information.
+ OS << "struct OpCodeProperty { \n \
+ dxil::OpCode OpCode; \n \
+ // Offset in DXILOpCodeNameTable. \n \
+ unsigned OpCodeNameOffset; \n \
+ dxil::OpCodeClass OpCodeClass; \n \
+ // Offset in DXILOpCodeClassNameTable. \n \
+ unsigned OpCodeClassNameOffset; \n \
+ std::vector<OpSMConstraints> SMConstraints; \n \
+ llvm::Attribute::AttrKind FuncAttr; \n \
+ int OverloadParamIndex; // parameter index which control the overload. \n \
+ // When < 0, should be only 1 overload type. \n \
+ unsigned NumOfParameters; // Number of parameters include return value. \n \
+ unsigned ParameterTableOffset; // Offset in ParameterTable. \n \
+ };\n\n";
+
+ // Emit access function getOverloadTypeName()
+ OS << "static const char *getOverloadTypeName(OverloadKind Kind) { \n \
+ switch (Kind) { \n \
+ case OverloadKind::HALF: \n \
+ return \"f16\"; \n \
+ case OverloadKind::FLOAT: \n \
+ return \"f32\"; \n \
+ case OverloadKind::DOUBLE: \n \
+ return \"f64\"; \n \
+ case OverloadKind::I1: \n \
+ return \"i1\"; \n \
+ case OverloadKind::I8: \n \
+ return \"i8\"; \n \
+ case OverloadKind::I16: \n \
+ return \"i16\"; \n \
+ case OverloadKind::I32: \n \
+ return \"i32\"; \n \
+ case OverloadKind::I64: \n \
+ return \"i64\"; \n \
+ case OverloadKind::VOID: \n \
+ case OverloadKind::ObjectType: \n \
+ case OverloadKind::UserDefinedType: \n \
+ break; \n \
+ } \n \
+ llvm_unreachable(\"invalid overload type for name\"); \n \
+ return \"void\"; \n \
+ }\n\n";
+
+ // Emit access function getOpcodeProperty() that embeds DXIL Operation table
+ // with entries of type struct OpcodeProperty.
OS << "static const OpCodeProperty *getOpCodeProperty(dxil::OpCode Op) "
"{\n";
OS << " static const OpCodeProperty OpCodeProps[] = {\n";
+ std::string Prefix = "";
for (auto &Op : Ops) {
// Consider Op.OverloadParamIndex as the overload parameter index, by
// default
@@ -408,13 +531,14 @@ static void emitDXILOperationTable(std::vector<DXILOperationDesc> &Ops,
if (OLParamIdx < 0) {
OLParamIdx = (Op.OpTypes.size() > 1) ? 1 : 0;
}
- OS << " { dxil::OpCode::" << Op.OpName << ", " << OpStrings.get(Op.OpName)
- << ", OpCodeClass::" << Op.OpClass << ", "
+ OS << Prefix << " { dxil::OpCode::" << Op.OpName << ", "
+ << OpStrings.get(Op.OpName) << ", OpCodeClass::" << Op.OpClass << ", "
<< OpClassStrings.get(Op.OpClass.data()) << ", "
- << getOverloadKindStr(Op.OpTypes[OLParamIdx]) << ", "
+ << getOverloadKindStrsFromConstraint(Op.SMConstraints) << ", "
<< emitDXILOperationAttr(Op.OpAttributes) << ", "
<< Op.OverloadParamIndex << ", " << Op.OpTypes.size() - 1 << ", "
- << Parameters.get(ParameterMap[Op.OpClass]) << " },\n";
+ << Parameters.get(ParameterMap[Op.OpClass]) << " }\n";
+ Prefix = ",";
}
OS << " };\n";
@@ -467,6 +591,49 @@ static void emitDXILOperationTable(std::vector<DXILOperationDesc> &Ops,
OS << " unsigned Index = Prop.ParameterTableOffset;\n";
OS << " return DXILOpParameterKindTable + Index;\n";
OS << "}\n ";
+ OS << "#endif // DXIL_OP_OPERATION_TABLE\n";
+}
+
+static void emitShaderKindEnums(RecordKeeper &Records, raw_ostream &OS) {
+ // Get Shader stage records
+ std::vector<Record *> ShaderKindRecs =
+ Records.getAllDerivedDefinitions("ShaderStage");
+ // Sort records by name
+ llvm::sort(ShaderKindRecs,
+ [](Record *A, Record *B) { return A->getName() < B->getName(); });
+
+ OS << "#ifdef SHADER_KIND_ENUM \n";
+ OS << "// Valid shader kinds\n\n";
+ // Choose the type of enum ShaderKind based on the number of stages declared
+ // This gives the flexibility to just add add new stage records in DXIL.td, if
+ // needed, with no need to change this backend code.
+ unsigned TypeSz = PowerOf2Ceil(ShaderKindRecs.size());
+ OS << "enum ShaderKind : uint" << TypeSz << "_t {\n";
+ const std::string allKinds("allKinds");
+ // set unknown kind to 0
+ OS << " Unknown = 0,\n";
+ int shiftVal = 1;
+ for (auto R : ShaderKindRecs) {
+ auto Name = R->getName();
+ if (Name.compare(allKinds)) {
+ OS << " " << Name << " = 1 << " << std::to_string(shiftVal++) << ",\n";
+ }
+ }
+ // allkinds is set to (1 << TypeSz) - 1, with all bits set denoting support
+ // for all stages
+ OS << " " << allKinds << " = 0x" << utohexstr(((1 << TypeSz) - 1), false, 4)
+ << "\n";
+ OS << "}\n\n; // enum ShaderKind\n";
+ // Generate ShaderKind enum getter from string
+ OS << "static ShaderKind getShaderkKindEnum(StringRef StageKindStr) {\n"
+ " return StringSwitch<ShaderKind>(StageKindStr)\n";
+ for (auto R : ShaderKindRecs) {
+ auto Name = R->getName();
+ OS << " .Case(\"" << Name << "\", ShaderKind::" << Name << ")\n";
+ }
+ OS << " .Default(ShaderKind::Unknown);\n";
+ OS << "}\n";
+ OS << "#endif // SHADER_KIND_ENUM \n\n\n";
}
/// Entry function call that invokes the functionality of this TableGen backend
@@ -475,22 +642,17 @@ static void emitDXILOperationTable(std::vector<DXILOperationDesc> &Ops,
static void EmitDXILOperation(RecordKeeper &Records, raw_ostream &OS) {
OS << "// Generated code, do not edit.\n";
OS << "\n";
- // Get all DXIL Ops to intrinsic mapping records
- std::vector<Record *> OpIntrMaps =
- Records.getAllDerivedDefinitions("DXILOpMapping");
+ emitShaderKindEnums(Records, OS);
+ // Get all DXIL Ops property records
+ std::vector<Record *> OpIntrProps =
+ Records.getAllDerivedDefinitions("DXILOp");
std::vector<DXILOperationDesc> DXILOps;
- for (auto *Record : OpIntrMaps) {
+ for (auto *Record : OpIntrProps) {
DXILOps.emplace_back(DXILOperationDesc(Record));
}
- OS << "#ifdef DXIL_OP_ENUM\n";
emitDXILEnums(DXILOps, OS);
- OS << "#endif\n\n";
- OS << "#ifdef DXIL_OP_INTRINSIC_MAP\n";
emitDXILIntrinsicMap(DXILOps, OS);
- OS << "#endif\n\n";
- OS << "#ifdef DXIL_OP_OPERATION_TABLE\n";
emitDXILOperationTable(DXILOps, OS);
- OS << "#endif\n\n";
}
static TableGen::Emitter::Opt X("gen-dxil-operation", EmitDXILOperation,
More information about the llvm-commits
mailing list