[llvm] [DXIL] Add DXIL version-specific TableGen specification and implementation of DXIL Ops (PR #97593)

S. Bharadwaj Yadavalli via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 26 13:51:32 PDT 2024


https://github.com/bharadwajy updated https://github.com/llvm/llvm-project/pull/97593

>From ef071d28288cf31b2a5cf82b2098f8e43c9c95ca 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 01/12] 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,

>From 749c06914bd4be4860069651a3e698fa07be98de Mon Sep 17 00:00:00 2001
From: Bharadwaj Yadavalli <Bharadwaj.Yadavalli at microsoft.com>
Date: Fri, 5 Jul 2024 17:02:44 +0000
Subject: [PATCH 02/12] Simplify getting shader version and shader stage kind
 information from DXIL Module.

Add new tests to ensure shader stage validation checks are triggered
when DXIL Operations are created.

Clean up unused class field in DXIL.td.
---
 llvm/lib/Target/DirectX/DXIL.td               | 42 ---------------
 llvm/lib/Target/DirectX/DXILOpBuilder.cpp     | 26 +++++++---
 llvm/lib/Target/DirectX/DXILOpLowering.cpp    | 52 +++++++------------
 llvm/test/CodeGen/DirectX/comput_ids.ll       |  4 +-
 .../flattened_thread_id_in_group_error.ll     | 14 +++++
 llvm/test/CodeGen/DirectX/group_id_error.ll   | 14 +++++
 .../CodeGen/DirectX/sin_no_stage_error.ll     | 13 +++++
 llvm/test/CodeGen/DirectX/thread_id_error.ll  | 14 +++++
 .../DirectX/thread_id_in_group_error.ll       | 14 +++++
 9 files changed, 108 insertions(+), 85 deletions(-)
 create mode 100644 llvm/test/CodeGen/DirectX/flattened_thread_id_in_group_error.ll
 create mode 100644 llvm/test/CodeGen/DirectX/group_id_error.ll
 create mode 100644 llvm/test/CodeGen/DirectX/sin_no_stage_error.ll
 create mode 100644 llvm/test/CodeGen/DirectX/thread_id_error.ll
 create mode 100644 llvm/test/CodeGen/DirectX/thread_id_in_group_error.ll

diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td
index c78bd9ae81661..efdcedce50d43 100644
--- a/llvm/lib/Target/DirectX/DXIL.td
+++ b/llvm/lib/Target/DirectX/DXIL.td
@@ -308,11 +308,6 @@ class DXILOp {
   // 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);
 
@@ -342,7 +337,6 @@ def IsInf : DXILOp {
   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,
@@ -355,7 +349,6 @@ def Abs : DXILOp {
   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,
@@ -368,7 +361,6 @@ def Cos  : DXILOp {
   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,
@@ -381,7 +373,6 @@ def Sin  : DXILOp {
   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,
@@ -396,7 +387,6 @@ def Tan  : DXILOp {
   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,
@@ -409,7 +399,6 @@ def ACos  : DXILOp {
   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,
@@ -422,7 +411,6 @@ def ASin  : DXILOp {
   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,
@@ -435,7 +423,6 @@ def ATan  : DXILOp {
   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,
@@ -448,7 +435,6 @@ def HCos  : DXILOp {
   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,
@@ -461,7 +447,6 @@ def HSin  : DXILOp {
   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,
@@ -474,7 +459,6 @@ def HTan  : DXILOp {
   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,
@@ -487,7 +471,6 @@ def Exp2 : DXILOp {
   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,
@@ -500,7 +483,6 @@ def Frac : DXILOp {
   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,
@@ -513,7 +495,6 @@ def Log2 : DXILOp {
   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,
@@ -526,7 +507,6 @@ def Sqrt : DXILOp {
   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,
@@ -539,7 +519,6 @@ def RSqrt : DXILOp {
   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,
@@ -552,7 +531,6 @@ def Round : DXILOp {
   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,
@@ -565,7 +543,6 @@ def Floor : DXILOp {
   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,
@@ -578,7 +555,6 @@ def Ceil  : DXILOp {
   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,
@@ -591,7 +567,6 @@ def Trunc : DXILOp {
   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,
@@ -604,7 +579,6 @@ def Rbits : DXILOp {
   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,
@@ -617,7 +591,6 @@ def FMax : DXILOp {
   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,
@@ -630,7 +603,6 @@ def FMin : DXILOp {
   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,
@@ -643,7 +615,6 @@ def SMax : DXILOp {
   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,
@@ -656,7 +627,6 @@ def SMin : DXILOp {
   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,
@@ -669,7 +639,6 @@ def UMax : DXILOp {
   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,
@@ -682,7 +651,6 @@ def UMin : DXILOp {
   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,
@@ -695,7 +663,6 @@ def FMad : DXILOp {
   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,
@@ -707,7 +674,6 @@ 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);
@@ -720,7 +686,6 @@ 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);
@@ -734,7 +699,6 @@ def Dot2 : DXILOp {
   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,
@@ -747,7 +711,6 @@ def Dot3 : DXILOp {
   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,
@@ -760,7 +723,6 @@ def Dot4 : DXILOp {
   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,
@@ -773,7 +735,6 @@ def ThreadId : DXILOp {
   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),
@@ -785,7 +746,6 @@ def GroupId  : DXILOp {
   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),
@@ -797,7 +757,6 @@ def ThreadIdInGroup : DXILOp {
   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),
@@ -809,7 +768,6 @@ def FlattenedThreadIdInGroup : DXILOp {
   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),
diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
index f90eb21122eba..3e45ade64ba85 100644
--- a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
@@ -197,7 +197,7 @@ static int getValidConstraintIndex(const OpCodeProperty *Prop,
   // 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--) {
+  for (int I = Size - 1; I >= 0; I--) {
     auto OL = Prop->SMConstraints[I];
     if (VersionTuple(OL.ShaderModelVer.Major, OL.ShaderModelVer.Minor) <=
         SMVer) {
@@ -205,7 +205,7 @@ static int getValidConstraintIndex(const OpCodeProperty *Prop,
     }
   }
   report_fatal_error(
-      StringRef(SMVer.getAsString().append(": Unhandled Shader Model Version")),
+      StringRef(SMVer.getAsString().append(": Unknown Shader Model Version")),
       /*gen_crash_diag*/ false);
 
   return -1;
@@ -229,21 +229,33 @@ CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode,
   }
 
   // Ensure Opcode is valid in the targetted shader kind
-
   uint16_t ValidShaderKindMask = Prop->SMConstraints[Index].ValidShaderKinds;
+  ShaderKind ModuleStagekind = getShaderkKindEnum(StageKind);
 
+  // Ensure valid shader stage constraints are specified
   if (ValidShaderKindMask == ShaderKind::Unknown) {
     report_fatal_error(
-        StringRef(SMVer.getAsString().append(": Unhandled Shader Kind")),
+        StringRef(SMVer.getAsString().append(": Unhandled Target Shader Stage")),
         /*gen_crash_diag*/ false);
   }
 
-  if (!(ValidShaderKindMask | getShaderkKindEnum(StageKind))) {
-    report_fatal_error(StringRef(std::string(StageKind).append(
-                           " : Invalid stage for operation")),
+  // Validate the shader stage specified in target triple to be known
+  if (ModuleStagekind == ShaderKind::Unknown) {
+    report_fatal_error(StringRef(SMVer.getAsString().append(
+                           ": DXIL Module created with Unspecifed or Unknown "
+                           "Target Shader Stage")),
                        /*gen_crash_diag*/ false);
   }
 
+  // Verify the target shader stage is valid for the DXIL operation
+  if (!(ValidShaderKindMask & ModuleStagekind)) {
+    report_fatal_error(
+        StringRef(std::string(StageKind)
+                      .append(" : Invalid Shader Stage for DXIL operation - ")
+                      .append(getOpCodeName((OpCode)))),
+        /*gen_crash_diag*/ false);
+  }
+
   std::string DXILFnName = constructOverloadName(Kind, OverloadTy, *Prop);
   FunctionCallee DXILFn;
   // Get the function with name DXILFnName, if one exists
diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
index eb55a661279c2..e69c17a43608e 100644
--- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
@@ -25,8 +25,7 @@
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/Pass.h"
 #include "llvm/Support/ErrorHandling.h"
-
-#include "iostream"
+#include <string>
 
 #define DEBUG_TYPE "dxil-op-lower"
 
@@ -75,38 +74,10 @@ 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) {
+static void lowerIntrinsic(dxil::OpCode DXILOp, Function &F, Module &M,
+                           VersionTuple SMVer, StringRef StageKind) {
   IRBuilder<> B(M.getContext());
   DXILOpBuilder DXILB(M, B);
-  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);
@@ -124,7 +95,7 @@ static void lowerIntrinsic(dxil::OpCode DXILOp, Function &F, Module &M) {
       Args.append(CI->arg_begin(), CI->arg_end());
 
     CallInst *DXILCI = DXILB.createDXILOpCall(
-        DXILOp, SMVer, Stagekind, F.getReturnType(), OverloadTy, Args);
+        DXILOp, SMVer, StageKind, F.getReturnType(), OverloadTy, Args);
 
     CI->replaceAllUsesWith(DXILCI);
     CI->eraseFromParent();
@@ -140,6 +111,19 @@ static bool lowerIntrinsics(Module &M) {
 #include "DXILOperation.inc"
 #undef DXIL_OP_INTRINSIC_MAP
 
+  // Get Shader Model version
+  std::string TTStr = M.getTargetTriple();
+  // No extra checks need be performed to verify that the Triple is
+  // well-formed or 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.
+  auto Major = Triple(TTStr).getOSVersion().getMajor();
+  auto MinorOrErr = Triple(TTStr).getOSVersion().getMinor();
+  uint32_t Minor = MinorOrErr.has_value() ? *MinorOrErr : 0;
+  VersionTuple SMVer(Major, Minor);
+  // Get Shader Kind
+  std::string StageKind = Triple(TTStr).getEnvironmentName().str();
+
   for (Function &F : make_early_inc_range(M.functions())) {
     if (!F.isDeclaration())
       continue;
@@ -149,7 +133,7 @@ static bool lowerIntrinsics(Module &M) {
     auto LowerIt = LowerMap.find(ID);
     if (LowerIt == LowerMap.end())
       continue;
-    lowerIntrinsic(LowerIt->second, F, M);
+    lowerIntrinsic(LowerIt->second, F, M, SMVer, StageKind);
     Updated = true;
   }
   return Updated;
diff --git a/llvm/test/CodeGen/DirectX/comput_ids.ll b/llvm/test/CodeGen/DirectX/comput_ids.ll
index 553994094d71e..976b3ea5c6ecd 100644
--- a/llvm/test/CodeGen/DirectX/comput_ids.ll
+++ b/llvm/test/CodeGen/DirectX/comput_ids.ll
@@ -1,9 +1,9 @@
-; RUN: opt -S -dxil-op-lower < %s | FileCheck %s
+; RUN: opt -S -dxil-op-lower  %s | FileCheck %s
 
 ; Make sure dxil operation function calls for all ComputeID dxil operations are generated.
 
 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.7-library"
+target triple = "dxil-pc-shadermodel6.7-compute"
 
 ; CHECK-LABEL: @test_thread_id(
 ; Function Attrs: noinline nounwind optnone
diff --git a/llvm/test/CodeGen/DirectX/flattened_thread_id_in_group_error.ll b/llvm/test/CodeGen/DirectX/flattened_thread_id_in_group_error.ll
new file mode 100644
index 0000000000000..05351563e7f8e
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/flattened_thread_id_in_group_error.ll
@@ -0,0 +1,14 @@
+; RUN: not opt -S -dxil-op-lower  %s 2>&1 | FileCheck %s
+
+; DXIL operation sin is not valid in library stage
+; CHECK: LLVM ERROR: library : Invalid Shader Stage for DXIL operation - FlattenedThreadIdInGroup
+
+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.7-library"
+
+; Function Attrs: noinline nounwind optnone
+define i32 @test_flattened_thread_id_in_group() #0 {
+entry:
+  %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
+  ret i32 %0
+}
diff --git a/llvm/test/CodeGen/DirectX/group_id_error.ll b/llvm/test/CodeGen/DirectX/group_id_error.ll
new file mode 100644
index 0000000000000..0bf62a785dbf7
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/group_id_error.ll
@@ -0,0 +1,14 @@
+; RUN: not opt -S -dxil-op-lower  %s 2>&1 | FileCheck %s
+
+; DXIL operation not valid for pixel stage
+; CHECK: LLVM ERROR: pixel : Invalid Shader Stage for DXIL operation - GroupId
+
+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.7-pixel"
+
+; Function Attrs: noinline nounwind optnone
+define i32 @test_group_id(i32 %a) #0 {
+entry:
+  %0 = call i32 @llvm.dx.group.id(i32 %a)
+  ret i32 %0
+}
diff --git a/llvm/test/CodeGen/DirectX/sin_no_stage_error.ll b/llvm/test/CodeGen/DirectX/sin_no_stage_error.ll
new file mode 100644
index 0000000000000..52c595571320a
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/sin_no_stage_error.ll
@@ -0,0 +1,13 @@
+; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.0 %s 2>&1 | FileCheck %s
+
+; Shader Stage is required to ensure the operation is supported.
+; CHECK: LLVM ERROR: 6.0: DXIL Module created with Unspecifed or Unknown Target Shader Stage
+
+define noundef float @sin_float(float noundef %a) #0 {
+entry:
+  %a.addr = alloca float, align 4
+  store float %a, ptr %a.addr, align 4
+  %0 = load float, ptr %a.addr, align 4
+  %1 = call float @llvm.sin.f32(float %0)
+  ret float %1
+}
diff --git a/llvm/test/CodeGen/DirectX/thread_id_error.ll b/llvm/test/CodeGen/DirectX/thread_id_error.ll
new file mode 100644
index 0000000000000..168ec01a75580
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/thread_id_error.ll
@@ -0,0 +1,14 @@
+; RUN: not opt -S -dxil-op-lower  %s 2>&1 | FileCheck %s
+
+; DXIL operation not valid for library stage
+; CHECK: LLVM ERROR: library : Invalid Shader Stage for DXIL operation - ThreadId
+
+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.7-library"
+
+; Function Attrs: noinline nounwind optnone
+define i32 @test_thread_id(i32 %a) #0 {
+entry:
+  %0 = call i32 @llvm.dx.thread.id(i32 %a)
+  ret i32 %0
+}
diff --git a/llvm/test/CodeGen/DirectX/thread_id_in_group_error.ll b/llvm/test/CodeGen/DirectX/thread_id_in_group_error.ll
new file mode 100644
index 0000000000000..ced91a24aee60
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/thread_id_in_group_error.ll
@@ -0,0 +1,14 @@
+; RUN: not opt -S -dxil-op-lower  %s 2>&1 | FileCheck %s
+
+; DXIL operation sin is not valid in vertex stage
+; CHECK: LLVM ERROR: vertex : Invalid Shader Stage for DXIL operation - ThreadIdInGroup
+
+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.7-vertex"
+
+; Function Attrs: noinline nounwind optnone
+define i32 @test_thread_id_in_group(i32 %a) #0 {
+entry:
+  %0 = call i32 @llvm.dx.thread.id.in.group(i32 %a)
+  ret i32 %0
+}

>From bc96291646e7001534f4d4ff0af0f05e72f68554 Mon Sep 17 00:00:00 2001
From: Bharadwaj Yadavalli <Bharadwaj.Yadavalli at microsoft.com>
Date: Mon, 8 Jul 2024 15:50:12 +0000
Subject: [PATCH 03/12] Provide additional information in error messages

---
 llvm/lib/Target/DirectX/DXILOpBuilder.cpp | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
index 3e45ade64ba85..5fa0ac19b1935 100644
--- a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
@@ -225,17 +225,24 @@ CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode,
 
   OverloadKind Kind = getOverloadKind(OverloadTy);
   if ((ValidTyMask & (uint16_t)Kind) == 0) {
-    report_fatal_error("Invalid Overload Type", /* gen_crash_diag=*/false);
+    report_fatal_error(
+        StringRef(std::string("Invalid Overload Type for DXIL operation - ")
+                      .append(getOpCodeName((OpCode)))),
+        /* gen_crash_diag=*/false);
   }
 
-  // Ensure Opcode is valid in the targetted shader kind
+  // Perform necessary checks to ensure Opcode is valid in the targeted shader
+  // kind
   uint16_t ValidShaderKindMask = Prop->SMConstraints[Index].ValidShaderKinds;
   ShaderKind ModuleStagekind = getShaderkKindEnum(StageKind);
 
   // Ensure valid shader stage constraints are specified
   if (ValidShaderKindMask == ShaderKind::Unknown) {
     report_fatal_error(
-        StringRef(SMVer.getAsString().append(": Unhandled Target Shader Stage")),
+        StringRef(
+            SMVer.getAsString()
+                .append(": Unknown Target Shader Stage for DXIL operation - ")
+                .append(getOpCodeName((OpCode)))),
         /*gen_crash_diag*/ false);
   }
 
@@ -252,7 +259,9 @@ CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode,
     report_fatal_error(
         StringRef(std::string(StageKind)
                       .append(" : Invalid Shader Stage for DXIL operation - ")
-                      .append(getOpCodeName((OpCode)))),
+                      .append(getOpCodeName(OpCode))
+                      .append(" for Shader Model ")
+                      .append(SMVer.getAsString())),
         /*gen_crash_diag*/ false);
   }
 

>From e8bb0c64866f12a15b81488c4422282eccf8cee9 Mon Sep 17 00:00:00 2001
From: Bharadwaj Yadavalli <Bharadwaj.Yadavalli at microsoft.com>
Date: Mon, 8 Jul 2024 16:43:57 +0000
Subject: [PATCH 04/12] Delete unused resourceVT and dxil_resource_ty

---
 llvm/lib/Target/DirectX/DXIL.td | 101 ++++++++++++++++++++++++++------
 1 file changed, 84 insertions(+), 17 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td
index efdcedce50d43..f643cf0720c8e 100644
--- a/llvm/lib/Target/DirectX/DXIL.td
+++ b/llvm/lib/Target/DirectX/DXIL.td
@@ -27,11 +27,6 @@ foreach i = 0...8 in {
   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;
 
@@ -332,18 +327,6 @@ class DXILOp {
 
 // 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 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;
@@ -354,6 +337,22 @@ def Abs : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty, llvm_double_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
+}
+
+def IsInf : DXILOp {
+  let Doc = "Determines if the specified value is infinite.";
+  let OpCode = 9;
+  let OpClass = isSpecialFloat;
+  let LLVMIntrinsic = int_dx_isinf;
+  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)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def Cos  : DXILOp {
@@ -366,6 +365,8 @@ def Cos  : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def Sin  : DXILOp {
@@ -392,6 +393,8 @@ def Tan  : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def ACos  : DXILOp {
@@ -404,6 +407,8 @@ def ACos  : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def ASin  : DXILOp {
@@ -416,6 +421,8 @@ def ASin  : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def ATan  : DXILOp {
@@ -428,6 +435,8 @@ def ATan  : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def HCos  : DXILOp {
@@ -440,6 +449,8 @@ def HCos  : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def HSin  : DXILOp {
@@ -452,6 +463,8 @@ def HSin  : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def HTan  : DXILOp {
@@ -464,6 +477,8 @@ def HTan  : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def Exp2 : DXILOp {
@@ -476,6 +491,8 @@ def Exp2 : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def Frac : DXILOp {
@@ -488,6 +505,8 @@ def Frac : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def Log2 : DXILOp {
@@ -500,6 +519,8 @@ def Log2 : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def Sqrt : DXILOp {
@@ -512,6 +533,8 @@ def Sqrt : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def RSqrt : DXILOp {
@@ -524,6 +547,8 @@ def RSqrt : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def Round : DXILOp {
@@ -536,6 +561,8 @@ def Round : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def Floor : DXILOp {
@@ -548,6 +575,8 @@ def Floor : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def Ceil  : DXILOp {
@@ -560,6 +589,8 @@ def Ceil  : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def Trunc : DXILOp {
@@ -572,6 +603,8 @@ def Trunc : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def Rbits : DXILOp {
@@ -584,6 +617,8 @@ def Rbits : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_i16_ty, llvm_i32_ty, llvm_i64_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def FMax : DXILOp {
@@ -596,6 +631,8 @@ def FMax : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty, llvm_double_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def FMin : DXILOp {
@@ -608,6 +645,8 @@ def FMin : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty, llvm_double_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def SMax : DXILOp {
@@ -620,6 +659,8 @@ def SMax : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_i16_ty, llvm_i32_ty, llvm_i64_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def SMin : DXILOp {
@@ -632,6 +673,8 @@ def SMin : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_i16_ty, llvm_i32_ty, llvm_i64_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def UMax : DXILOp {
@@ -644,6 +687,8 @@ def UMax : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_i16_ty, llvm_i32_ty, llvm_i64_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def UMin : DXILOp {
@@ -656,6 +701,8 @@ def UMin : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_i16_ty, llvm_i32_ty, llvm_i64_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def FMad : DXILOp {
@@ -668,6 +715,8 @@ def FMad : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty, llvm_double_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def IMad : DXILOp {
@@ -680,6 +729,8 @@ def IMad : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_i16_ty, llvm_i32_ty, llvm_i64_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def UMad : DXILOp {
@@ -692,6 +743,8 @@ def UMad : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_i16_ty, llvm_i32_ty, llvm_i64_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def Dot2 : DXILOp {
@@ -704,6 +757,8 @@ def Dot2 : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def Dot3 : DXILOp {
@@ -716,6 +771,8 @@ def Dot3 : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def Dot4 : DXILOp {
@@ -728,6 +785,8 @@ def Dot4 : DXILOp {
   let sm_constraints = [SMVersionConstraints<SM6_0,
                              (overloads llvm_half_ty, llvm_float_ty),
                              (stages allKinds)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def ThreadId : DXILOp {
@@ -739,6 +798,8 @@ def ThreadId : DXILOp {
   let result = (out llvm_i32_ty);
   let sm_constraints = [SMVersionConstraints<SM6_0, (overloads llvm_i32_ty),
                              (stages compute, mesh, amplification, node)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def GroupId  : DXILOp {
@@ -750,6 +811,8 @@ def GroupId  : DXILOp {
   let result = (out llvm_i32_ty);
   let sm_constraints = [SMVersionConstraints<SM6_0, (overloads llvm_i32_ty),
                              (stages compute, mesh, amplification, node)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def ThreadIdInGroup : DXILOp {
@@ -761,6 +824,8 @@ def ThreadIdInGroup : DXILOp {
   let result = (out llvm_i32_ty);
   let sm_constraints = [SMVersionConstraints<SM6_0, (overloads llvm_i32_ty),
                              (stages compute, mesh, amplification, node)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }
 
 def FlattenedThreadIdInGroup : DXILOp {
@@ -772,4 +837,6 @@ def FlattenedThreadIdInGroup : DXILOp {
   let result = (out);
   let sm_constraints = [SMVersionConstraints<SM6_0, (overloads llvm_i32_ty),
                              (stages compute, mesh, amplification, node)>];
+  let attributes = (attrs ReadNone);
+  let DXILVersion = DX1_0;
 }

>From 5d2d02d031baac2198ae6992763ada7fc0b43e83 Mon Sep 17 00:00:00 2001
From: Bharadwaj Yadavalli <Bharadwaj.Yadavalli at microsoft.com>
Date: Mon, 8 Jul 2024 20:54:19 +0000
Subject: [PATCH 05/12] Add convenience TableGen class DXILOpAndClass<>
 Accomdate for non-specification of LLVMIntrinsic field

Replace use of dag with list in specifications throughout
DXIL.td

Rename getOverloadTy() to getOverloadType()

Delete all defsets from DXIL.td as they are not used
Delete datalayout attribute from newly added tests
Delete pseudo shader stage kind allKinds from DXIL.td
---
 llvm/lib/Target/DirectX/DXIL.td               | 1145 ++++++++---------
 llvm/lib/Target/DirectX/DXILOpBuilder.cpp     |   54 +-
 llvm/lib/Target/DirectX/DXILOpBuilder.h       |    4 +-
 llvm/lib/Target/DirectX/DXILOpLowering.cpp    |    2 +-
 .../flattened_thread_id_in_group_error.ll     |    1 -
 llvm/test/CodeGen/DirectX/group_id_error.ll   |    1 -
 llvm/test/CodeGen/DirectX/thread_id_error.ll  |    1 -
 .../DirectX/thread_id_in_group_error.ll       |    1 -
 llvm/utils/TableGen/DXILEmitter.cpp           |  184 ++-
 9 files changed, 674 insertions(+), 719 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td
index f643cf0720c8e..3d25b4e8cb60c 100644
--- a/llvm/lib/Target/DirectX/DXIL.td
+++ b/llvm/lib/Target/DirectX/DXIL.td
@@ -23,268 +23,260 @@ class Version<int major, int minor> {
 
 // 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>;
+  def SM6_ #i : Version<6, i>;
+  def DX1_ #i : Version<1, i>;
 }
 
 // Overload type alias of llvm_any_ty
-defvar dxil_overload_ty  = llvm_any_ty;
-
-// 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;
-}
+defvar dxil_overload_ty = llvm_any_ty;
 
 class DXILOpClass;
 
 // Concrete definitions of DXIL Op Classes
-defset list<DXILOpClass> OpClasses = {
-  def acceptHitAndEndSearch : DXILOpClass;
-  def allocateNodeOutputRecords : DXILOpClass;
-  def allocateRayQuery : DXILOpClass;
-  def annotateHandle : DXILOpClass;
-  def annotateNodeHandle : DXILOpClass;
-  def annotateNodeRecordHandle : DXILOpClass;
-  def atomicBinOp : DXILOpClass;
-  def atomicCompareExchange : DXILOpClass;
-  def attributeAtVertex : DXILOpClass;
-  def barrier : DXILOpClass;
-  def barrierByMemoryHandle : DXILOpClass;
-  def barrierByMemoryType : DXILOpClass;
-  def barrierByNodeRecordHandle : DXILOpClass;
-  def binary : DXILOpClass;
-  def binaryWithCarryOrBorrow : DXILOpClass;
-  def binaryWithTwoOuts : DXILOpClass;
-  def bitcastF16toI16 : DXILOpClass;
-  def bitcastF32toI32 : DXILOpClass;
-  def bitcastF64toI64 : DXILOpClass;
-  def bitcastI16toF16 : DXILOpClass;
-  def bitcastI32toF32 : DXILOpClass;
-  def bitcastI64toF64 : DXILOpClass;
-  def bufferLoad : DXILOpClass;
-  def bufferStore : DXILOpClass;
-  def bufferUpdateCounter : DXILOpClass;
-  def calculateLOD : DXILOpClass;
-  def callShader : DXILOpClass;
-  def cbufferLoad : DXILOpClass;
-  def cbufferLoadLegacy : DXILOpClass;
-  def checkAccessFullyMapped : DXILOpClass;
-  def coverage : DXILOpClass;
-  def createHandle : DXILOpClass;
-  def createHandleForLib : DXILOpClass;
-  def createHandleFromBinding : DXILOpClass;
-  def createHandleFromHeap : DXILOpClass;
-  def createNodeInputRecordHandle : DXILOpClass;
-  def createNodeOutputHandle : DXILOpClass;
-  def cutStream : DXILOpClass;
-  def cycleCounterLegacy : DXILOpClass;
-  def discard : DXILOpClass;
-  def dispatchMesh : DXILOpClass;
-  def dispatchRaysDimensions : DXILOpClass;
-  def dispatchRaysIndex : DXILOpClass;
-  def domainLocation : DXILOpClass;
-  def dot2 : DXILOpClass;
-  def dot2AddHalf : DXILOpClass;
-  def dot3 : DXILOpClass;
-  def dot4 : DXILOpClass;
-  def dot4AddPacked : DXILOpClass;
-  def emitIndices : DXILOpClass;
-  def emitStream : DXILOpClass;
-  def emitThenCutStream : DXILOpClass;
-  def evalCentroid : DXILOpClass;
-  def evalSampleIndex : DXILOpClass;
-  def evalSnapped : DXILOpClass;
-  def finishedCrossGroupSharing : DXILOpClass;
-  def flattenedThreadIdInGroup : DXILOpClass;
-  def geometryIndex : DXILOpClass;
-  def getDimensions : DXILOpClass;
-  def getInputRecordCount : DXILOpClass;
-  def getMeshPayload : DXILOpClass;
-  def getNodeRecordPtr : DXILOpClass;
-  def getRemainingRecursionLevels : DXILOpClass;
-  def groupId : DXILOpClass;
-  def gsInstanceID : DXILOpClass;
-  def hitKind : DXILOpClass;
-  def ignoreHit : DXILOpClass;
-  def incrementOutputCount : DXILOpClass;
-  def indexNodeHandle : DXILOpClass;
-  def innerCoverage : DXILOpClass;
-  def instanceID : DXILOpClass;
-  def instanceIndex : DXILOpClass;
-  def isHelperLane : DXILOpClass;
-  def isSpecialFloat : DXILOpClass;
-  def legacyDoubleToFloat : DXILOpClass;
-  def legacyDoubleToSInt32 : DXILOpClass;
-  def legacyDoubleToUInt32 : DXILOpClass;
-  def legacyF16ToF32 : DXILOpClass;
-  def legacyF32ToF16 : DXILOpClass;
-  def loadInput : DXILOpClass;
-  def loadOutputControlPoint : DXILOpClass;
-  def loadPatchConstant : DXILOpClass;
-  def makeDouble : DXILOpClass;
-  def minPrecXRegLoad : DXILOpClass;
-  def minPrecXRegStore : DXILOpClass;
-  def nodeOutputIsValid : DXILOpClass;
-  def objectRayDirection : DXILOpClass;
-  def objectRayOrigin : DXILOpClass;
-  def objectToWorld : DXILOpClass;
-  def outputComplete : DXILOpClass;
-  def outputControlPointID : DXILOpClass;
-  def pack4x8 : DXILOpClass;
-  def primitiveID : DXILOpClass;
-  def primitiveIndex : DXILOpClass;
-  def quadOp : DXILOpClass;
-  def quadReadLaneAt : DXILOpClass;
-  def quadVote : DXILOpClass;
-  def quaternary : DXILOpClass;
-  def rawBufferLoad : DXILOpClass;
-  def rawBufferStore : DXILOpClass;
-  def rayFlags : DXILOpClass;
-  def rayQuery_Abort : DXILOpClass;
-  def rayQuery_CommitNonOpaqueTriangleHit : DXILOpClass;
-  def rayQuery_CommitProceduralPrimitiveHit : DXILOpClass;
-  def rayQuery_Proceed : DXILOpClass;
-  def rayQuery_StateMatrix : DXILOpClass;
-  def rayQuery_StateScalar : DXILOpClass;
-  def rayQuery_StateVector : DXILOpClass;
-  def rayQuery_TraceRayInline : DXILOpClass;
-  def rayTCurrent : DXILOpClass;
-  def rayTMin : DXILOpClass;
-  def renderTargetGetSampleCount : DXILOpClass;
-  def renderTargetGetSamplePosition : DXILOpClass;
-  def reportHit : DXILOpClass;
-  def sample : DXILOpClass;
-  def sampleBias : DXILOpClass;
-  def sampleCmp : DXILOpClass;
-  def sampleCmpBias : DXILOpClass;
-  def sampleCmpGrad : DXILOpClass;
-  def sampleCmpLevel : DXILOpClass;
-  def sampleCmpLevelZero : DXILOpClass;
-  def sampleGrad : DXILOpClass;
-  def sampleIndex : DXILOpClass;
-  def sampleLevel : DXILOpClass;
-  def setMeshOutputCounts : DXILOpClass;
-  def splitDouble : DXILOpClass;
-  def startInstanceLocation : DXILOpClass;
-  def startVertexLocation : DXILOpClass;
-  def storeOutput : DXILOpClass;
-  def storePatchConstant : DXILOpClass;
-  def storePrimitiveOutput : DXILOpClass;
-  def storeVertexOutput : DXILOpClass;
-  def tempRegLoad : DXILOpClass;
-  def tempRegStore : DXILOpClass;
-  def tertiary : DXILOpClass;
-  def texture2DMSGetSamplePosition : DXILOpClass;
-  def textureGather : DXILOpClass;
-  def textureGatherCmp : DXILOpClass;
-  def textureGatherRaw : DXILOpClass;
-  def textureLoad : DXILOpClass;
-  def textureStore : DXILOpClass;
-  def textureStoreSample : DXILOpClass;
-  def threadId : DXILOpClass;
-  def threadIdInGroup : DXILOpClass;
-  def traceRay : DXILOpClass;
-  def unary : DXILOpClass;
-  def unaryBits : DXILOpClass;
-  def unpack4x8 : DXILOpClass;
-  def viewID : DXILOpClass;
-  def waveActiveAllEqual : DXILOpClass;
-  def waveActiveBallot : DXILOpClass;
-  def waveActiveBit : DXILOpClass;
-  def waveActiveOp : DXILOpClass;
-  def waveAllOp : DXILOpClass;
-  def waveAllTrue : DXILOpClass;
-  def waveAnyTrue : DXILOpClass;
-  def waveGetLaneCount : DXILOpClass;
-  def waveGetLaneIndex : DXILOpClass;
-  def waveIsFirstLane : DXILOpClass;
-  def waveMatch : DXILOpClass;
-  def waveMatrix_Accumulate : DXILOpClass;
-  def waveMatrix_Annotate : DXILOpClass;
-  def waveMatrix_Depth : DXILOpClass;
-  def waveMatrix_Fill : DXILOpClass;
-  def waveMatrix_LoadGroupShared : DXILOpClass;
-  def waveMatrix_LoadRawBuf : DXILOpClass;
-  def waveMatrix_Multiply : DXILOpClass;
-  def waveMatrix_ScalarOp : DXILOpClass;
-  def waveMatrix_StoreGroupShared : DXILOpClass;
-  def waveMatrix_StoreRawBuf : DXILOpClass;
-  def waveMultiPrefixBitCount : DXILOpClass;
-  def waveMultiPrefixOp : DXILOpClass;
-  def wavePrefixOp : DXILOpClass;
-  def waveReadLaneAt : DXILOpClass;
-  def waveReadLaneFirst : DXILOpClass;
-  def worldRayDirection : DXILOpClass;
-  def worldRayOrigin : DXILOpClass;
-  def worldToObject : DXILOpClass;
-  def writeSamplerFeedback : DXILOpClass;
-  def writeSamplerFeedbackBias : DXILOpClass;
-  def writeSamplerFeedbackGrad : DXILOpClass;
-  def writeSamplerFeedbackLevel: DXILOpClass;
-
-  // This is a sentinel definition. Hence placed at the end of the list
-  // and not as part of the above alphabetically sorted valid definitions.
-  // Additionally it is capitalized unlike all the others.
-  def UnknownOpClass: DXILOpClass;
-}
+def acceptHitAndEndSearch : DXILOpClass;
+def allocateNodeOutputRecords : DXILOpClass;
+def allocateRayQuery : DXILOpClass;
+def annotateHandle : DXILOpClass;
+def annotateNodeHandle : DXILOpClass;
+def annotateNodeRecordHandle : DXILOpClass;
+def atomicBinOp : DXILOpClass;
+def atomicCompareExchange : DXILOpClass;
+def attributeAtVertex : DXILOpClass;
+def barrier : DXILOpClass;
+def barrierByMemoryHandle : DXILOpClass;
+def barrierByMemoryType : DXILOpClass;
+def barrierByNodeRecordHandle : DXILOpClass;
+def binary : DXILOpClass;
+def binaryWithCarryOrBorrow : DXILOpClass;
+def binaryWithTwoOuts : DXILOpClass;
+def bitcastF16toI16 : DXILOpClass;
+def bitcastF32toI32 : DXILOpClass;
+def bitcastF64toI64 : DXILOpClass;
+def bitcastI16toF16 : DXILOpClass;
+def bitcastI32toF32 : DXILOpClass;
+def bitcastI64toF64 : DXILOpClass;
+def bufferLoad : DXILOpClass;
+def bufferStore : DXILOpClass;
+def bufferUpdateCounter : DXILOpClass;
+def calculateLOD : DXILOpClass;
+def callShader : DXILOpClass;
+def cbufferLoad : DXILOpClass;
+def cbufferLoadLegacy : DXILOpClass;
+def checkAccessFullyMapped : DXILOpClass;
+def coverage : DXILOpClass;
+def createHandle : DXILOpClass;
+def createHandleForLib : DXILOpClass;
+def createHandleFromBinding : DXILOpClass;
+def createHandleFromHeap : DXILOpClass;
+def createNodeInputRecordHandle : DXILOpClass;
+def createNodeOutputHandle : DXILOpClass;
+def cutStream : DXILOpClass;
+def cycleCounterLegacy : DXILOpClass;
+def discard : DXILOpClass;
+def dispatchMesh : DXILOpClass;
+def dispatchRaysDimensions : DXILOpClass;
+def dispatchRaysIndex : DXILOpClass;
+def domainLocation : DXILOpClass;
+def dot2 : DXILOpClass;
+def dot2AddHalf : DXILOpClass;
+def dot3 : DXILOpClass;
+def dot4 : DXILOpClass;
+def dot4AddPacked : DXILOpClass;
+def emitIndices : DXILOpClass;
+def emitStream : DXILOpClass;
+def emitThenCutStream : DXILOpClass;
+def evalCentroid : DXILOpClass;
+def evalSampleIndex : DXILOpClass;
+def evalSnapped : DXILOpClass;
+def finishedCrossGroupSharing : DXILOpClass;
+def flattenedThreadIdInGroup : DXILOpClass;
+def geometryIndex : DXILOpClass;
+def getDimensions : DXILOpClass;
+def getInputRecordCount : DXILOpClass;
+def getMeshPayload : DXILOpClass;
+def getNodeRecordPtr : DXILOpClass;
+def getRemainingRecursionLevels : DXILOpClass;
+def groupId : DXILOpClass;
+def gsInstanceID : DXILOpClass;
+def hitKind : DXILOpClass;
+def ignoreHit : DXILOpClass;
+def incrementOutputCount : DXILOpClass;
+def indexNodeHandle : DXILOpClass;
+def innerCoverage : DXILOpClass;
+def instanceID : DXILOpClass;
+def instanceIndex : DXILOpClass;
+def isHelperLane : DXILOpClass;
+def isSpecialFloat : DXILOpClass;
+def legacyDoubleToFloat : DXILOpClass;
+def legacyDoubleToSInt32 : DXILOpClass;
+def legacyDoubleToUInt32 : DXILOpClass;
+def legacyF16ToF32 : DXILOpClass;
+def legacyF32ToF16 : DXILOpClass;
+def loadInput : DXILOpClass;
+def loadOutputControlPoint : DXILOpClass;
+def loadPatchConstant : DXILOpClass;
+def makeDouble : DXILOpClass;
+def minPrecXRegLoad : DXILOpClass;
+def minPrecXRegStore : DXILOpClass;
+def nodeOutputIsValid : DXILOpClass;
+def objectRayDirection : DXILOpClass;
+def objectRayOrigin : DXILOpClass;
+def objectToWorld : DXILOpClass;
+def outputComplete : DXILOpClass;
+def outputControlPointID : DXILOpClass;
+def pack4x8 : DXILOpClass;
+def primitiveID : DXILOpClass;
+def primitiveIndex : DXILOpClass;
+def quadOp : DXILOpClass;
+def quadReadLaneAt : DXILOpClass;
+def quadVote : DXILOpClass;
+def quaternary : DXILOpClass;
+def rawBufferLoad : DXILOpClass;
+def rawBufferStore : DXILOpClass;
+def rayFlags : DXILOpClass;
+def rayQuery_Abort : DXILOpClass;
+def rayQuery_CommitNonOpaqueTriangleHit : DXILOpClass;
+def rayQuery_CommitProceduralPrimitiveHit : DXILOpClass;
+def rayQuery_Proceed : DXILOpClass;
+def rayQuery_StateMatrix : DXILOpClass;
+def rayQuery_StateScalar : DXILOpClass;
+def rayQuery_StateVector : DXILOpClass;
+def rayQuery_TraceRayInline : DXILOpClass;
+def rayTCurrent : DXILOpClass;
+def rayTMin : DXILOpClass;
+def renderTargetGetSampleCount : DXILOpClass;
+def renderTargetGetSamplePosition : DXILOpClass;
+def reportHit : DXILOpClass;
+def sample : DXILOpClass;
+def sampleBias : DXILOpClass;
+def sampleCmp : DXILOpClass;
+def sampleCmpBias : DXILOpClass;
+def sampleCmpGrad : DXILOpClass;
+def sampleCmpLevel : DXILOpClass;
+def sampleCmpLevelZero : DXILOpClass;
+def sampleGrad : DXILOpClass;
+def sampleIndex : DXILOpClass;
+def sampleLevel : DXILOpClass;
+def setMeshOutputCounts : DXILOpClass;
+def splitDouble : DXILOpClass;
+def startInstanceLocation : DXILOpClass;
+def startVertexLocation : DXILOpClass;
+def storeOutput : DXILOpClass;
+def storePatchConstant : DXILOpClass;
+def storePrimitiveOutput : DXILOpClass;
+def storeVertexOutput : DXILOpClass;
+def tempRegLoad : DXILOpClass;
+def tempRegStore : DXILOpClass;
+def tertiary : DXILOpClass;
+def texture2DMSGetSamplePosition : DXILOpClass;
+def textureGather : DXILOpClass;
+def textureGatherCmp : DXILOpClass;
+def textureGatherRaw : DXILOpClass;
+def textureLoad : DXILOpClass;
+def textureStore : DXILOpClass;
+def textureStoreSample : DXILOpClass;
+def threadId : DXILOpClass;
+def threadIdInGroup : DXILOpClass;
+def traceRay : DXILOpClass;
+def unary : DXILOpClass;
+def unaryBits : DXILOpClass;
+def unpack4x8 : DXILOpClass;
+def viewID : DXILOpClass;
+def waveActiveAllEqual : DXILOpClass;
+def waveActiveBallot : DXILOpClass;
+def waveActiveBit : DXILOpClass;
+def waveActiveOp : DXILOpClass;
+def waveAllOp : DXILOpClass;
+def waveAllTrue : DXILOpClass;
+def waveAnyTrue : DXILOpClass;
+def waveGetLaneCount : DXILOpClass;
+def waveGetLaneIndex : DXILOpClass;
+def waveIsFirstLane : DXILOpClass;
+def waveMatch : DXILOpClass;
+def waveMatrix_Accumulate : DXILOpClass;
+def waveMatrix_Annotate : DXILOpClass;
+def waveMatrix_Depth : DXILOpClass;
+def waveMatrix_Fill : DXILOpClass;
+def waveMatrix_LoadGroupShared : DXILOpClass;
+def waveMatrix_LoadRawBuf : DXILOpClass;
+def waveMatrix_Multiply : DXILOpClass;
+def waveMatrix_ScalarOp : DXILOpClass;
+def waveMatrix_StoreGroupShared : DXILOpClass;
+def waveMatrix_StoreRawBuf : DXILOpClass;
+def waveMultiPrefixBitCount : DXILOpClass;
+def waveMultiPrefixOp : DXILOpClass;
+def wavePrefixOp : DXILOpClass;
+def waveReadLaneAt : DXILOpClass;
+def waveReadLaneFirst : DXILOpClass;
+def worldRayDirection : DXILOpClass;
+def worldRayOrigin : DXILOpClass;
+def worldToObject : DXILOpClass;
+def writeSamplerFeedback : DXILOpClass;
+def writeSamplerFeedbackBias : DXILOpClass;
+def writeSamplerFeedbackGrad : DXILOpClass;
+def writeSamplerFeedbackLevel : DXILOpClass;
+
+// This is a sentinel definition. Hence placed at the end here
+// and not as part of the above alphabetically sorted valid definitions.
+// It is never used to construct the name of DXIL Op call name.
+// Additionally it is capitalized unlike all the others.
+def UnknownOpClass : DXILOpClass;
 
 // 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;
-}
+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;
 
 // Primitive predicate
 class Pred;
 
-// Shader Model version predicate. This translates to
-// a check for specified shader model version
+// Following classes represent predicate that evaluate to the payload,
+// if one xists, unconditionally.
+
+// DXIL Op attributes defined as true predicates, if specified
+
+def ReadOnly : Pred;
+def ReadNone : Pred;
+def IsDerivative : Pred;
+def IsGradient : Pred;
+def IsFeedback : Pred;
+def IsWave : Pred;
+def NeedsUniformInputs : Pred;
+def IsBarrier : Pred;
+
+// Predicate that evaluates to specified shader model version unconditionally.
 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;
+// Predicate that evaluates to specified overload type list unconditionally.
+class Overloads<list<LLVMType> tys> : Pred {
+  list<LLVMType> overload_types = tys;
 }
 
-// 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;
+// Predicate that evaluates to specified list of shader stages unconditionally.
+class Stages<list<ShaderStage> st> : Pred {
+  list<ShaderStage> stage_kinds = st;
+}
 
-// Marker used to identify overload types list.
-def overloads;
+// Following class represents predicate that evaluates to the payload when
+// specified predicte is true.
 
-// Marker used to identify stage kinds list.
-def stages;
+class Constraints<Pred p, list<Pred> l = []> : Pred {
+  Pred pred = p;
+  list<Pred> constraints = l;
+}
 
 // Marker used to identify attribute list.
 def attrs;
@@ -301,542 +293,493 @@ class DXILOp {
   DXILOpClass OpClass = UnknownOpClass;
 
   // LLVM Intrinsic DXIL Operation maps to
-  Intrinsic LLVMIntrinsic = ?;
+  Intrinsic LLVMIntrinsic = ? ;
 
-  // Dag containing the arguments of the op. Default to 0 arguments.
-  dag arguments = (ins);
+  // List of argument types of the op. Default to 0 arguments.
+  list<LLVMType> arguments = [];
 
-  // Results of the op. Default to 0 results.
-  dag result = (out);
+  // List of result types of the op. Default to 0 results.
+  list<LLVMType> result = [];
 
-  // 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 of constraints predicated on Shader Model version.
+  // If no contraints are specified,
+  // a) operation is assumed to be supported in Shader Model 6.0 and later.
+  // b) has no overload types
+  // c) is supported in all shader stage kinds
+  // If a constraint is specified, Shader Model version on which the
+  // constraint is predicated is mandatory. One or both of the Overload
+  // type and shader kind constraints can be omitted when appropriate.
+
+  list<Constraints> constraints = [];
+
+  // Operation attributes
+  list<Pred> attributes = [];
+
+  Version DXILVersion = ? ;
+}
 
-  list<SMVersionConstraints> sm_constraints;
+// Convenience class for minimal DXIL Op definition
 
-  // Non-predicated operation attributes
-  dag attributes = (attrs);
-  Version DXILVersion = ?;
+class DXILOpAndClass<int opcode, DXILOpClass opcalss> : DXILOp {
+  int OpCode = opcode;
+  DXILOpClass OpClass = opcalss;
 }
 
 // Concrete definitions of DXIL Operations
 
-def Abs : DXILOp {
+def Abs : DXILOpAndClass<6, unary> {
   let Doc = "Returns the absolute value of the input.";
-  let OpCode = 6;
-  let OpClass = unary;
   let LLVMIntrinsic = int_fabs;
-  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)>];
-  let attributes = (attrs ReadNone);
+  let arguments = [LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints =
+      [Constraints<SMVersion<SM6_0>,
+                   [Overloads<[llvm_half_ty, llvm_float_ty, llvm_double_ty]>]>];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def IsInf : DXILOp {
+def IsInf : DXILOpAndClass<9, isSpecialFloat> {
   let Doc = "Determines if the specified value is infinite.";
-  let OpCode = 9;
-  let OpClass = isSpecialFloat;
   let LLVMIntrinsic = int_dx_isinf;
-  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)>];
-  let attributes = (attrs ReadNone);
+  let arguments = [llvm_anyfloat_ty];
+  let result = [llvm_i1_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def Cos  : DXILOp {
-  let Doc ="Returns cosine(theta) for theta in radians.";
-  let OpCode = 12;
-  let OpClass = unary;
+def Cos : DXILOpAndClass<12, unary> {
+  let Doc = "Returns cosine(theta) for theta in radians.";
   let LLVMIntrinsic = int_cos;
-  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 arguments = [LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def Sin  : DXILOp {
-  let Doc ="Returns sine(theta) for theta in radians.";
-  let OpCode = 13;
-  let OpClass = unary;
+def Sin : DXILOpAndClass<13, unary> {
+  let Doc = "Returns sine(theta) for theta in radians.";
   let LLVMIntrinsic = int_sin;
-  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 arguments = [LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def Tan  : DXILOp {
+def Tan : DXILOpAndClass<14, unary> {
   let Doc = "Returns tangent(theta) for theta in radians.";
-  let OpCode = 14;
-  let OpClass = unary;
   let LLVMIntrinsic = int_tan;
-  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 arguments = [LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def ACos  : DXILOp {
+def ACos : DXILOpAndClass<15, unary> {
   let Doc = "Returns the arccosine of the specified value.";
-  let OpCode = 15;
-  let OpClass = unary;
   let LLVMIntrinsic = int_acos;
-  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 arguments = [LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def ASin  : DXILOp {
+def ASin : DXILOpAndClass<16, unary> {
   let Doc = "Returns the arcsine of the specified value.";
-  let OpCode = 16;
-  let OpClass = unary;
   let LLVMIntrinsic = int_asin;
-  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 arguments = [LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def ATan  : DXILOp {
+def ATan : DXILOpAndClass<17, unary> {
   let Doc = "Returns the arctangent of the specified value.";
-  let OpCode = 17;
-  let OpClass = unary;
   let LLVMIntrinsic = int_atan;
-  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 arguments = [LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def HCos  : DXILOp {
+def HCos : DXILOpAndClass<18, unary> {
   let Doc = "Returns the hyperbolic cosine of the specified value.";
-  let OpCode = 18;
-  let OpClass = unary;
   let LLVMIntrinsic = int_cosh;
-  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 arguments = [LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def HSin  : DXILOp {
+def HSin : DXILOpAndClass<19, unary> {
   let Doc = "Returns the hyperbolic sine of the specified value.";
-  let OpCode = 19;
-  let OpClass = unary;
   let LLVMIntrinsic = int_sinh;
-  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 arguments = [LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def HTan  : DXILOp {
+def HTan : DXILOpAndClass<20, unary> {
   let Doc = "Returns the hyperbolic tan of the specified value.";
-  let OpCode = 20;
-  let OpClass = unary;
   let LLVMIntrinsic = int_tanh;
-  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 arguments = [LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-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;
+def Exp2 : DXILOpAndClass<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 = (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 arguments = [LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-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;
+def Frac : DXILOpAndClass<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 = (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 arguments = [LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def Log2 : DXILOp {
+def Log2 : DXILOpAndClass<23, unary> {
   let Doc = "Returns the base-2 logarithm of the specified value.";
-  let OpCode = 23;
-  let OpClass = unary;
   let LLVMIntrinsic = int_log2;
-  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 arguments = [LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def Sqrt : DXILOp {
-  let Doc = "Returns the square root of the specified floating-point value, per component.";
-  let OpCode = 24;
-  let OpClass = unary;
+def Sqrt : DXILOpAndClass<24, unary> {
+  let Doc = "Returns the square root of the specified floating-point value, "
+            "per component.";
   let LLVMIntrinsic = int_sqrt;
-  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 arguments = [LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-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;
+def RSqrt : DXILOpAndClass<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 = (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 arguments = [LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def Round : DXILOp {
-  let Doc = "Returns the input rounded to the nearest integer within a floating-point type.";
-  let OpCode = 26;
-  let OpClass = unary;
+def Round : DXILOpAndClass<26, unary> {
+  let Doc = "Returns the input rounded to the nearest integer within a "
+            "floating-point type.";
   let LLVMIntrinsic = int_roundeven;
-  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 arguments = [LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def Floor : DXILOp {
-  let Doc = "Returns the largest integer that is less than or equal to the input.";
-  let OpCode = 27;
-  let OpClass = unary;
+def Floor : DXILOpAndClass<27, unary> {
+  let Doc =
+      "Returns the largest integer that is less than or equal to the input.";
   let LLVMIntrinsic = int_floor;
-  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 arguments = [LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def Ceil  : DXILOp {
-  let Doc = "Returns the smallest integer that is greater than or equal to the input.";
-  let OpCode = 28;
-  let OpClass = unary;
+def Ceil : DXILOpAndClass<28, unary> {
+  let Doc = "Returns the smallest integer that is greater than or equal to the "
+            "input.";
   let LLVMIntrinsic = int_ceil;
-  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 arguments = [LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def Trunc : DXILOp {
+def Trunc : DXILOpAndClass<29, unary> {
   let Doc = "Returns the specified value truncated to the integer component.";
-  let OpCode = 29;
-  let OpClass = unary;
   let LLVMIntrinsic = int_trunc;
-  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 arguments = [LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def Rbits : DXILOp {
+def Rbits : DXILOpAndClass<30, unary> {
   let Doc = "Returns the specified value with its bits reversed.";
-  let OpCode = 30;
-  let OpClass = unary;
   let LLVMIntrinsic = int_bitreverse;
-  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)>];
-  let attributes = (attrs ReadNone);
+  let arguments = [LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints =
+      [Constraints<SMVersion<SM6_0>,
+                   [Overloads<[llvm_i16_ty, llvm_i32_ty, llvm_i64_ty]>]>];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def FMax : DXILOp {
+def FMax : DXILOpAndClass<35, binary> {
   let Doc = "Float maximum. FMax(a,b) = a > b ? a : b";
-  let OpCode = 35;
-  let OpClass = binary;
   let LLVMIntrinsic = int_maxnum;
-  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)>];
-  let attributes = (attrs ReadNone);
+  let arguments = [LLVMMatchType<0>, LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints =
+      [Constraints<SMVersion<SM6_0>,
+                   [Overloads<[llvm_half_ty, llvm_float_ty, llvm_double_ty]>]>];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def FMin : DXILOp {
+def FMin : DXILOpAndClass<36, binary> {
   let Doc = "Float minimum. FMin(a,b) = a < b ? a : b";
-  let OpCode = 36;
-  let OpClass = binary;
   let LLVMIntrinsic = int_minnum;
-  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)>];
-  let attributes = (attrs ReadNone);
+  let arguments = [LLVMMatchType<0>, LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints =
+      [Constraints<SMVersion<SM6_0>,
+                   [Overloads<[llvm_half_ty, llvm_float_ty, llvm_double_ty]>]>];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def SMax : DXILOp {
+def SMax : DXILOpAndClass<37, binary> {
   let Doc = "Signed integer maximum. SMax(a,b) = a > b ? a : b";
-  let OpCode = 37;
-  let OpClass = binary;
   let LLVMIntrinsic = int_smax;
-  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)>];
-  let attributes = (attrs ReadNone);
+  let arguments = [LLVMMatchType<0>, LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints =
+      [Constraints<SMVersion<SM6_0>,
+                   [Overloads<[llvm_i16_ty, llvm_i32_ty, llvm_i64_ty]>]>];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def SMin : DXILOp {
+def SMin : DXILOpAndClass<38, binary> {
   let Doc = "Signed integer minimum. SMin(a,b) = a < b ? a : b";
-  let OpCode = 38;
-  let OpClass = binary;
   let LLVMIntrinsic = int_smin;
-  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)>];
-  let attributes = (attrs ReadNone);
+  let arguments = [LLVMMatchType<0>, LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints =
+      [Constraints<SMVersion<SM6_0>,
+                   [Overloads<[llvm_i16_ty, llvm_i32_ty, llvm_i64_ty]>]>];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def UMax : DXILOp {
+def UMax : DXILOpAndClass<39, binary> {
   let Doc = "Unsigned integer maximum. UMax(a,b) = a > b ? a : b";
-  let OpCode = 39;
-  let OpClass = binary;
   let LLVMIntrinsic = int_umax;
-  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)>];
-  let attributes = (attrs ReadNone);
+  let arguments = [LLVMMatchType<0>, LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints =
+      [Constraints<SMVersion<SM6_0>,
+                   [Overloads<[llvm_i16_ty, llvm_i32_ty, llvm_i64_ty]>]>];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def UMin : DXILOp {
+def UMin : DXILOpAndClass<40, binary> {
   let Doc = "Unsigned integer minimum. UMin(a,b) = a < b ? a : b";
-  let OpCode = 40;
-  let OpClass = binary;
   let LLVMIntrinsic = int_umin;
-  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)>];
-  let attributes = (attrs ReadNone);
+  let arguments = [LLVMMatchType<0>, LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints =
+      [Constraints<SMVersion<SM6_0>,
+                   [Overloads<[llvm_i16_ty, llvm_i32_ty, llvm_i64_ty]>]>];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def FMad : DXILOp {
-  let Doc = "Floating point arithmetic multiply/add operation. fmad(m,a,b) = m * a + b.";
-  let OpCode = 46;
-  let OpClass = tertiary;
+def FMad : DXILOpAndClass<46, tertiary> {
+  let Doc = "Floating point arithmetic multiply/add operation. fmad(m,a,b) = m "
+            "* a + b.";
   let LLVMIntrinsic = int_fmuladd;
-  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)>];
-  let attributes = (attrs ReadNone);
+  let arguments = [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints =
+      [Constraints<SMVersion<SM6_0>,
+                   [Overloads<[llvm_half_ty, llvm_float_ty, llvm_double_ty]>]>];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def IMad : DXILOp {
-  let OpCode = 48;
-  let OpClass = tertiary;
+def IMad : DXILOpAndClass<48, tertiary> {
+  let Doc = "Signed integer arithmetic multiply/add operation. imad(m,a,b) = m "
+            "* a + b.";
   let LLVMIntrinsic = int_dx_imad;
-  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)>];
-  let attributes = (attrs ReadNone);
+  let arguments = [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints =
+      [Constraints<SMVersion<SM6_0>,
+                   [Overloads<[llvm_i16_ty, llvm_i32_ty, llvm_i64_ty]>]>];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def UMad : DXILOp {
-  let OpCode = 49;
-  let OpClass = tertiary;
+def UMad : DXILOpAndClass<49, tertiary> {
+  let Doc = "Unsigned integer arithmetic multiply/add operation. umad(m,a, = m "
+            "* a + b.";
   let LLVMIntrinsic = int_dx_umad;
-  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)>];
-  let attributes = (attrs ReadNone);
+  let arguments = [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>];
+  let result = [dxil_overload_ty];
+  let constraints =
+      [Constraints<SMVersion<SM6_0>,
+                   [Overloads<[llvm_i16_ty, llvm_i32_ty, llvm_i64_ty]>]>];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-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;
+def Dot2 : DXILOpAndClass<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 = !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)>];
-  let attributes = (attrs ReadNone);
+  let arguments = !listsplat(llvm_anyfloat_ty, 4);
+  let result = [llvm_anyfloat_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-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;
+def Dot3 : DXILOpAndClass<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 = !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)>];
-  let attributes = (attrs ReadNone);
+  let arguments = !listsplat(llvm_anyfloat_ty, 6);
+  let result = [llvm_anyfloat_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-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;
+def Dot4 : DXILOpAndClass<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 = !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)>];
-  let attributes = (attrs ReadNone);
+  let arguments = !listsplat(llvm_anyfloat_ty, 8);
+  let result = [llvm_anyfloat_ty];
+  let constraints = [
+    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
+  ];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def ThreadId : DXILOp {
+def ThreadId : DXILOpAndClass<93, threadId> {
   let Doc = "Reads the thread ID";
-  let OpCode = 93;
-  let OpClass = threadId;
   let LLVMIntrinsic = int_dx_thread_id;
-  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)>];
-  let attributes = (attrs ReadNone);
+  let arguments = [llvm_i32_ty];
+  let result = [llvm_i32_ty];
+  let constraints =
+      [Constraints<SMVersion<SM6_0>,
+                   [Stages<[compute, mesh, amplification, node]>]>];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def GroupId  : DXILOp {
+def GroupId : DXILOpAndClass<94, groupId> {
   let Doc = "Reads the group ID (SV_GroupID)";
-  let OpCode = 94;
-  let OpClass = groupId;
   let LLVMIntrinsic = int_dx_group_id;
-  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)>];
-  let attributes = (attrs ReadNone);
+  let arguments = [llvm_i32_ty];
+  let result = [llvm_i32_ty];
+  let constraints =
+      [Constraints<SMVersion<SM6_0>,
+                   [Stages<[compute, mesh, amplification, node]>]>];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-def ThreadIdInGroup : DXILOp {
+def ThreadIdInGroup : DXILOpAndClass<95, threadIdInGroup> {
   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 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)>];
-  let attributes = (attrs ReadNone);
+  let arguments = [llvm_i32_ty];
+  let result = [llvm_i32_ty];
+  let constraints =
+      [Constraints<SMVersion<SM6_0>,
+                   [Stages<[compute, mesh, amplification, node]>]>];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
 
-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;
+def FlattenedThreadIdInGroup : DXILOpAndClass<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 arguments = (ins llvm_i32_ty);
-  let result = (out);
-  let sm_constraints = [SMVersionConstraints<SM6_0, (overloads llvm_i32_ty),
-                             (stages compute, mesh, amplification, node)>];
-  let attributes = (attrs ReadNone);
+  let arguments = [llvm_i32_ty];
+  let constraints =
+      [Constraints<SMVersion<SM6_0>,
+                   [Stages<[compute, mesh, amplification, node]>]>];
+  let attributes = [ReadNone];
   let DXILVersion = DX1_0;
 }
diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
index 5fa0ac19b1935..2ae543eccd225 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/ADT/StringSwitch.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/DXILABI.h"
@@ -193,12 +192,12 @@ static FunctionType *getDXILOpFunctionType(const OpCodeProperty *Prop,
 
 static int getValidConstraintIndex(const OpCodeProperty *Prop,
                                    const VersionTuple SMVer) {
-  // std::vector Prop->SMConstraints is in ascending order of SM Version
+  // std::vector Prop->Constraints 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();
+  auto Size = Prop->Constraints.size();
   for (int I = Size - 1; I >= 0; I--) {
-    auto OL = Prop->SMConstraints[I];
+    auto OL = Prop->Constraints[I];
     if (VersionTuple(OL.ShaderModelVer.Major, OL.ShaderModelVer.Minor) <=
         SMVer) {
       return I;
@@ -221,10 +220,14 @@ CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode,
                                           SmallVector<Value *> Args) {
   const OpCodeProperty *Prop = getOpCodeProperty(OpCode);
   int Index = getValidConstraintIndex(Prop, SMVer);
-  uint16_t ValidTyMask = Prop->SMConstraints[Index].ValidTys;
+  uint16_t ValidTyMask = Prop->Constraints[Index].ValidTys;
 
   OverloadKind Kind = getOverloadKind(OverloadTy);
-  if ((ValidTyMask & (uint16_t)Kind) == 0) {
+
+  // Check if the operation supports overload types and OverloadTy is valid
+  // per the specified types for the operation
+  if ((ValidTyMask != OverloadKind::UNDEFINED) &&
+      (ValidTyMask & (uint16_t)Kind) == 0) {
     report_fatal_error(
         StringRef(std::string("Invalid Overload Type for DXIL operation - ")
                       .append(getOpCodeName((OpCode)))),
@@ -233,7 +236,7 @@ CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode,
 
   // Perform necessary checks to ensure Opcode is valid in the targeted shader
   // kind
-  uint16_t ValidShaderKindMask = Prop->SMConstraints[Index].ValidShaderKinds;
+  uint16_t ValidShaderKindMask = Prop->Constraints[Index].ValidShaderKinds;
   ShaderKind ModuleStagekind = getShaderkKindEnum(StageKind);
 
   // Ensure valid shader stage constraints are specified
@@ -279,45 +282,14 @@ CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode,
   return B.CreateCall(DXILFn, Args);
 }
 
-Type *DXILOpBuilder::getOverloadTy(dxil::OpCode OpCode, VersionTuple SMVer,
-                                   FunctionType *FT) {
+Type *DXILOpBuilder::getOverloadType(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();
-    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:
-      return Type::getHalfTy(Ctx);
-    case OverloadKind::FLOAT:
-      return Type::getFloatTy(Ctx);
-    case OverloadKind::DOUBLE:
-      return Type::getDoubleTy(Ctx);
-    case OverloadKind::I1:
-      return Type::getInt1Ty(Ctx);
-    case OverloadKind::I8:
-      return Type::getInt8Ty(Ctx);
-    case OverloadKind::I16:
-      return Type::getInt16Ty(Ctx);
-    case OverloadKind::I32:
-      return Type::getInt32Ty(Ctx);
-    case OverloadKind::I64:
-      return Type::getInt64Ty(Ctx);
-    default:
-      llvm_unreachable("invalid overload type");
-      return nullptr;
-    }
+    return FT->getReturnType();
   }
 
   // Consider FT->getReturnType() as default overload type, unless
diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.h b/llvm/lib/Target/DirectX/DXILOpBuilder.h
index 1abb7da7cb1b6..7bc4f2e1d20cf 100644
--- a/llvm/lib/Target/DirectX/DXILOpBuilder.h
+++ b/llvm/lib/Target/DirectX/DXILOpBuilder.h
@@ -44,8 +44,8 @@ class DXILOpBuilder {
                              StringRef StageKind, Type *ReturnTy,
                              Type *OverloadTy, SmallVector<Value *> Args);
 
-  Type *getOverloadTy(dxil::OpCode OpCode, VersionTuple SMVer,
-                      FunctionType *FT);
+  Type *getOverloadType(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 e69c17a43608e..20d8b586e702b 100644
--- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
@@ -78,7 +78,7 @@ static void lowerIntrinsic(dxil::OpCode DXILOp, Function &F, Module &M,
                            VersionTuple SMVer, StringRef StageKind) {
   IRBuilder<> B(M.getContext());
   DXILOpBuilder DXILB(M, B);
-  Type *OverloadTy = DXILB.getOverloadTy(DXILOp, SMVer, F.getFunctionType());
+  Type *OverloadTy = DXILB.getOverloadType(DXILOp, SMVer, F.getFunctionType());
   for (User *U : make_early_inc_range(F.users())) {
     CallInst *CI = dyn_cast<CallInst>(U);
     if (!CI)
diff --git a/llvm/test/CodeGen/DirectX/flattened_thread_id_in_group_error.ll b/llvm/test/CodeGen/DirectX/flattened_thread_id_in_group_error.ll
index 05351563e7f8e..9abea5e82868f 100644
--- a/llvm/test/CodeGen/DirectX/flattened_thread_id_in_group_error.ll
+++ b/llvm/test/CodeGen/DirectX/flattened_thread_id_in_group_error.ll
@@ -3,7 +3,6 @@
 ; DXIL operation sin is not valid in library stage
 ; CHECK: LLVM ERROR: library : Invalid Shader Stage for DXIL operation - FlattenedThreadIdInGroup
 
-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.7-library"
 
 ; Function Attrs: noinline nounwind optnone
diff --git a/llvm/test/CodeGen/DirectX/group_id_error.ll b/llvm/test/CodeGen/DirectX/group_id_error.ll
index 0bf62a785dbf7..2a6adcf2a9362 100644
--- a/llvm/test/CodeGen/DirectX/group_id_error.ll
+++ b/llvm/test/CodeGen/DirectX/group_id_error.ll
@@ -3,7 +3,6 @@
 ; DXIL operation not valid for pixel stage
 ; CHECK: LLVM ERROR: pixel : Invalid Shader Stage for DXIL operation - GroupId
 
-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.7-pixel"
 
 ; Function Attrs: noinline nounwind optnone
diff --git a/llvm/test/CodeGen/DirectX/thread_id_error.ll b/llvm/test/CodeGen/DirectX/thread_id_error.ll
index 168ec01a75580..6928932328fbe 100644
--- a/llvm/test/CodeGen/DirectX/thread_id_error.ll
+++ b/llvm/test/CodeGen/DirectX/thread_id_error.ll
@@ -3,7 +3,6 @@
 ; DXIL operation not valid for library stage
 ; CHECK: LLVM ERROR: library : Invalid Shader Stage for DXIL operation - ThreadId
 
-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.7-library"
 
 ; Function Attrs: noinline nounwind optnone
diff --git a/llvm/test/CodeGen/DirectX/thread_id_in_group_error.ll b/llvm/test/CodeGen/DirectX/thread_id_in_group_error.ll
index ced91a24aee60..8b63fd7bae543 100644
--- a/llvm/test/CodeGen/DirectX/thread_id_in_group_error.ll
+++ b/llvm/test/CodeGen/DirectX/thread_id_in_group_error.ll
@@ -3,7 +3,6 @@
 ; DXIL operation sin is not valid in vertex stage
 ; CHECK: LLVM ERROR: vertex : Invalid Shader Stage for DXIL operation - ThreadIdInGroup
 
-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.7-vertex"
 
 ; Function Attrs: noinline nounwind optnone
diff --git a/llvm/utils/TableGen/DXILEmitter.cpp b/llvm/utils/TableGen/DXILEmitter.cpp
index 24b94f68791f7..79e4e09df437d 100644
--- a/llvm/utils/TableGen/DXILEmitter.cpp
+++ b/llvm/utils/TableGen/DXILEmitter.cpp
@@ -40,10 +40,8 @@ struct DXILOperationDesc {
   StringRef Doc;      // the documentation description of this instruction
   // 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;
+  // Vector of operation constraint records
+  SmallVector<Record *> Constraints;
   SmallVector<std::string>
       OpAttributes;     // operation attribute represented as strings
   StringRef Intrinsic;  // The llvm intrinsic map to OpName. Default is "" which
@@ -102,13 +100,13 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) {
 
   Doc = R->getValueAsString("Doc");
   SmallVector<Record *> ParamTypeRecs;
-  DagInit *OutDag = R->getValueAsDag("result");
-  for (const Init *Arg : OutDag->getArgs()) {
-    ParamTypeRecs.push_back(cast<DefInit>(Arg)->getDef());
+  std::vector<Record *> RetTys = R->getValueAsListOfDefs("result");
+  for (auto Ty : RetTys) {
+    ParamTypeRecs.push_back(Ty);
   }
-  DagInit *InDag = R->getValueAsDag("arguments");
-  for (const Init *Arg : InDag->getArgs()) {
-    ParamTypeRecs.push_back(cast<DefInit>(Arg)->getDef());
+  std::vector<Record *> ArgTys = R->getValueAsListOfDefs("arguments");
+  for (auto Ty : ArgTys) {
+    ParamTypeRecs.push_back(Ty);
   }
   unsigned ParamTypeRecsSize = ParamTypeRecs.size();
   // Populate OpTypes with return type and parameter types
@@ -166,48 +164,58 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) {
            "Multiple overload type specification not supported");
     OverloadParamIndex = OverloadParamIndices[0];
   }
-
-  // Get Shader Model Constraint Records
-  std::vector<Record *> SMConstrintRecs =
-      R->getValueAsListOfDefs("sm_constraints");
+  // Get Constraint Records
+  std::vector<Record *> ConstrintRecs =
+      R->getValueAsListOfDefs("constraints");
 
   // Sort records in ascending order of Shader Model version
-  std::sort(SMConstrintRecs.begin(), SMConstrintRecs.end(),
+  std::sort(ConstrintRecs.begin(), ConstrintRecs.end(),
             [](Record *RecA, Record *RecB) {
               unsigned RecAMaj =
-                  RecA->getValueAsDef("sm_version")->getValueAsInt("Major");
+                  RecA->getValueAsDef("pred")->getValueAsDef("sm_version")->getValueAsInt("Major");
               unsigned RecAMin =
-                  RecA->getValueAsDef("sm_version")->getValueAsInt("Minor");
+                  RecA->getValueAsDef("pred")->getValueAsDef("sm_version")->getValueAsInt("Minor");
               unsigned RecBMaj =
-                  RecB->getValueAsDef("sm_version")->getValueAsInt("Major");
+                  RecB->getValueAsDef("pred")->getValueAsDef("sm_version")->getValueAsInt("Major");
               unsigned RecBMin =
-                  RecB->getValueAsDef("sm_version")->getValueAsInt("Minor");
+                  RecB->getValueAsDef("pred")->getValueAsDef("sm_version")->getValueAsInt("Minor");
 
               return (VersionTuple(RecAMaj, RecAMin) <
                       VersionTuple(RecBMaj, RecBMin));
             });
 
-  for (Record *SMCR : SMConstrintRecs) {
-    SMConstraints.push_back(SMCR);
+  for (Record *CR : ConstrintRecs) {
+    Constraints.push_back(CR);
   }
 
   // Get the operation class
   OpClass = R->getValueAsDef("OpClass")->getName();
 
-  if (R->getValue("LLVMIntrinsic")) {
-    auto *IntrinsicDef = R->getValueAsDef("LLVMIntrinsic");
-    auto DefName = IntrinsicDef->getName();
-    assert(DefName.starts_with("int_") && "invalid intrinsic name");
-    // Remove the int_ from intrinsic name.
-    Intrinsic = DefName.substr(4);
-    // TODO: For now, assume that attributes of DXIL Operation are the same as
-    // that of the intrinsic. Deviations are expected to be encoded in TableGen
-    // record specification and handled accordingly here. Support to be added
-    // as needed.
-    ListInit *IntrPropList = IntrinsicDef->getValueAsListInit("IntrProperties");
-    auto IntrPropListSize = IntrPropList->size();
-    for (unsigned I = 0; I < IntrPropListSize; I++) {
-      OpAttributes.emplace_back(IntrPropList->getElement(I)->getAsString());
+  if (!OpClass.str().compare("UnknownOpClass")) {
+    report_fatal_error(
+        StringRef(std::string("Unspecified DXIL OpClass for DXIL operation - ")
+                      .append(OpName)),
+        /* gen_crash_diag=*/false);
+  }
+
+  const RecordVal *RV = R->getValue("LLVMIntrinsic");
+  if (RV && RV->getValue()) {
+    if (DefInit *DI = dyn_cast<DefInit>(RV->getValue())) {
+      auto *IntrinsicDef = DI->getDef();
+      auto DefName = IntrinsicDef->getName();
+      assert(DefName.starts_with("int_") && "invalid intrinsic name");
+      // Remove the int_ from intrinsic name.
+      Intrinsic = DefName.substr(4);
+      // TODO: For now, assume that attributes of DXIL Operation are the same as
+      // that of the intrinsic. Deviations are expected to be encoded in
+      // TableGen record specification and handled accordingly here. Support to
+      // be added as needed.
+      ListInit *IntrPropList =
+          IntrinsicDef->getValueAsListInit("IntrProperties");
+      auto IntrPropListSize = IntrPropList->size();
+      for (unsigned I = 0; I < IntrPropListSize; I++) {
+        OpAttributes.emplace_back(IntrPropList->getElement(I)->getAsString());
+      }
     }
   }
 }
@@ -279,47 +287,79 @@ static std::string getOverloadKindStr(const Record *R) {
   }
 }
 
-/// Return a string representation of OverloadKind enum that maps to
-/// input LLVMType record
+/// Return a string representation of constraints specified for the DXIL
+/// Operation
+//
 /// \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 = "";
+getConstraintString(const SmallVector<Record *> Recs) {
+  std::string ConstraintString = "";
   std::string Prefix = "";
-  OverloadString.append("{");
-  for (auto SMConstrRec : Recs) {
-    OverloadString.append(Prefix).append("{");
+  ConstraintString.append("{{");
+  // If no constraints were specified, assume the operation
+  // a) to be supported in SM 6.0 and later
+  // b) has no overload types
+  // c) is supported in all shader stage kinds
+  if (Recs.empty()) {
+    ConstraintString.append("{6, 0}, OverloadKind::UNDEFINED, ShaderKind::allKinds}");
+  }
+  for (auto ConstrRec : Recs) {
+    auto SMConstrRec = ConstrRec->getValueAsDef("pred");
     unsigned Major =
         SMConstrRec->getValueAsDef("sm_version")->getValueAsInt("Major");
     unsigned Minor =
         SMConstrRec->getValueAsDef("sm_version")->getValueAsInt("Minor");
-    OverloadString.append("{")
+    ConstraintString.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 = " | ";
+
+    auto ConstraintList = ConstrRec->getValueAsListOfDefs("constraints");
+    std::string OverloadMaskString = "";
+    std::string StageMaskString = "";
+    for (auto Constr : ConstraintList) {
+      // All Constraints are specified as anonymous records.
+      assert(Constr->isAnonymous() && "Constraint Specification Record expected to be anonymous");
+      // Generate Overload mask for constraint of class Overloads
+      if (!Constr->getType()->getAsString().compare("Overloads")) {
+        std::string PipePrefix = "";
+        auto OLTys = Constr->getValueAsListOfDefs("overload_types");
+        if (OLTys.empty()) {
+          OverloadMaskString.append("OverloadKind::UNDEFINED");
+        }
+        for (const auto *Ty : OLTys) {
+          OverloadMaskString.append(PipePrefix).append(getOverloadKindStr(Ty));
+          PipePrefix = " | ";
+        }
+      }
+      // Generate Shader Kind mask from Shader Stages constraints
+      if (!Constr->getType()->getAsString().compare("Stages")) {
+        std::string PipePrefix = "";
+        auto Stages = Constr->getValueAsListOfDefs("stage_kinds");
+        if (Stages.empty()) {
+          StageMaskString.append("ShaderKind::allKinds");
+        }
+        for (const auto *S : Stages) {
+          StageMaskString.append(PipePrefix).append("ShaderKind::").append(S->getName());
+          PipePrefix = " | ";
+        }
+      }
+    }
+    if (OverloadMaskString.empty()) {
+      OverloadMaskString.append(" OverloadKind::UNDEFINED ");
     }
-    // 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 = " | ";
+    if (StageMaskString.empty()) {
+      StageMaskString.append(" ShaderKind::allKinds ");
     }
-    OverloadString.append("}");
-    Prefix = ", ";
+
+    ConstraintString.append(OverloadMaskString)
+        .append(", ")
+        .append(StageMaskString);
+    ConstraintString.append("}");
   }
-  OverloadString.append("}");
-  return OverloadString;
+  ConstraintString.append("}");
+  return ConstraintString;
 }
 
 /// Emit Enums of DXIL Ops
@@ -448,6 +488,7 @@ static void emitDXILOperationTable(std::vector<DXILOperationDesc> &Ops,
   // code.
   unsigned TypeSz = PowerOf2Ceil(OverloadKindList.size());
   OS << "enum OverloadKind : uint" << TypeSz << "_t {\n";
+  OS << "    UNDEFINED = 0,\n";
   int shiftVal = 1;
   for (auto TyStr : OverloadKindList) {
     OS << "    " << TyStr << " = 1 << " << shiftVal++ << ",\n";
@@ -461,9 +502,9 @@ static void emitDXILOperationTable(std::vector<DXILOperationDesc> &Ops,
             unsigned Minor = 0; \n \
           };\n\n";
 
-  // Emit struct SMConstraints that encapsulates overload and shader kind
+  // Emit struct Constraints that encapsulates overload and shader kind
   // constraints predicated on shader model version, if any.
-  OS << "struct OpSMConstraints { \n \
+  OS << "struct OpConstraints { \n \
             Version ShaderModelVer; \n \
             uint16_t ValidTys; \n \
             uint16_t ValidShaderKinds; \n \
@@ -477,7 +518,7 @@ static void emitDXILOperationTable(std::vector<DXILOperationDesc> &Ops,
             dxil::OpCodeClass OpCodeClass; \n \
             // Offset in DXILOpCodeClassNameTable. \n \
             unsigned OpCodeClassNameOffset; \n \
-            std::vector<OpSMConstraints> SMConstraints; \n \
+            std::vector<OpConstraints> Constraints; \n \
             llvm::Attribute::AttrKind FuncAttr; \n \
             int OverloadParamIndex;        // parameter index which control the overload. \n \
                                            // When < 0, should be only 1 overload type. \n \
@@ -505,12 +546,13 @@ static void emitDXILOperationTable(std::vector<DXILOperationDesc> &Ops,
     case OverloadKind::I64:  \n \
       return \"i64\";  \n \
     case OverloadKind::VOID:  \n \
+    case OverloadKind::UNDEFINED:  \n \
+      return \"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
@@ -533,12 +575,14 @@ static void emitDXILOperationTable(std::vector<DXILOperationDesc> &Ops,
     }
     OS << Prefix << "  { dxil::OpCode::" << Op.OpName << ", "
        << OpStrings.get(Op.OpName) << ", OpCodeClass::" << Op.OpClass << ", "
-       << OpClassStrings.get(Op.OpClass.data()) << ", "
-       << getOverloadKindStrsFromConstraint(Op.SMConstraints) << ", "
+       << OpClassStrings.get(Op.OpClass.data())
+       << ", "
+       << getConstraintString(Op.Constraints) << ", "
        << emitDXILOperationAttr(Op.OpAttributes) << ", "
        << Op.OverloadParamIndex << ", " << Op.OpTypes.size() - 1 << ", "
-       << Parameters.get(ParameterMap[Op.OpClass]) << " }\n";
-    Prefix = ",";
+       << Parameters.get(ParameterMap[Op.OpClass]) << " }";
+    Prefix = ",\n";
+    // OS << "\n// " << getConstraintString(Op.Constraints) << "\n";
   }
   OS << "  };\n";
 

>From 4f3be130b9dc4bdef50a1cad0788746299adaffb Mon Sep 17 00:00:00 2001
From: Bharadwaj Yadavalli <Bharadwaj.Yadavalli at microsoft.com>
Date: Wed, 10 Jul 2024 23:01:26 +0000
Subject: [PATCH 06/12] Use Module field of DXILOpBuilder to find target SM
 version and Shader Kind in createDXILOpCall() instead of computing them in
 its callers and passing them as arguments.

---
 llvm/lib/Target/DirectX/DXIL.td               |   4 +
 llvm/lib/Target/DirectX/DXILOpBuilder.cpp     |  85 ++++++-
 llvm/lib/Target/DirectX/DXILOpBuilder.h       |   6 +-
 llvm/lib/Target/DirectX/DXILOpLowering.cpp    |  24 +-
 .../CodeGen/DirectX/sin_no_stage_error.ll     |   2 +-
 llvm/utils/TableGen/DXILEmitter.cpp           | 232 +++++++++---------
 6 files changed, 202 insertions(+), 151 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td
index 3d25b4e8cb60c..3f3dac0453ecc 100644
--- a/llvm/lib/Target/DirectX/DXIL.td
+++ b/llvm/lib/Target/DirectX/DXIL.td
@@ -237,6 +237,10 @@ def mesh : ShaderStage;
 def node : ShaderStage;
 def raygeneration : ShaderStage;
 def intersection : ShaderStage;
+def anyhit : ShaderStage;
+def closesthit : ShaderStage;
+def callable : ShaderStage;
+def miss : ShaderStage;
 
 // Primitive predicate
 class Pred;
diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
index 2ae543eccd225..4384eec0184bb 100644
--- a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
@@ -15,6 +15,7 @@
 #include "llvm/IR/Module.h"
 #include "llvm/Support/DXILABI.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/TargetParser/Triple.h"
 
 using namespace llvm;
 using namespace llvm::dxil;
@@ -24,9 +25,7 @@ constexpr StringLiteral DXILOpNamePrefix = "dx.op.";
 // 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) {
@@ -162,6 +161,45 @@ static Type *getTypeFromParameterKind(ParameterKind Kind, Type *OverloadTy) {
   return nullptr;
 }
 
+static ShaderKind getShaderKindEnum(Triple::EnvironmentType EnvType) {
+  switch (EnvType) {
+  case Triple::Pixel:
+    return ShaderKind::pixel;
+  case Triple::Vertex:
+    return ShaderKind::vertex;
+  case Triple::Geometry:
+    return ShaderKind::geometry;
+  case Triple::Hull:
+    return ShaderKind::hull;
+  case Triple::Domain:
+    return ShaderKind::domain;
+  case Triple::Compute:
+    return ShaderKind::compute;
+  case Triple::Library:
+    return ShaderKind::library;
+  case Triple::RayGeneration:
+    return ShaderKind::raygeneration;
+  case Triple::Intersection:
+    return ShaderKind::intersection;
+  case Triple::AnyHit:
+    return ShaderKind::anyhit;
+  case Triple::ClosestHit:
+    return ShaderKind::closesthit;
+  case Triple::Miss:
+    return ShaderKind::miss;
+  case Triple::Callable:
+    return ShaderKind::callable;
+  case Triple::Mesh:
+    return ShaderKind::mesh;
+  case Triple::Amplification:
+    return ShaderKind::amplification;
+  default:
+    break;
+  }
+  llvm_unreachable(
+      "Shader Kind Not Found - Invalid DXIL Environment Specified");
+}
+
 /// Construct DXIL function type. This is the type of a function with
 /// the following prototype
 ///     OverloadType dx.op.<opclass>.<return-type>(int opcode, <param types>)
@@ -213,11 +251,23 @@ static int getValidConstraintIndex(const OpCodeProperty *Prop,
 namespace llvm {
 namespace dxil {
 
-CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode,
-                                          VersionTuple SMVer,
-                                          StringRef StageKind, Type *ReturnTy,
+CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode, Type *ReturnTy,
                                           Type *OverloadTy,
                                           SmallVector<Value *> Args) {
+
+  std::string TTStr = M.getTargetTriple();
+  // No extra checks need be performed to verify that the Triple is
+  // well-formed or 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.
+  auto Major = Triple(TTStr).getOSVersion().getMajor();
+  auto MinorOrErr = Triple(TTStr).getOSVersion().getMinor();
+  uint32_t Minor = MinorOrErr.has_value() ? *MinorOrErr : 0;
+  VersionTuple SMVer(Major, Minor);
+  // Get Shader Stage Kind
+  Triple::EnvironmentType ShaderEnv = Triple(TTStr).getEnvironment();
+  auto ShaderEnvStr = Triple(TTStr).getEnvironmentName();
+
   const OpCodeProperty *Prop = getOpCodeProperty(OpCode);
   int Index = getValidConstraintIndex(Prop, SMVer);
   uint16_t ValidTyMask = Prop->Constraints[Index].ValidTys;
@@ -234,10 +284,18 @@ CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode,
         /* gen_crash_diag=*/false);
   }
 
+  // Ensure Environment type is known
+  if (ShaderEnv == Triple::UnknownEnvironment) {
+    report_fatal_error(
+        StringRef(SMVer.getAsString().append(
+            ": Unknown Compilation Target Shader Stage specified ")),
+        /*gen_crash_diag*/ false);
+  }
+
   // Perform necessary checks to ensure Opcode is valid in the targeted shader
   // kind
   uint16_t ValidShaderKindMask = Prop->Constraints[Index].ValidShaderKinds;
-  ShaderKind ModuleStagekind = getShaderkKindEnum(StageKind);
+  enum ShaderKind ModuleStagekind = getShaderKindEnum(ShaderEnv);
 
   // Ensure valid shader stage constraints are specified
   if (ValidShaderKindMask == ShaderKind::Unknown) {
@@ -260,7 +318,7 @@ CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode,
   // Verify the target shader stage is valid for the DXIL operation
   if (!(ValidShaderKindMask & ModuleStagekind)) {
     report_fatal_error(
-        StringRef(std::string(StageKind)
+        StringRef(std::string(ShaderEnvStr)
                       .append(" : Invalid Shader Stage for DXIL operation - ")
                       .append(getOpCodeName(OpCode))
                       .append(" for Shader Model ")
@@ -282,8 +340,17 @@ CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode,
   return B.CreateCall(DXILFn, Args);
 }
 
-Type *DXILOpBuilder::getOverloadType(dxil::OpCode OpCode, VersionTuple SMVer,
-                                     FunctionType *FT) {
+Type *DXILOpBuilder::getOverloadType(dxil::OpCode OpCode, FunctionType *FT) {
+
+  std::string TTStr = M.getTargetTriple();
+  // No extra checks need be performed to verify that the Triple is
+  // well-formed or 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.
+  auto Major = Triple(TTStr).getOSVersion().getMajor();
+  auto MinorOrErr = Triple(TTStr).getOSVersion().getMinor();
+  uint32_t Minor = MinorOrErr.has_value() ? *MinorOrErr : 0;
+  VersionTuple SMVer(Major, Minor);
 
   const OpCodeProperty *Prop = getOpCodeProperty(OpCode);
   // If DXIL Op has no overload parameter, just return the
diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.h b/llvm/lib/Target/DirectX/DXILOpBuilder.h
index 7bc4f2e1d20cf..584770a8a3a56 100644
--- a/llvm/lib/Target/DirectX/DXILOpBuilder.h
+++ b/llvm/lib/Target/DirectX/DXILOpBuilder.h
@@ -40,12 +40,10 @@ class DXILOpBuilder {
   /// \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, VersionTuple SMVer,
-                             StringRef StageKind, Type *ReturnTy,
+  CallInst *createDXILOpCall(dxil::OpCode OpCode, Type *ReturnTy,
                              Type *OverloadTy, SmallVector<Value *> Args);
 
-  Type *getOverloadType(dxil::OpCode OpCode, VersionTuple SMVer,
-                        FunctionType *FT);
+  Type *getOverloadType(dxil::OpCode OpCode, 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 20d8b586e702b..7b098d6a6b39c 100644
--- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
@@ -74,11 +74,10 @@ static SmallVector<Value *> argVectorFlatten(CallInst *Orig,
   return NewOperands;
 }
 
-static void lowerIntrinsic(dxil::OpCode DXILOp, Function &F, Module &M,
-                           VersionTuple SMVer, StringRef StageKind) {
+static void lowerIntrinsic(dxil::OpCode DXILOp, Function &F, Module &M) {
   IRBuilder<> B(M.getContext());
   DXILOpBuilder DXILB(M, B);
-  Type *OverloadTy = DXILB.getOverloadType(DXILOp, SMVer, F.getFunctionType());
+  Type *OverloadTy = DXILB.getOverloadType(DXILOp, F.getFunctionType());
   for (User *U : make_early_inc_range(F.users())) {
     CallInst *CI = dyn_cast<CallInst>(U);
     if (!CI)
@@ -94,8 +93,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, SMVer, StageKind, F.getReturnType(), OverloadTy, Args);
+    CallInst *DXILCI =
+        DXILB.createDXILOpCall(DXILOp, F.getReturnType(), OverloadTy, Args);
 
     CI->replaceAllUsesWith(DXILCI);
     CI->eraseFromParent();
@@ -111,19 +110,6 @@ static bool lowerIntrinsics(Module &M) {
 #include "DXILOperation.inc"
 #undef DXIL_OP_INTRINSIC_MAP
 
-  // Get Shader Model version
-  std::string TTStr = M.getTargetTriple();
-  // No extra checks need be performed to verify that the Triple is
-  // well-formed or 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.
-  auto Major = Triple(TTStr).getOSVersion().getMajor();
-  auto MinorOrErr = Triple(TTStr).getOSVersion().getMinor();
-  uint32_t Minor = MinorOrErr.has_value() ? *MinorOrErr : 0;
-  VersionTuple SMVer(Major, Minor);
-  // Get Shader Kind
-  std::string StageKind = Triple(TTStr).getEnvironmentName().str();
-
   for (Function &F : make_early_inc_range(M.functions())) {
     if (!F.isDeclaration())
       continue;
@@ -133,7 +119,7 @@ static bool lowerIntrinsics(Module &M) {
     auto LowerIt = LowerMap.find(ID);
     if (LowerIt == LowerMap.end())
       continue;
-    lowerIntrinsic(LowerIt->second, F, M, SMVer, StageKind);
+    lowerIntrinsic(LowerIt->second, F, M);
     Updated = true;
   }
   return Updated;
diff --git a/llvm/test/CodeGen/DirectX/sin_no_stage_error.ll b/llvm/test/CodeGen/DirectX/sin_no_stage_error.ll
index 52c595571320a..712d5afce1fa7 100644
--- a/llvm/test/CodeGen/DirectX/sin_no_stage_error.ll
+++ b/llvm/test/CodeGen/DirectX/sin_no_stage_error.ll
@@ -1,7 +1,7 @@
 ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.0 %s 2>&1 | FileCheck %s
 
 ; Shader Stage is required to ensure the operation is supported.
-; CHECK: LLVM ERROR: 6.0: DXIL Module created with Unspecifed or Unknown Target Shader Stage
+; CHECK: LLVM ERROR: 6.0: Unknown Compilation Target Shader Stage specified
 
 define noundef float @sin_float(float noundef %a) #0 {
 entry:
diff --git a/llvm/utils/TableGen/DXILEmitter.cpp b/llvm/utils/TableGen/DXILEmitter.cpp
index 79e4e09df437d..e86b44a92d270 100644
--- a/llvm/utils/TableGen/DXILEmitter.cpp
+++ b/llvm/utils/TableGen/DXILEmitter.cpp
@@ -165,20 +165,23 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) {
     OverloadParamIndex = OverloadParamIndices[0];
   }
   // Get Constraint Records
-  std::vector<Record *> ConstrintRecs =
-      R->getValueAsListOfDefs("constraints");
+  std::vector<Record *> ConstrintRecs = R->getValueAsListOfDefs("constraints");
 
   // Sort records in ascending order of Shader Model version
   std::sort(ConstrintRecs.begin(), ConstrintRecs.end(),
             [](Record *RecA, Record *RecB) {
-              unsigned RecAMaj =
-                  RecA->getValueAsDef("pred")->getValueAsDef("sm_version")->getValueAsInt("Major");
-              unsigned RecAMin =
-                  RecA->getValueAsDef("pred")->getValueAsDef("sm_version")->getValueAsInt("Minor");
-              unsigned RecBMaj =
-                  RecB->getValueAsDef("pred")->getValueAsDef("sm_version")->getValueAsInt("Major");
-              unsigned RecBMin =
-                  RecB->getValueAsDef("pred")->getValueAsDef("sm_version")->getValueAsInt("Minor");
+              unsigned RecAMaj = RecA->getValueAsDef("pred")
+                                     ->getValueAsDef("sm_version")
+                                     ->getValueAsInt("Major");
+              unsigned RecAMin = RecA->getValueAsDef("pred")
+                                     ->getValueAsDef("sm_version")
+                                     ->getValueAsInt("Minor");
+              unsigned RecBMaj = RecB->getValueAsDef("pred")
+                                     ->getValueAsDef("sm_version")
+                                     ->getValueAsInt("Major");
+              unsigned RecBMin = RecB->getValueAsDef("pred")
+                                     ->getValueAsDef("sm_version")
+                                     ->getValueAsInt("Minor");
 
               return (VersionTuple(RecAMaj, RecAMin) <
                       VersionTuple(RecBMaj, RecBMin));
@@ -292,8 +295,7 @@ static std::string getOverloadKindStr(const Record *R) {
 //
 /// \param Recs A vector of records of TableGen class type DXILShaderModel
 /// \return std::string string representation of OverloadKind
-static std::string
-getConstraintString(const SmallVector<Record *> Recs) {
+static std::string getConstraintString(const SmallVector<Record *> Recs) {
   std::string ConstraintString = "";
   std::string Prefix = "";
   ConstraintString.append("{{");
@@ -302,7 +304,8 @@ getConstraintString(const SmallVector<Record *> Recs) {
   // b) has no overload types
   // c) is supported in all shader stage kinds
   if (Recs.empty()) {
-    ConstraintString.append("{6, 0}, OverloadKind::UNDEFINED, ShaderKind::allKinds}");
+    ConstraintString.append(
+        "{6, 0}, OverloadKind::UNDEFINED, ShaderKind::allKinds}");
   }
   for (auto ConstrRec : Recs) {
     auto SMConstrRec = ConstrRec->getValueAsDef("pred");
@@ -320,7 +323,8 @@ getConstraintString(const SmallVector<Record *> Recs) {
     std::string StageMaskString = "";
     for (auto Constr : ConstraintList) {
       // All Constraints are specified as anonymous records.
-      assert(Constr->isAnonymous() && "Constraint Specification Record expected to be anonymous");
+      assert(Constr->isAnonymous() &&
+             "Constraint Specification Record expected to be anonymous");
       // Generate Overload mask for constraint of class Overloads
       if (!Constr->getType()->getAsString().compare("Overloads")) {
         std::string PipePrefix = "";
@@ -341,7 +345,9 @@ getConstraintString(const SmallVector<Record *> Recs) {
           StageMaskString.append("ShaderKind::allKinds");
         }
         for (const auto *S : Stages) {
-          StageMaskString.append(PipePrefix).append("ShaderKind::").append(S->getName());
+          StageMaskString.append(PipePrefix)
+              .append("ShaderKind::")
+              .append(S->getName());
           PipePrefix = " | ";
         }
       }
@@ -441,7 +447,6 @@ 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;
@@ -475,86 +480,6 @@ static void emitDXILOperationTable(std::vector<DXILOperationDesc> &Ops,
   OpClassStrings.layout();
   Parameters.layout();
 
-  // 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";
-  OS << "    UNDEFINED = 0,\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 Constraints that encapsulates overload and shader kind
-  // constraints predicated on shader model version, if any.
-  OS << "struct OpConstraints { \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<OpConstraints> Constraints; \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::UNDEFINED:  \n \
-      return \"void\";  \n \
-    case OverloadKind::ObjectType: \n \
-    case OverloadKind::UserDefinedType: \n \
-      break; \n \
-    } \n \
-    llvm_unreachable(\"invalid overload type for name\"); \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) "
@@ -575,8 +500,7 @@ static void emitDXILOperationTable(std::vector<DXILOperationDesc> &Ops,
     }
     OS << Prefix << "  { dxil::OpCode::" << Op.OpName << ", "
        << OpStrings.get(Op.OpName) << ", OpCodeClass::" << Op.OpClass << ", "
-       << OpClassStrings.get(Op.OpClass.data())
-       << ", "
+       << OpClassStrings.get(Op.OpClass.data()) << ", "
        << getConstraintString(Op.Constraints) << ", "
        << emitDXILOperationAttr(Op.OpAttributes) << ", "
        << Op.OverloadParamIndex << ", " << Op.OpTypes.size() - 1 << ", "
@@ -635,10 +559,10 @@ 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) {
+static void emitDXILOperationTableDataStructs(RecordKeeper &Records,
+                                              raw_ostream &OS) {
   // Get Shader stage records
   std::vector<Record *> ShaderKindRecs =
       Records.getAllDerivedDefinitions("ShaderStage");
@@ -646,13 +570,13 @@ static void emitShaderKindEnums(RecordKeeper &Records, raw_ostream &OS) {
   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
+  // plus one for allKinds
   // 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";
+  uint64_t ShaderKindCount = PowerOf2Ceil(ShaderKindRecs.size() + 1);
+  OS << "enum ShaderKind : uint" << ShaderKindCount << "_t {\n";
   const std::string allKinds("allKinds");
   // set unknown kind to 0
   OS << "  Unknown = 0,\n";
@@ -663,21 +587,91 @@ static void emitShaderKindEnums(RecordKeeper &Records, raw_ostream &OS) {
       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";
+  // allkinds is set to (1 << ShaderKindCount) - 1, with all bits set denoting
+  // support for all stages
+  OS << "  " << allKinds << " =  0x"
+     << utohexstr(((1 << shiftVal) - 1), false, 0) << "\n";
+  OS << "}; // enum ShaderKind\n\n";
+
+  // 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 OverloadKindCount = PowerOf2Ceil(OverloadKindList.size());
+  OS << "enum OverloadKind : uint" << OverloadKindCount << "_t {\n";
+  OS << "    UNDEFINED = 0,\n";
+  shiftVal = 1;
+  for (auto TyStr : OverloadKindList) {
+    OS << "    " << TyStr << " = 1 << " << shiftVal++ << ",\n";
   }
-  OS << "    .Default(ShaderKind::Unknown);\n";
-  OS << "}\n";
-  OS << "#endif // SHADER_KIND_ENUM \n\n\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 Constraints that encapsulate overload and shader kind
+  // constraints predicated on shader model version, if any.
+  OS << "struct OpConstraints { \n \
+            Version ShaderModelVer; \n";
+  OS << "             uint" << OverloadKindCount << "_t ValidTys; \n";
+  OS << "             uint" << ShaderKindCount << "_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<OpConstraints> Constraints; \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::UNDEFINED:  \n \
+      return \"void\";  \n \
+    case OverloadKind::ObjectType: \n \
+    case OverloadKind::UserDefinedType: \n \
+      break; \n \
+    } \n \
+    llvm_unreachable(\"invalid overload type for name\"); \n \
+  }\n\n";
 }
 
 /// Entry function call that invokes the functionality of this TableGen backend
@@ -686,7 +680,6 @@ static void emitShaderKindEnums(RecordKeeper &Records, raw_ostream &OS) {
 static void EmitDXILOperation(RecordKeeper &Records, raw_ostream &OS) {
   OS << "// Generated code, do not edit.\n";
   OS << "\n";
-  emitShaderKindEnums(Records, OS);
   // Get all DXIL Ops property records
   std::vector<Record *> OpIntrProps =
       Records.getAllDerivedDefinitions("DXILOp");
@@ -696,7 +689,10 @@ static void EmitDXILOperation(RecordKeeper &Records, raw_ostream &OS) {
   }
   emitDXILEnums(DXILOps, OS);
   emitDXILIntrinsicMap(DXILOps, OS);
+  OS << "#ifdef DXIL_OP_OPERATION_TABLE\n";
+  emitDXILOperationTableDataStructs(Records, OS);
   emitDXILOperationTable(DXILOps, OS);
+  OS << "#endif // DXIL_OP_OPERATION_TABLE\n";
 }
 
 static TableGen::Emitter::Opt X("gen-dxil-operation", EmitDXILOperation,

>From 9b0f40e6488f891a9a6bc40aa740be59b8ee87d3 Mon Sep 17 00:00:00 2001
From: Bharadwaj Yadavalli <Bharadwaj.Yadavalli at microsoft.com>
Date: Fri, 12 Jul 2024 14:39:03 +0000
Subject: [PATCH 07/12] Delete unused code snippet

---
 llvm/lib/Target/DirectX/DXILOpBuilder.cpp | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
index 4384eec0184bb..5d66f6836feb8 100644
--- a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
@@ -342,16 +342,6 @@ CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode, Type *ReturnTy,
 
 Type *DXILOpBuilder::getOverloadType(dxil::OpCode OpCode, FunctionType *FT) {
 
-  std::string TTStr = M.getTargetTriple();
-  // No extra checks need be performed to verify that the Triple is
-  // well-formed or 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.
-  auto Major = Triple(TTStr).getOSVersion().getMajor();
-  auto MinorOrErr = Triple(TTStr).getOSVersion().getMinor();
-  uint32_t Minor = MinorOrErr.has_value() ? *MinorOrErr : 0;
-  VersionTuple SMVer(Major, Minor);
-
   const OpCodeProperty *Prop = getOpCodeProperty(OpCode);
   // If DXIL Op has no overload parameter, just return the
   // precise return type specified.

>From ab19613f95c9824145d3f38b8174f8a977362282 Mon Sep 17 00:00:00 2001
From: Bharadwaj Yadavalli <Bharadwaj.Yadavalli at microsoft.com>
Date: Mon, 15 Jul 2024 19:03:55 +0000
Subject: [PATCH 08/12] Revert NFC changes to reduce changeset size.

---
 llvm/lib/Target/DirectX/DXIL.td            |  2 +-
 llvm/lib/Target/DirectX/DXILOpBuilder.cpp  | 10 +++++-----
 llvm/lib/Target/DirectX/DXILOpBuilder.h    |  4 +---
 llvm/lib/Target/DirectX/DXILOpLowering.cpp |  4 +---
 llvm/utils/TableGen/DXILEmitter.cpp        | 20 ++++++++++----------
 5 files changed, 18 insertions(+), 22 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td
index 3f3dac0453ecc..fce945284c2f7 100644
--- a/llvm/lib/Target/DirectX/DXIL.td
+++ b/llvm/lib/Target/DirectX/DXIL.td
@@ -275,7 +275,7 @@ class Stages<list<ShaderStage> st> : Pred {
 }
 
 // Following class represents predicate that evaluates to the payload when
-// specified predicte is true.
+// specified predicate is true.
 
 class Constraints<Pred p, list<Pred> l = []> : Pred {
   Pred pred = p;
diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
index 5d66f6836feb8..2cfb51edaea85 100644
--- a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
@@ -59,7 +59,7 @@ static OverloadKind getOverloadKind(Type *Ty) {
     }
   }
   case Type::PointerTyID:
-    return OverloadKind::UserDefinedType;
+    return OverloadKind::UserDefineType;
   case Type::StructTyID:
     return OverloadKind::ObjectType;
   default:
@@ -69,9 +69,9 @@ static OverloadKind getOverloadKind(Type *Ty) {
 }
 
 static std::string getTypeName(OverloadKind Kind, Type *Ty) {
-  if (Kind < OverloadKind::UserDefinedType) {
+  if (Kind < OverloadKind::UserDefineType) {
     return getOverloadTypeName(Kind);
-  } else if (Kind == OverloadKind::UserDefinedType) {
+  } else if (Kind == OverloadKind::UserDefineType) {
     StructType *ST = cast<StructType>(Ty);
     return ST->getStructName().str();
   } else if (Kind == OverloadKind::ObjectType) {
@@ -100,7 +100,7 @@ static std::string constructOverloadTypeName(OverloadKind Kind,
   if (Kind == OverloadKind::VOID)
     return TypeName.str();
 
-  assert(Kind < OverloadKind::UserDefinedType && "invalid overload kind");
+  assert(Kind < OverloadKind::UserDefineType && "invalid overload kind");
   return (Twine(TypeName) + getOverloadTypeName(Kind)).str();
 }
 
@@ -340,7 +340,7 @@ CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode, Type *ReturnTy,
   return B.CreateCall(DXILFn, Args);
 }
 
-Type *DXILOpBuilder::getOverloadType(dxil::OpCode OpCode, FunctionType *FT) {
+Type *DXILOpBuilder::getOverloadTy(dxil::OpCode OpCode, FunctionType *FT) {
 
   const OpCodeProperty *Prop = getOpCodeProperty(OpCode);
   // If DXIL Op has no overload parameter, just return the
diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.h b/llvm/lib/Target/DirectX/DXILOpBuilder.h
index 584770a8a3a56..6c2801df8d891 100644
--- a/llvm/lib/Target/DirectX/DXILOpBuilder.h
+++ b/llvm/lib/Target/DirectX/DXILOpBuilder.h
@@ -14,8 +14,6 @@
 
 #include "DXILConstants.h"
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/DXILABI.h"
-#include "llvm/Support/VersionTuple.h"
 namespace llvm {
 class Module;
 class IRBuilderBase;
@@ -43,7 +41,7 @@ class DXILOpBuilder {
   CallInst *createDXILOpCall(dxil::OpCode OpCode, Type *ReturnTy,
                              Type *OverloadTy, SmallVector<Value *> Args);
 
-  Type *getOverloadType(dxil::OpCode OpCode, FunctionType *FT);
+  Type *getOverloadTy(dxil::OpCode OpCode, 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 7b098d6a6b39c..1329308ffec26 100644
--- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
@@ -22,10 +22,8 @@
 #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 <string>
 
 #define DEBUG_TYPE "dxil-op-lower"
 
@@ -77,7 +75,7 @@ static SmallVector<Value *> argVectorFlatten(CallInst *Orig,
 static void lowerIntrinsic(dxil::OpCode DXILOp, Function &F, Module &M) {
   IRBuilder<> B(M.getContext());
   DXILOpBuilder DXILB(M, B);
-  Type *OverloadTy = DXILB.getOverloadType(DXILOp, F.getFunctionType());
+  Type *OverloadTy = DXILB.getOverloadTy(DXILOp, F.getFunctionType());
   for (User *U : make_early_inc_range(F.users())) {
     CallInst *CI = dyn_cast<CallInst>(U);
     if (!CI)
diff --git a/llvm/utils/TableGen/DXILEmitter.cpp b/llvm/utils/TableGen/DXILEmitter.cpp
index e86b44a92d270..c9da631e1abcc 100644
--- a/llvm/utils/TableGen/DXILEmitter.cpp
+++ b/llvm/utils/TableGen/DXILEmitter.cpp
@@ -25,6 +25,7 @@
 #include "llvm/TableGen/Record.h"
 #include "llvm/TableGen/TableGenBackend.h"
 
+#include <cstddef>
 #include <string>
 #include <vector>
 
@@ -108,7 +109,7 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) {
   for (auto Ty : ArgTys) {
     ParamTypeRecs.push_back(Ty);
   }
-  unsigned ParamTypeRecsSize = ParamTypeRecs.size();
+  size_t ParamTypeRecsSize = ParamTypeRecs.size();
   // Populate OpTypes with return type and parameter types
 
   // Parameter indices of overloaded parameters.
@@ -120,23 +121,23 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) {
   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) {
-      // TODO: At present it is expected that all overload types in a DXIL Op
+    auto isAny = TR->getValueAsInt("isAny");
+    if (isAny == 1) {
+      // 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 != ParamTypeRecs[Idx]) {
-            KnownType = false;
+            knownType = false;
             break;
           }
         }
-        assert(KnownType && "Specification of multiple differing overload "
+        assert(knownType && "Specification of multiple differing overload "
                             "parameter types not yet supported");
       } else {
         OverloadParamIndices.push_back(I);
@@ -506,7 +507,6 @@ static void emitDXILOperationTable(std::vector<DXILOperationDesc> &Ops,
        << Op.OverloadParamIndex << ", " << Op.OpTypes.size() - 1 << ", "
        << Parameters.get(ParameterMap[Op.OpClass]) << " }";
     Prefix = ",\n";
-    // OS << "\n// " << getConstraintString(Op.Constraints) << "\n";
   }
   OS << "  };\n";
 
@@ -599,7 +599,7 @@ static void emitDXILOperationTableDataStructs(RecordKeeper &Records,
   // Emit enum OverloadKind with valid overload types.
   const SmallVector<std::string> OverloadKindList = {
       "VOID", "HALF", "FLOAT", "DOUBLE",          "I1",        "I8",
-      "I16",  "I32",  "I64",   "UserDefinedType", "ObjectType"};
+      "I16",  "I32",  "I64",   "UserDefineType", "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
@@ -667,7 +667,7 @@ static void emitDXILOperationTableDataStructs(RecordKeeper &Records,
     case OverloadKind::UNDEFINED:  \n \
       return \"void\";  \n \
     case OverloadKind::ObjectType: \n \
-    case OverloadKind::UserDefinedType: \n \
+    case OverloadKind::UserDefineType: \n \
       break; \n \
     } \n \
     llvm_unreachable(\"invalid overload type for name\"); \n \

>From ecb8d1e4f9db95960ed093289fceb27daa531aa4 Mon Sep 17 00:00:00 2001
From: Bharadwaj Yadavalli <Bharadwaj.Yadavalli at microsoft.com>
Date: Mon, 15 Jul 2024 19:55:39 +0000
Subject: [PATCH 09/12] Declare and use TableGen class DXILAttribute instead of
 class Pred to define DXIL attributes

---
 llvm/lib/Target/DirectX/DXIL.td | 27 +++++++++++++++------------
 1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td
index fce945284c2f7..2a160e9323684 100644
--- a/llvm/lib/Target/DirectX/DXIL.td
+++ b/llvm/lib/Target/DirectX/DXIL.td
@@ -248,17 +248,6 @@ class Pred;
 // Following classes represent predicate that evaluate to the payload,
 // if one xists, unconditionally.
 
-// DXIL Op attributes defined as true predicates, if specified
-
-def ReadOnly : Pred;
-def ReadNone : Pred;
-def IsDerivative : Pred;
-def IsGradient : Pred;
-def IsFeedback : Pred;
-def IsWave : Pred;
-def NeedsUniformInputs : Pred;
-def IsBarrier : Pred;
-
 // Predicate that evaluates to specified shader model version unconditionally.
 class SMVersion<Version ver> : Pred {
   Version sm_version = ver;
@@ -282,6 +271,20 @@ class Constraints<Pred p, list<Pred> l = []> : Pred {
   list<Pred> constraints = l;
 }
 
+// DXIL Op attributes defined as true predicates, if specified
+
+class DXILAttribute;
+
+def ReadOnly : DXILAttribute;
+def ReadNone : DXILAttribute;
+def IsDerivative : DXILAttribute;
+def IsGradient : DXILAttribute;
+def IsFeedback : DXILAttribute;
+def IsWave : DXILAttribute;
+def NeedsUniformInputs : DXILAttribute;
+def IsBarrier : DXILAttribute;
+
+
 // Marker used to identify attribute list.
 def attrs;
 
@@ -317,7 +320,7 @@ class DXILOp {
   list<Constraints> constraints = [];
 
   // Operation attributes
-  list<Pred> attributes = [];
+  list<DXILAttribute> attributes = [];
 
   Version DXILVersion = ? ;
 }

>From 1c49dd0c02cb8c0b45b73aadf2df21790ebe1197 Mon Sep 17 00:00:00 2001
From: Bharadwaj Yadavalli <Bharadwaj.Yadavalli at microsoft.com>
Date: Mon, 15 Jul 2024 23:54:10 +0000
Subject: [PATCH 10/12] Bug fix

---
 llvm/lib/Target/DirectX/DXIL.td     | 2 +-
 llvm/utils/TableGen/DXILEmitter.cpp | 7 ++++---
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td
index 2a160e9323684..1fd9f80f46e89 100644
--- a/llvm/lib/Target/DirectX/DXIL.td
+++ b/llvm/lib/Target/DirectX/DXIL.td
@@ -309,7 +309,7 @@ class DXILOp {
   list<LLVMType> result = [];
 
   // List of constraints predicated on Shader Model version.
-  // If no contraints are specified,
+  // If no constraints are specified,
   // a) operation is assumed to be supported in Shader Model 6.0 and later.
   // b) has no overload types
   // c) is supported in all shader stage kinds
diff --git a/llvm/utils/TableGen/DXILEmitter.cpp b/llvm/utils/TableGen/DXILEmitter.cpp
index c9da631e1abcc..1aa255a6d61c6 100644
--- a/llvm/utils/TableGen/DXILEmitter.cpp
+++ b/llvm/utils/TableGen/DXILEmitter.cpp
@@ -299,14 +299,14 @@ static std::string getOverloadKindStr(const Record *R) {
 static std::string getConstraintString(const SmallVector<Record *> Recs) {
   std::string ConstraintString = "";
   std::string Prefix = "";
-  ConstraintString.append("{{");
+  ConstraintString.append("{");
   // If no constraints were specified, assume the operation
   // a) to be supported in SM 6.0 and later
   // b) has no overload types
   // c) is supported in all shader stage kinds
   if (Recs.empty()) {
     ConstraintString.append(
-        "{6, 0}, OverloadKind::UNDEFINED, ShaderKind::allKinds}");
+        "{{6, 0}, OverloadKind::UNDEFINED, ShaderKind::allKinds}}");
   }
   for (auto ConstrRec : Recs) {
     auto SMConstrRec = ConstrRec->getValueAsDef("pred");
@@ -314,7 +314,7 @@ static std::string getConstraintString(const SmallVector<Record *> Recs) {
         SMConstrRec->getValueAsDef("sm_version")->getValueAsInt("Major");
     unsigned Minor =
         SMConstrRec->getValueAsDef("sm_version")->getValueAsInt("Minor");
-    ConstraintString.append("{")
+    ConstraintString.append(Prefix).append("{{")
         .append(std::to_string(Major))
         .append(", ")
         .append(std::to_string(Minor).append("}, "));
@@ -364,6 +364,7 @@ static std::string getConstraintString(const SmallVector<Record *> Recs) {
         .append(", ")
         .append(StageMaskString);
     ConstraintString.append("}");
+    Prefix = ", ";
   }
   ConstraintString.append("}");
   return ConstraintString;

>From 17a9fe1d526d50adfa3c0d2ee63e36ba7f535f9c Mon Sep 17 00:00:00 2001
From: Bharadwaj Yadavalli <Bharadwaj.Yadavalli at microsoft.com>
Date: Tue, 16 Jul 2024 21:41:03 +0000
Subject: [PATCH 11/12] Changes in accordance with the latest update to design
 document for TableGen specification of DXIL Operations.

---
 llvm/lib/Target/DirectX/DXIL.td               | 996 ++++++++----------
 llvm/lib/Target/DirectX/DXILOpBuilder.cpp     | 164 ++-
 llvm/lib/Target/DirectX/DXILOpBuilder.h       |   5 +-
 .../CodeGen/DirectX/sin_no_stage_error.ll     |   2 +-
 llvm/utils/TableGen/DXILEmitter.cpp           | 433 ++++----
 5 files changed, 783 insertions(+), 817 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td
index 1fd9f80f46e89..b1496feba28f1 100644
--- a/llvm/lib/Target/DirectX/DXIL.td
+++ b/llvm/lib/Target/DirectX/DXIL.td
@@ -19,259 +19,244 @@ class Version<int major, int minor> {
   int Minor = minor;
 }
 
-// Valid Shader model version records
-
-// Shader Model 6.0 - 6.8 and DXIL Version 1.0 - 1.8
+// Valid DXIL Version records
 foreach i = 0...8 in {
-  def SM6_ #i : Version<6, i>;
-  def DX1_ #i : Version<1, i>;
+  def DXIL1_ #i : Version<1, i>;
 }
 
 // Overload type alias of llvm_any_ty
-defvar dxil_overload_ty = 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;
+defvar anyfloatTy = llvm_anyfloat_ty;
 
 class DXILOpClass;
 
-// Concrete definitions of DXIL Op Classes
-def acceptHitAndEndSearch : DXILOpClass;
-def allocateNodeOutputRecords : DXILOpClass;
-def allocateRayQuery : DXILOpClass;
-def annotateHandle : DXILOpClass;
-def annotateNodeHandle : DXILOpClass;
-def annotateNodeRecordHandle : DXILOpClass;
-def atomicBinOp : DXILOpClass;
-def atomicCompareExchange : DXILOpClass;
-def attributeAtVertex : DXILOpClass;
-def barrier : DXILOpClass;
-def barrierByMemoryHandle : DXILOpClass;
-def barrierByMemoryType : DXILOpClass;
-def barrierByNodeRecordHandle : DXILOpClass;
-def binary : DXILOpClass;
-def binaryWithCarryOrBorrow : DXILOpClass;
-def binaryWithTwoOuts : DXILOpClass;
-def bitcastF16toI16 : DXILOpClass;
-def bitcastF32toI32 : DXILOpClass;
-def bitcastF64toI64 : DXILOpClass;
-def bitcastI16toF16 : DXILOpClass;
-def bitcastI32toF32 : DXILOpClass;
-def bitcastI64toF64 : DXILOpClass;
-def bufferLoad : DXILOpClass;
-def bufferStore : DXILOpClass;
-def bufferUpdateCounter : DXILOpClass;
-def calculateLOD : DXILOpClass;
-def callShader : DXILOpClass;
-def cbufferLoad : DXILOpClass;
-def cbufferLoadLegacy : DXILOpClass;
-def checkAccessFullyMapped : DXILOpClass;
-def coverage : DXILOpClass;
-def createHandle : DXILOpClass;
-def createHandleForLib : DXILOpClass;
-def createHandleFromBinding : DXILOpClass;
-def createHandleFromHeap : DXILOpClass;
-def createNodeInputRecordHandle : DXILOpClass;
-def createNodeOutputHandle : DXILOpClass;
-def cutStream : DXILOpClass;
-def cycleCounterLegacy : DXILOpClass;
-def discard : DXILOpClass;
-def dispatchMesh : DXILOpClass;
-def dispatchRaysDimensions : DXILOpClass;
-def dispatchRaysIndex : DXILOpClass;
-def domainLocation : DXILOpClass;
-def dot2 : DXILOpClass;
-def dot2AddHalf : DXILOpClass;
-def dot3 : DXILOpClass;
-def dot4 : DXILOpClass;
-def dot4AddPacked : DXILOpClass;
-def emitIndices : DXILOpClass;
-def emitStream : DXILOpClass;
-def emitThenCutStream : DXILOpClass;
-def evalCentroid : DXILOpClass;
-def evalSampleIndex : DXILOpClass;
-def evalSnapped : DXILOpClass;
-def finishedCrossGroupSharing : DXILOpClass;
-def flattenedThreadIdInGroup : DXILOpClass;
-def geometryIndex : DXILOpClass;
-def getDimensions : DXILOpClass;
-def getInputRecordCount : DXILOpClass;
-def getMeshPayload : DXILOpClass;
-def getNodeRecordPtr : DXILOpClass;
-def getRemainingRecursionLevels : DXILOpClass;
-def groupId : DXILOpClass;
-def gsInstanceID : DXILOpClass;
-def hitKind : DXILOpClass;
-def ignoreHit : DXILOpClass;
-def incrementOutputCount : DXILOpClass;
-def indexNodeHandle : DXILOpClass;
-def innerCoverage : DXILOpClass;
-def instanceID : DXILOpClass;
-def instanceIndex : DXILOpClass;
-def isHelperLane : DXILOpClass;
-def isSpecialFloat : DXILOpClass;
-def legacyDoubleToFloat : DXILOpClass;
-def legacyDoubleToSInt32 : DXILOpClass;
-def legacyDoubleToUInt32 : DXILOpClass;
-def legacyF16ToF32 : DXILOpClass;
-def legacyF32ToF16 : DXILOpClass;
-def loadInput : DXILOpClass;
-def loadOutputControlPoint : DXILOpClass;
-def loadPatchConstant : DXILOpClass;
-def makeDouble : DXILOpClass;
-def minPrecXRegLoad : DXILOpClass;
-def minPrecXRegStore : DXILOpClass;
-def nodeOutputIsValid : DXILOpClass;
-def objectRayDirection : DXILOpClass;
-def objectRayOrigin : DXILOpClass;
-def objectToWorld : DXILOpClass;
-def outputComplete : DXILOpClass;
-def outputControlPointID : DXILOpClass;
-def pack4x8 : DXILOpClass;
-def primitiveID : DXILOpClass;
-def primitiveIndex : DXILOpClass;
-def quadOp : DXILOpClass;
-def quadReadLaneAt : DXILOpClass;
-def quadVote : DXILOpClass;
-def quaternary : DXILOpClass;
-def rawBufferLoad : DXILOpClass;
-def rawBufferStore : DXILOpClass;
-def rayFlags : DXILOpClass;
-def rayQuery_Abort : DXILOpClass;
-def rayQuery_CommitNonOpaqueTriangleHit : DXILOpClass;
-def rayQuery_CommitProceduralPrimitiveHit : DXILOpClass;
-def rayQuery_Proceed : DXILOpClass;
-def rayQuery_StateMatrix : DXILOpClass;
-def rayQuery_StateScalar : DXILOpClass;
-def rayQuery_StateVector : DXILOpClass;
-def rayQuery_TraceRayInline : DXILOpClass;
-def rayTCurrent : DXILOpClass;
-def rayTMin : DXILOpClass;
-def renderTargetGetSampleCount : DXILOpClass;
-def renderTargetGetSamplePosition : DXILOpClass;
-def reportHit : DXILOpClass;
-def sample : DXILOpClass;
-def sampleBias : DXILOpClass;
-def sampleCmp : DXILOpClass;
-def sampleCmpBias : DXILOpClass;
-def sampleCmpGrad : DXILOpClass;
-def sampleCmpLevel : DXILOpClass;
-def sampleCmpLevelZero : DXILOpClass;
-def sampleGrad : DXILOpClass;
-def sampleIndex : DXILOpClass;
-def sampleLevel : DXILOpClass;
-def setMeshOutputCounts : DXILOpClass;
-def splitDouble : DXILOpClass;
-def startInstanceLocation : DXILOpClass;
-def startVertexLocation : DXILOpClass;
-def storeOutput : DXILOpClass;
-def storePatchConstant : DXILOpClass;
-def storePrimitiveOutput : DXILOpClass;
-def storeVertexOutput : DXILOpClass;
-def tempRegLoad : DXILOpClass;
-def tempRegStore : DXILOpClass;
-def tertiary : DXILOpClass;
-def texture2DMSGetSamplePosition : DXILOpClass;
-def textureGather : DXILOpClass;
-def textureGatherCmp : DXILOpClass;
-def textureGatherRaw : DXILOpClass;
-def textureLoad : DXILOpClass;
-def textureStore : DXILOpClass;
-def textureStoreSample : DXILOpClass;
-def threadId : DXILOpClass;
-def threadIdInGroup : DXILOpClass;
-def traceRay : DXILOpClass;
-def unary : DXILOpClass;
-def unaryBits : DXILOpClass;
-def unpack4x8 : DXILOpClass;
-def viewID : DXILOpClass;
-def waveActiveAllEqual : DXILOpClass;
-def waveActiveBallot : DXILOpClass;
-def waveActiveBit : DXILOpClass;
-def waveActiveOp : DXILOpClass;
-def waveAllOp : DXILOpClass;
-def waveAllTrue : DXILOpClass;
-def waveAnyTrue : DXILOpClass;
-def waveGetLaneCount : DXILOpClass;
-def waveGetLaneIndex : DXILOpClass;
-def waveIsFirstLane : DXILOpClass;
-def waveMatch : DXILOpClass;
-def waveMatrix_Accumulate : DXILOpClass;
-def waveMatrix_Annotate : DXILOpClass;
-def waveMatrix_Depth : DXILOpClass;
-def waveMatrix_Fill : DXILOpClass;
-def waveMatrix_LoadGroupShared : DXILOpClass;
-def waveMatrix_LoadRawBuf : DXILOpClass;
-def waveMatrix_Multiply : DXILOpClass;
-def waveMatrix_ScalarOp : DXILOpClass;
-def waveMatrix_StoreGroupShared : DXILOpClass;
-def waveMatrix_StoreRawBuf : DXILOpClass;
-def waveMultiPrefixBitCount : DXILOpClass;
-def waveMultiPrefixOp : DXILOpClass;
-def wavePrefixOp : DXILOpClass;
-def waveReadLaneAt : DXILOpClass;
-def waveReadLaneFirst : DXILOpClass;
-def worldRayDirection : DXILOpClass;
-def worldRayOrigin : DXILOpClass;
-def worldToObject : DXILOpClass;
-def writeSamplerFeedback : DXILOpClass;
-def writeSamplerFeedbackBias : DXILOpClass;
-def writeSamplerFeedbackGrad : DXILOpClass;
-def writeSamplerFeedbackLevel : DXILOpClass;
-
-// This is a sentinel definition. Hence placed at the end here
-// and not as part of the above alphabetically sorted valid definitions.
-// It is never used to construct the name of DXIL Op call name.
-// Additionally it is capitalized unlike all the others.
-def UnknownOpClass : DXILOpClass;
-
-// Shader stages
-class ShaderStage;
-
-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 anyhit : ShaderStage;
-def closesthit : ShaderStage;
-def callable : ShaderStage;
-def miss : ShaderStage;
-
-// Primitive predicate
-class Pred;
-
-// Following classes represent predicate that evaluate to the payload,
-// if one xists, unconditionally.
-
-// Predicate that evaluates to specified shader model version unconditionally.
-class SMVersion<Version ver> : Pred {
-  Version sm_version = ver;
-}
-
-// Predicate that evaluates to specified overload type list unconditionally.
-class Overloads<list<LLVMType> tys> : Pred {
-  list<LLVMType> overload_types = tys;
-}
-
-// Predicate that evaluates to specified list of shader stages unconditionally.
-class Stages<list<ShaderStage> st> : Pred {
-  list<ShaderStage> stage_kinds = st;
-}
-
-// Following class represents predicate that evaluates to the payload when
-// specified predicate is true.
-
-class Constraints<Pred p, list<Pred> l = []> : Pred {
-  Pred pred = p;
-  list<Pred> constraints = l;
-}
-
-// DXIL Op attributes defined as true predicates, if specified
+defset list<DXILOpClass> OpClasses = {
+  def acceptHitAndEndSearch : DXILOpClass;
+  def allocateNodeOutputRecords : DXILOpClass;
+  def allocateRayQuery : DXILOpClass;
+  def annotateHandle : DXILOpClass;
+  def annotateNodeHandle : DXILOpClass;
+  def annotateNodeRecordHandle : DXILOpClass;
+  def atomicBinOp : DXILOpClass;
+  def atomicCompareExchange : DXILOpClass;
+  def attributeAtVertex : DXILOpClass;
+  def barrier : DXILOpClass;
+  def barrierByMemoryHandle : DXILOpClass;
+  def barrierByMemoryType : DXILOpClass;
+  def barrierByNodeRecordHandle : DXILOpClass;
+  def binary : DXILOpClass;
+  def binaryWithCarryOrBorrow : DXILOpClass;
+  def binaryWithTwoOuts : DXILOpClass;
+  def bitcastF16toI16 : DXILOpClass;
+  def bitcastF32toI32 : DXILOpClass;
+  def bitcastF64toI64 : DXILOpClass;
+  def bitcastI16toF16 : DXILOpClass;
+  def bitcastI32toF32 : DXILOpClass;
+  def bitcastI64toF64 : DXILOpClass;
+  def bufferLoad : DXILOpClass;
+  def bufferStore : DXILOpClass;
+  def bufferUpdateCounter : DXILOpClass;
+  def calculateLOD : DXILOpClass;
+  def callShader : DXILOpClass;
+  def cbufferLoad : DXILOpClass;
+  def cbufferLoadLegacy : DXILOpClass;
+  def checkAccessFullyMapped : DXILOpClass;
+  def coverage : DXILOpClass;
+  def createHandle : DXILOpClass;
+  def createHandleForLib : DXILOpClass;
+  def createHandleFromBinding : DXILOpClass;
+  def createHandleFromHeap : DXILOpClass;
+  def createNodeInputRecordHandle : DXILOpClass;
+  def createNodeOutputHandle : DXILOpClass;
+  def cutStream : DXILOpClass;
+  def cycleCounterLegacy : DXILOpClass;
+  def discard : DXILOpClass;
+  def dispatchMesh : DXILOpClass;
+  def dispatchRaysDimensions : DXILOpClass;
+  def dispatchRaysIndex : DXILOpClass;
+  def domainLocation : DXILOpClass;
+  def dot2 : DXILOpClass;
+  def dot2AddHalf : DXILOpClass;
+  def dot3 : DXILOpClass;
+  def dot4 : DXILOpClass;
+  def dot4AddPacked : DXILOpClass;
+  def emitIndices : DXILOpClass;
+  def emitStream : DXILOpClass;
+  def emitThenCutStream : DXILOpClass;
+  def evalCentroid : DXILOpClass;
+  def evalSampleIndex : DXILOpClass;
+  def evalSnapped : DXILOpClass;
+  def finishedCrossGroupSharing : DXILOpClass;
+  def flattenedThreadIdInGroup : DXILOpClass;
+  def geometryIndex : DXILOpClass;
+  def getDimensions : DXILOpClass;
+  def getInputRecordCount : DXILOpClass;
+  def getMeshPayload : DXILOpClass;
+  def getNodeRecordPtr : DXILOpClass;
+  def getRemainingRecursionLevels : DXILOpClass;
+  def groupId : DXILOpClass;
+  def gsInstanceID : DXILOpClass;
+  def hitKind : DXILOpClass;
+  def ignoreHit : DXILOpClass;
+  def incrementOutputCount : DXILOpClass;
+  def indexNodeHandle : DXILOpClass;
+  def innerCoverage : DXILOpClass;
+  def instanceID : DXILOpClass;
+  def instanceIndex : DXILOpClass;
+  def isHelperLane : DXILOpClass;
+  def isSpecialFloat : DXILOpClass;
+  def legacyDoubleToFloat : DXILOpClass;
+  def legacyDoubleToSInt32 : DXILOpClass;
+  def legacyDoubleToUInt32 : DXILOpClass;
+  def legacyF16ToF32 : DXILOpClass;
+  def legacyF32ToF16 : DXILOpClass;
+  def loadInput : DXILOpClass;
+  def loadOutputControlPoint : DXILOpClass;
+  def loadPatchConstant : DXILOpClass;
+  def makeDouble : DXILOpClass;
+  def minPrecXRegLoad : DXILOpClass;
+  def minPrecXRegStore : DXILOpClass;
+  def nodeOutputIsValid : DXILOpClass;
+  def objectRayDirection : DXILOpClass;
+  def objectRayOrigin : DXILOpClass;
+  def objectToWorld : DXILOpClass;
+  def outputComplete : DXILOpClass;
+  def outputControlPointID : DXILOpClass;
+  def pack4x8 : DXILOpClass;
+  def primitiveID : DXILOpClass;
+  def primitiveIndex : DXILOpClass;
+  def quadOp : DXILOpClass;
+  def quadReadLaneAt : DXILOpClass;
+  def quadVote : DXILOpClass;
+  def quaternary : DXILOpClass;
+  def rawBufferLoad : DXILOpClass;
+  def rawBufferStore : DXILOpClass;
+  def rayFlags : DXILOpClass;
+  def rayQuery_Abort : DXILOpClass;
+  def rayQuery_CommitNonOpaqueTriangleHit : DXILOpClass;
+  def rayQuery_CommitProceduralPrimitiveHit : DXILOpClass;
+  def rayQuery_Proceed : DXILOpClass;
+  def rayQuery_StateMatrix : DXILOpClass;
+  def rayQuery_StateScalar : DXILOpClass;
+  def rayQuery_StateVector : DXILOpClass;
+  def rayQuery_TraceRayInline : DXILOpClass;
+  def rayTCurrent : DXILOpClass;
+  def rayTMin : DXILOpClass;
+  def renderTargetGetSampleCount : DXILOpClass;
+  def renderTargetGetSamplePosition : DXILOpClass;
+  def reportHit : DXILOpClass;
+  def sample : DXILOpClass;
+  def sampleBias : DXILOpClass;
+  def sampleCmp : DXILOpClass;
+  def sampleCmpBias : DXILOpClass;
+  def sampleCmpGrad : DXILOpClass;
+  def sampleCmpLevel : DXILOpClass;
+  def sampleCmpLevelZero : DXILOpClass;
+  def sampleGrad : DXILOpClass;
+  def sampleIndex : DXILOpClass;
+  def sampleLevel : DXILOpClass;
+  def setMeshOutputCounts : DXILOpClass;
+  def splitDouble : DXILOpClass;
+  def startInstanceLocation : DXILOpClass;
+  def startVertexLocation : DXILOpClass;
+  def storeOutput : DXILOpClass;
+  def storePatchConstant : DXILOpClass;
+  def storePrimitiveOutput : DXILOpClass;
+  def storeVertexOutput : DXILOpClass;
+  def tempRegLoad : DXILOpClass;
+  def tempRegStore : DXILOpClass;
+  def tertiary : DXILOpClass;
+  def texture2DMSGetSamplePosition : DXILOpClass;
+  def textureGather : DXILOpClass;
+  def textureGatherCmp : DXILOpClass;
+  def textureGatherRaw : DXILOpClass;
+  def textureLoad : DXILOpClass;
+  def textureStore : DXILOpClass;
+  def textureStoreSample : DXILOpClass;
+  def threadId : DXILOpClass;
+  def threadIdInGroup : DXILOpClass;
+  def traceRay : DXILOpClass;
+  def unary : DXILOpClass;
+  def unaryBits : DXILOpClass;
+  def unpack4x8 : DXILOpClass;
+  def viewID : DXILOpClass;
+  def waveActiveAllEqual : DXILOpClass;
+  def waveActiveBallot : DXILOpClass;
+  def waveActiveBit : DXILOpClass;
+  def waveActiveOp : DXILOpClass;
+  def waveAllOp : DXILOpClass;
+  def waveAllTrue : DXILOpClass;
+  def waveAnyTrue : DXILOpClass;
+  def waveGetLaneCount : DXILOpClass;
+  def waveGetLaneIndex : DXILOpClass;
+  def waveIsFirstLane : DXILOpClass;
+  def waveMatch : DXILOpClass;
+  def waveMatrix_Accumulate : DXILOpClass;
+  def waveMatrix_Annotate : DXILOpClass;
+  def waveMatrix_Depth : DXILOpClass;
+  def waveMatrix_Fill : DXILOpClass;
+  def waveMatrix_LoadGroupShared : DXILOpClass;
+  def waveMatrix_LoadRawBuf : DXILOpClass;
+  def waveMatrix_Multiply : DXILOpClass;
+  def waveMatrix_ScalarOp : DXILOpClass;
+  def waveMatrix_StoreGroupShared : DXILOpClass;
+  def waveMatrix_StoreRawBuf : DXILOpClass;
+  def waveMultiPrefixBitCount : DXILOpClass;
+  def waveMultiPrefixOp : DXILOpClass;
+  def wavePrefixOp : DXILOpClass;
+  def waveReadLaneAt : DXILOpClass;
+  def waveReadLaneFirst : DXILOpClass;
+  def worldRayDirection : DXILOpClass;
+  def worldRayOrigin : DXILOpClass;
+  def worldToObject : DXILOpClass;
+  def writeSamplerFeedback : DXILOpClass;
+  def writeSamplerFeedbackBias : DXILOpClass;
+  def writeSamplerFeedbackGrad : DXILOpClass;
+  def writeSamplerFeedbackLevel: DXILOpClass;
+
+  // This is a sentinel definition. Hence placed at the end here and
+  // not as part of the above alphabetically sorted valid definitions.
+  // It is never used to construct the name of DXIL Op call name.
+  // Additionally it is capitalized unlike all the others.
+  def UnknownOpClass : DXILOpClass;
+}
+
+class DXILShaderStage;
+
+def compute : DXILShaderStage;
+def domain : DXILShaderStage;
+def hull : DXILShaderStage;
+def pixel : DXILShaderStage;
+def vertex : DXILShaderStage;
+def geometry : DXILShaderStage;
+def library : DXILShaderStage;
+def amplification : DXILShaderStage;
+def mesh : DXILShaderStage;
+def node : DXILShaderStage;
+def raygeneration : DXILShaderStage;
+def intersection : DXILShaderStage;
+def anyhit : DXILShaderStage;
+def closesthit : DXILShaderStage;
+def callable : DXILShaderStage;
+def miss : DXILShaderStage;
+
+// Pseudo-stages
+// Denote DXIL Op to be supported in all stages
+def all_stages : DXILShaderStage;
+// Denote support for DXIL Op to have been removed
+def removed : DXILShaderStage;
+// DXIL Op attributes
 
 class DXILAttribute;
 
@@ -284,509 +269,438 @@ def IsWave : DXILAttribute;
 def NeedsUniformInputs : DXILAttribute;
 def IsBarrier : DXILAttribute;
 
+class Overloads<Version ver, list<LLVMType> ols> {
+  Version dxil_version = ver;
+  list<LLVMType> overload_types = ols;
+}
 
-// Marker used to identify attribute list.
-def attrs;
+class Stages<Version ver, list<DXILShaderStage> st> {
+  Version dxil_version = ver;
+  list<DXILShaderStage> shader_stages = st;
+}
+
+class Attributes<Version ver = DXIL1_0, list<DXILAttribute> attrs> {
+  Version dxil_version = ver;
+  list<DXILAttribute> op_attrs = attrs;
+}
 
 // Abstraction DXIL Operation
-class DXILOp {
+class DXILOp<int opcode, DXILOpClass opclass> {
   // A short description of the operation
   string Doc = "";
 
   // Opcode of DXIL Operation
-  int OpCode = 0;
+  int OpCode = opcode;
 
   // Class of DXIL Operation.
-  DXILOpClass OpClass = UnknownOpClass;
+  DXILOpClass OpClass = opclass;
 
   // LLVM Intrinsic DXIL Operation maps to
-  Intrinsic LLVMIntrinsic = ? ;
+  Intrinsic LLVMIntrinsic = ?;
+
+  // Result type of the op
+  LLVMType result;
 
   // List of argument types of the op. Default to 0 arguments.
   list<LLVMType> arguments = [];
 
-  // List of result types of the op. Default to 0 results.
-  list<LLVMType> result = [];
+  // List of valid overload types predicated by DXIL version
+  list<Overloads> overloads = [];
 
-  // List of constraints predicated on Shader Model version.
-  // If no constraints are specified,
-  // a) operation is assumed to be supported in Shader Model 6.0 and later.
-  // b) has no overload types
-  // c) is supported in all shader stage kinds
-  // If a constraint is specified, Shader Model version on which the
-  // constraint is predicated is mandatory. One or both of the Overload
-  // type and shader kind constraints can be omitted when appropriate.
+  // List of valid shader stages predicated by DXIL version
+  list<Stages> stages;
 
-  list<Constraints> constraints = [];
-
-  // Operation attributes
-  list<DXILAttribute> attributes = [];
-
-  Version DXILVersion = ? ;
-}
-
-// Convenience class for minimal DXIL Op definition
-
-class DXILOpAndClass<int opcode, DXILOpClass opcalss> : DXILOp {
-  int OpCode = opcode;
-  DXILOpClass OpClass = opcalss;
+  // Versioned attributes of operation
+  list<Attributes> attributes = [];
 }
 
 // Concrete definitions of DXIL Operations
 
-def Abs : DXILOpAndClass<6, unary> {
+def Abs :  DXILOp<6, unary> {
   let Doc = "Returns the absolute value of the input.";
   let LLVMIntrinsic = int_fabs;
   let arguments = [LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints =
-      [Constraints<SMVersion<SM6_0>,
-                   [Overloads<[llvm_half_ty, llvm_float_ty, llvm_double_ty]>]>];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy, doubleTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def IsInf : DXILOpAndClass<9, isSpecialFloat> {
+def IsInf :  DXILOp<9, isSpecialFloat> {
   let Doc = "Determines if the specified value is infinite.";
   let LLVMIntrinsic = int_dx_isinf;
-  let arguments = [llvm_anyfloat_ty];
-  let result = [llvm_i1_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let arguments = [anyfloatTy];
+  let result = i1Ty;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def Cos : DXILOpAndClass<12, unary> {
+def Cos :  DXILOp<12, unary> {
   let Doc = "Returns cosine(theta) for theta in radians.";
   let LLVMIntrinsic = int_cos;
   let arguments = [LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def Sin : DXILOpAndClass<13, unary> {
+def Sin :  DXILOp<13, unary> {
   let Doc = "Returns sine(theta) for theta in radians.";
   let LLVMIntrinsic = int_sin;
   let arguments = [LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def Tan : DXILOpAndClass<14, unary> {
+def Tan :  DXILOp<14, unary> {
   let Doc = "Returns tangent(theta) for theta in radians.";
   let LLVMIntrinsic = int_tan;
   let arguments = [LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def ACos : DXILOpAndClass<15, unary> {
+def ACos :  DXILOp<15, unary> {
   let Doc = "Returns the arccosine of the specified value.";
   let LLVMIntrinsic = int_acos;
   let arguments = [LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def ASin : DXILOpAndClass<16, unary> {
+def ASin :  DXILOp<16, unary> {
   let Doc = "Returns the arcsine of the specified value.";
   let LLVMIntrinsic = int_asin;
   let arguments = [LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def ATan : DXILOpAndClass<17, unary> {
+def ATan :  DXILOp<17, unary> {
   let Doc = "Returns the arctangent of the specified value.";
   let LLVMIntrinsic = int_atan;
   let arguments = [LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def HCos : DXILOpAndClass<18, unary> {
+def HCos :  DXILOp<18, unary> {
   let Doc = "Returns the hyperbolic cosine of the specified value.";
   let LLVMIntrinsic = int_cosh;
   let arguments = [LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def HSin : DXILOpAndClass<19, unary> {
+def HSin :  DXILOp<19, unary> {
   let Doc = "Returns the hyperbolic sine of the specified value.";
   let LLVMIntrinsic = int_sinh;
   let arguments = [LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def HTan : DXILOpAndClass<20, unary> {
+def HTan :  DXILOp<20, unary> {
   let Doc = "Returns the hyperbolic tan of the specified value.";
   let LLVMIntrinsic = int_tanh;
   let arguments = [LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def Exp2 : DXILOpAndClass<21, unary> {
+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 = [LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def Frac : DXILOpAndClass<22, unary> {
+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 = [LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def Log2 : DXILOpAndClass<23, unary> {
+def Log2 :  DXILOp<23, unary> {
   let Doc = "Returns the base-2 logarithm of the specified value.";
   let LLVMIntrinsic = int_log2;
   let arguments = [LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def Sqrt : DXILOpAndClass<24, unary> {
+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 = [LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def RSqrt : DXILOpAndClass<25, unary> {
+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 = [LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def Round : DXILOpAndClass<26, unary> {
+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 = [LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def Floor : DXILOpAndClass<27, unary> {
+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 = [LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def Ceil : DXILOpAndClass<28, unary> {
+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 = [LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def Trunc : DXILOpAndClass<29, unary> {
+def Trunc :  DXILOp<29, unary> {
   let Doc = "Returns the specified value truncated to the integer component.";
   let LLVMIntrinsic = int_trunc;
   let arguments = [LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def Rbits : DXILOpAndClass<30, unary> {
+def Rbits :  DXILOp<30, unary> {
   let Doc = "Returns the specified value with its bits reversed.";
   let LLVMIntrinsic = int_bitreverse;
   let arguments = [LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints =
-      [Constraints<SMVersion<SM6_0>,
-                   [Overloads<[llvm_i16_ty, llvm_i32_ty, llvm_i64_ty]>]>];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads =
+      [Overloads<DXIL1_0, [i16Ty, i32Ty, i64Ty]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def FMax : DXILOpAndClass<35, binary> {
+def FMax :  DXILOp<35, binary> {
   let Doc = "Float maximum. FMax(a,b) = a > b ? a : b";
   let LLVMIntrinsic = int_maxnum;
   let arguments = [LLVMMatchType<0>, LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints =
-      [Constraints<SMVersion<SM6_0>,
-                   [Overloads<[llvm_half_ty, llvm_float_ty, llvm_double_ty]>]>];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads =
+      [Overloads<DXIL1_0, [halfTy, floatTy, doubleTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def FMin : DXILOpAndClass<36, binary> {
+def FMin :  DXILOp<36, binary> {
   let Doc = "Float minimum. FMin(a,b) = a < b ? a : b";
   let LLVMIntrinsic = int_minnum;
   let arguments = [LLVMMatchType<0>, LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints =
-      [Constraints<SMVersion<SM6_0>,
-                   [Overloads<[llvm_half_ty, llvm_float_ty, llvm_double_ty]>]>];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads =
+      [Overloads<DXIL1_0, [halfTy, floatTy, doubleTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def SMax : DXILOpAndClass<37, binary> {
+def SMax :  DXILOp<37, binary> {
   let Doc = "Signed integer maximum. SMax(a,b) = a > b ? a : b";
   let LLVMIntrinsic = int_smax;
   let arguments = [LLVMMatchType<0>, LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints =
-      [Constraints<SMVersion<SM6_0>,
-                   [Overloads<[llvm_i16_ty, llvm_i32_ty, llvm_i64_ty]>]>];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads =
+      [Overloads<DXIL1_0, [i16Ty, i32Ty, i64Ty]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def SMin : DXILOpAndClass<38, binary> {
+def SMin :  DXILOp<38, binary> {
   let Doc = "Signed integer minimum. SMin(a,b) = a < b ? a : b";
   let LLVMIntrinsic = int_smin;
   let arguments = [LLVMMatchType<0>, LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints =
-      [Constraints<SMVersion<SM6_0>,
-                   [Overloads<[llvm_i16_ty, llvm_i32_ty, llvm_i64_ty]>]>];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads =
+      [Overloads<DXIL1_0, [i16Ty, i32Ty, i64Ty]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def UMax : DXILOpAndClass<39, binary> {
+def UMax :  DXILOp<39, binary> {
   let Doc = "Unsigned integer maximum. UMax(a,b) = a > b ? a : b";
   let LLVMIntrinsic = int_umax;
   let arguments = [LLVMMatchType<0>, LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints =
-      [Constraints<SMVersion<SM6_0>,
-                   [Overloads<[llvm_i16_ty, llvm_i32_ty, llvm_i64_ty]>]>];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads =
+      [Overloads<DXIL1_0, [i16Ty, i32Ty, i64Ty]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def UMin : DXILOpAndClass<40, binary> {
+def UMin :  DXILOp<40, binary> {
   let Doc = "Unsigned integer minimum. UMin(a,b) = a < b ? a : b";
   let LLVMIntrinsic = int_umin;
   let arguments = [LLVMMatchType<0>, LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints =
-      [Constraints<SMVersion<SM6_0>,
-                   [Overloads<[llvm_i16_ty, llvm_i32_ty, llvm_i64_ty]>]>];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads =
+      [Overloads<DXIL1_0, [i16Ty, i32Ty, i64Ty]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def FMad : DXILOpAndClass<46, tertiary> {
+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 = [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints =
-      [Constraints<SMVersion<SM6_0>,
-                   [Overloads<[llvm_half_ty, llvm_float_ty, llvm_double_ty]>]>];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads =
+      [Overloads<DXIL1_0, [halfTy, floatTy, doubleTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def IMad : DXILOpAndClass<48, tertiary> {
+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 = [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints =
-      [Constraints<SMVersion<SM6_0>,
-                   [Overloads<[llvm_i16_ty, llvm_i32_ty, llvm_i64_ty]>]>];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads =
+      [Overloads<DXIL1_0, [i16Ty, i32Ty, i64Ty]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def UMad : DXILOpAndClass<49, tertiary> {
+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 = [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>];
-  let result = [dxil_overload_ty];
-  let constraints =
-      [Constraints<SMVersion<SM6_0>,
-                   [Overloads<[llvm_i16_ty, llvm_i32_ty, llvm_i64_ty]>]>];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = overloadTy;
+  let overloads =
+      [Overloads<DXIL1_0, [i16Ty, i32Ty, i64Ty]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def Dot2 : DXILOpAndClass<54, dot2> {
+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(llvm_anyfloat_ty, 4);
-  let result = [llvm_anyfloat_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let arguments = !listsplat(anyfloatTy, 4);
+  let result = anyfloatTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def Dot3 : DXILOpAndClass<55, dot3> {
+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(llvm_anyfloat_ty, 6);
-  let result = [llvm_anyfloat_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let arguments = !listsplat(anyfloatTy, 6);
+  let result = anyfloatTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def Dot4 : DXILOpAndClass<56, dot4> {
+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(llvm_anyfloat_ty, 8);
-  let result = [llvm_anyfloat_ty];
-  let constraints = [
-    Constraints<SMVersion<SM6_0>, [Overloads<[llvm_half_ty, llvm_float_ty]>]>
-  ];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let arguments = !listsplat(anyfloatTy, 8);
+  let result = anyfloatTy;
+  let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
+  let stages = [Stages<DXIL1_0, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def ThreadId : DXILOpAndClass<93, threadId> {
+def ThreadId :  DXILOp<93, threadId> {
   let Doc = "Reads the thread ID";
   let LLVMIntrinsic = int_dx_thread_id;
-  let arguments = [llvm_i32_ty];
-  let result = [llvm_i32_ty];
-  let constraints =
-      [Constraints<SMVersion<SM6_0>,
-                   [Stages<[compute, mesh, amplification, node]>]>];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let arguments = [i32Ty];
+  let result = i32Ty;
+  let stages = [Stages<DXIL1_0, [compute, mesh, amplification, node]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def GroupId : DXILOpAndClass<94, groupId> {
+def GroupId :  DXILOp<94, groupId> {
   let Doc = "Reads the group ID (SV_GroupID)";
   let LLVMIntrinsic = int_dx_group_id;
-  let arguments = [llvm_i32_ty];
-  let result = [llvm_i32_ty];
-  let constraints =
-      [Constraints<SMVersion<SM6_0>,
-                   [Stages<[compute, mesh, amplification, node]>]>];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let arguments = [i32Ty];
+  let result = i32Ty;
+  let stages = [Stages<DXIL1_0, [compute, mesh, amplification, node]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def ThreadIdInGroup : DXILOpAndClass<95, threadIdInGroup> {
+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 = [llvm_i32_ty];
-  let result = [llvm_i32_ty];
-  let constraints =
-      [Constraints<SMVersion<SM6_0>,
-                   [Stages<[compute, mesh, amplification, node]>]>];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let arguments = [i32Ty];
+  let result = i32Ty;
+  let stages = [Stages<DXIL1_0, [compute, mesh, amplification, node]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
 
-def FlattenedThreadIdInGroup : DXILOpAndClass<96, flattenedThreadIdInGroup> {
+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 arguments = [llvm_i32_ty];
-  let constraints =
-      [Constraints<SMVersion<SM6_0>,
-                   [Stages<[compute, mesh, amplification, node]>]>];
-  let attributes = [ReadNone];
-  let DXILVersion = DX1_0;
+  let result = i32Ty;
+  let stages = [Stages<DXIL1_0, [compute, mesh, amplification, node]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
index 2cfb51edaea85..bcc39a19924ab 100644
--- a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
@@ -22,11 +22,69 @@ using namespace llvm::dxil;
 
 constexpr StringLiteral DXILOpNamePrefix = "dx.op.";
 
-// Include DXIL Operation data and corresponding access functions
-// generated by the TableGen backend DXILEmitter.
-#define DXIL_OP_OPERATION_TABLE
-#include "DXILOperation.inc"
-#undef DXIL_OP_OPERATION_TABLE
+namespace {
+enum OverloadKind : uint16_t {
+  UNDEFINED = 0,
+  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,
+};
+struct Version {
+  unsigned Major = 0;
+  unsigned Minor = 0;
+};
+
+struct OpOverload {
+  Version DXILVersion;
+  uint16_t ValidTys;
+};
+} // namespace
+
+struct OpStage {
+  Version DXILVersion;
+  uint32_t ValidStages;
+};
+
+struct OpAttribute {
+  Version DXILVersion;
+  uint32_t ValidAttrs;
+};
+
+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::UNDEFINED:
+    return "void";
+  case OverloadKind::ObjectType:
+  case OverloadKind::UserDefineType:
+    break;
+  }
+  llvm_unreachable("invalid overload type for name");
+}
 
 static OverloadKind getOverloadKind(Type *Ty) {
   Type::TypeID T = Ty->getTypeID();
@@ -85,6 +143,29 @@ 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;
+  std::vector<OpOverload> Overloads;
+  std::vector<OpStage> Stages;
+  std::vector<OpAttribute> 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
+// 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) {
@@ -228,21 +309,21 @@ 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->Constraints 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->Constraints.size();
+/// Get index of the property from PropList valid for the most recent
+/// DXIL version not greater than DXILVer.
+/// PropList is expected to be sorted in ascending order of DXIL version.
+template <typename T>
+static int getPropIndex(const std::vector<T> PropList,
+                        const VersionTuple DXILVer) {
+  auto Size = PropList.size();
   for (int I = Size - 1; I >= 0; I--) {
-    auto OL = Prop->Constraints[I];
-    if (VersionTuple(OL.ShaderModelVer.Major, OL.ShaderModelVer.Minor) <=
-        SMVer) {
+    auto OL = PropList[I];
+    if (VersionTuple(OL.DXILVersion.Major, OL.DXILVersion.Minor) <= DXILVer) {
       return I;
     }
   }
   report_fatal_error(
-      StringRef(SMVer.getAsString().append(": Unknown Shader Model Version")),
+      StringRef(DXILVer.getAsString().append(": Unknown DXIL Version")),
       /*gen_crash_diag*/ false);
 
   return -1;
@@ -251,26 +332,27 @@ static int getValidConstraintIndex(const OpCodeProperty *Prop,
 namespace llvm {
 namespace dxil {
 
+// No extra checks on TargetTripleStr need be performed to verify that the
+// 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), TargetTripleStr(M.getTargetTriple()) {}
+
 CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode, Type *ReturnTy,
                                           Type *OverloadTy,
                                           SmallVector<Value *> Args) {
 
-  std::string TTStr = M.getTargetTriple();
-  // No extra checks need be performed to verify that the Triple is
-  // well-formed or 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.
-  auto Major = Triple(TTStr).getOSVersion().getMajor();
-  auto MinorOrErr = Triple(TTStr).getOSVersion().getMinor();
+  auto Major = Triple(TargetTripleStr).getDXILVersion().getMajor();
+  auto MinorOrErr = Triple(TargetTripleStr).getDXILVersion().getMinor();
   uint32_t Minor = MinorOrErr.has_value() ? *MinorOrErr : 0;
-  VersionTuple SMVer(Major, Minor);
+  VersionTuple DXILVer(Major, Minor);
   // Get Shader Stage Kind
-  Triple::EnvironmentType ShaderEnv = Triple(TTStr).getEnvironment();
-  auto ShaderEnvStr = Triple(TTStr).getEnvironmentName();
+  Triple::EnvironmentType ShaderEnv = Triple(TargetTripleStr).getEnvironment();
 
   const OpCodeProperty *Prop = getOpCodeProperty(OpCode);
-  int Index = getValidConstraintIndex(Prop, SMVer);
-  uint16_t ValidTyMask = Prop->Constraints[Index].ValidTys;
+  int OlIndex = getPropIndex(Prop->Overloads, DXILVer);
+  uint16_t ValidTyMask = Prop->Overloads[OlIndex].ValidTys;
 
   OverloadKind Kind = getOverloadKind(OverloadTy);
 
@@ -287,42 +369,40 @@ CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode, Type *ReturnTy,
   // Ensure Environment type is known
   if (ShaderEnv == Triple::UnknownEnvironment) {
     report_fatal_error(
-        StringRef(SMVer.getAsString().append(
+        StringRef(DXILVer.getAsString().append(
             ": Unknown Compilation Target Shader Stage specified ")),
         /*gen_crash_diag*/ false);
   }
 
   // Perform necessary checks to ensure Opcode is valid in the targeted shader
   // kind
-  uint16_t ValidShaderKindMask = Prop->Constraints[Index].ValidShaderKinds;
+  int StIndex = getPropIndex(Prop->Stages, DXILVer);
+  uint16_t ValidShaderKindMask = Prop->Stages[StIndex].ValidStages;
   enum ShaderKind ModuleStagekind = getShaderKindEnum(ShaderEnv);
 
-  // Ensure valid shader stage constraints are specified
-  if (ValidShaderKindMask == ShaderKind::Unknown) {
+  // Ensure valid shader stage properties are specified
+  if (ValidShaderKindMask == ShaderKind::removed) {
     report_fatal_error(
         StringRef(
-            SMVer.getAsString()
-                .append(": Unknown Target Shader Stage for DXIL operation - ")
+            DXILVer.getAsString()
+                .append(
+                    ": Unsupported Target Shader Stage for DXIL operation - ")
                 .append(getOpCodeName((OpCode)))),
         /*gen_crash_diag*/ false);
   }
 
-  // Validate the shader stage specified in target triple to be known
-  if (ModuleStagekind == ShaderKind::Unknown) {
-    report_fatal_error(StringRef(SMVer.getAsString().append(
-                           ": DXIL Module created with Unspecifed or Unknown "
-                           "Target Shader Stage")),
-                       /*gen_crash_diag*/ false);
-  }
+  // Shader stage need not be validated since getShaderKindEnum() fails
+  // for unknown shader stage.
 
   // Verify the target shader stage is valid for the DXIL operation
   if (!(ValidShaderKindMask & ModuleStagekind)) {
+    auto ShaderEnvStr = Triple(TargetTripleStr).getEnvironmentName();
     report_fatal_error(
         StringRef(std::string(ShaderEnvStr)
                       .append(" : Invalid Shader Stage for DXIL operation - ")
                       .append(getOpCodeName(OpCode))
-                      .append(" for Shader Model ")
-                      .append(SMVer.getAsString())),
+                      .append(" for DXIL Version ")
+                      .append(DXILVer.getAsString())),
         /*gen_crash_diag*/ false);
   }
 
diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.h b/llvm/lib/Target/DirectX/DXILOpBuilder.h
index 6c2801df8d891..978295c5bf80d 100644
--- a/llvm/lib/Target/DirectX/DXILOpBuilder.h
+++ b/llvm/lib/Target/DirectX/DXILOpBuilder.h
@@ -14,6 +14,7 @@
 
 #include "DXILConstants.h"
 #include "llvm/ADT/SmallVector.h"
+
 namespace llvm {
 class Module;
 class IRBuilderBase;
@@ -27,7 +28,7 @@ namespace dxil {
 
 class DXILOpBuilder {
 public:
-  DXILOpBuilder(Module &M, IRBuilderBase &B) : M(M), B(B) {}
+  DXILOpBuilder(Module &M, IRBuilderBase &B);
   /// Create an instruction that calls DXIL Op with return type, specified
   /// opcode, and call arguments.
   ///
@@ -40,13 +41,13 @@ class DXILOpBuilder {
   /// \return DXIL Op call constructed
   CallInst *createDXILOpCall(dxil::OpCode OpCode, Type *ReturnTy,
                              Type *OverloadTy, SmallVector<Value *> Args);
-
   Type *getOverloadTy(dxil::OpCode OpCode, FunctionType *FT);
   static const char *getOpCodeName(dxil::OpCode DXILOp);
 
 private:
   Module &M;
   IRBuilderBase &B;
+  std::string TargetTripleStr;
 };
 
 } // namespace dxil
diff --git a/llvm/test/CodeGen/DirectX/sin_no_stage_error.ll b/llvm/test/CodeGen/DirectX/sin_no_stage_error.ll
index 712d5afce1fa7..673fc22c32cd0 100644
--- a/llvm/test/CodeGen/DirectX/sin_no_stage_error.ll
+++ b/llvm/test/CodeGen/DirectX/sin_no_stage_error.ll
@@ -1,7 +1,7 @@
 ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.0 %s 2>&1 | FileCheck %s
 
 ; Shader Stage is required to ensure the operation is supported.
-; CHECK: LLVM ERROR: 6.0: Unknown Compilation Target Shader Stage specified
+; CHECK: LLVM ERROR: 1.0: Unknown Compilation Target Shader Stage specified
 
 define noundef float @sin_float(float noundef %a) #0 {
 entry:
diff --git a/llvm/utils/TableGen/DXILEmitter.cpp b/llvm/utils/TableGen/DXILEmitter.cpp
index 1aa255a6d61c6..35b29675e2c04 100644
--- a/llvm/utils/TableGen/DXILEmitter.cpp
+++ b/llvm/utils/TableGen/DXILEmitter.cpp
@@ -20,12 +20,10 @@
 #include "llvm/ADT/StringSet.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 <cstddef>
 #include <string>
 #include <vector>
 
@@ -41,12 +39,11 @@ struct DXILOperationDesc {
   StringRef Doc;      // the documentation description of this instruction
   // Vector of operand type records - return type is at index 0
   SmallVector<Record *> OpTypes;
-  // Vector of operation constraint records
-  SmallVector<Record *> Constraints;
-  SmallVector<std::string>
-      OpAttributes;     // operation attribute represented as strings
-  StringRef Intrinsic;  // The llvm intrinsic map to OpName. Default is "" which
-                        // means no map exists
+  SmallVector<Record *> OverloadRecs;
+  SmallVector<Record *> StageRecs;
+  SmallVector<Record *> AttrRecs;
+  StringRef Intrinsic; // The llvm intrinsic map to OpName. Default is "" which
+                       // means no map exists
   SmallVector<StringRef, 4>
       ShaderStages; // shader stages to which this applies, empty for all.
   int OverloadParamIndex;             // Index of parameter with overload type.
@@ -90,6 +87,24 @@ static ParameterKind getParameterKind(const Record *R) {
   }
 }
 
+/// In-place sort TableGen records of class with a field
+///    Version dxil_version
+/// in the ascending version order.
+static void AscendingSortByVersion(std::vector<Record *> &Recs) {
+  std::sort(Recs.begin(), Recs.end(), [](Record *RecA, Record *RecB) {
+    unsigned RecAMaj =
+        RecA->getValueAsDef("dxil_version")->getValueAsInt("Major");
+    unsigned RecAMin =
+        RecA->getValueAsDef("dxil_version")->getValueAsInt("Minor");
+    unsigned RecBMaj =
+        RecB->getValueAsDef("dxil_version")->getValueAsInt("Major");
+    unsigned RecBMin =
+        RecB->getValueAsDef("dxil_version")->getValueAsInt("Minor");
+
+    return (VersionTuple(RecAMaj, RecAMin) < VersionTuple(RecBMaj, RecBMin));
+  });
+}
+
 /// Construct an object using the DXIL Operation records specified
 /// in DXIL.td. This serves as the single source of reference of
 /// the information extracted from the specified Record R, for
@@ -101,10 +116,9 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) {
 
   Doc = R->getValueAsString("Doc");
   SmallVector<Record *> ParamTypeRecs;
-  std::vector<Record *> RetTys = R->getValueAsListOfDefs("result");
-  for (auto Ty : RetTys) {
-    ParamTypeRecs.push_back(Ty);
-  }
+
+  ParamTypeRecs.push_back(R->getValueAsDef("result"));
+
   std::vector<Record *> ArgTys = R->getValueAsListOfDefs("arguments");
   for (auto Ty : ArgTys) {
     ParamTypeRecs.push_back(Ty);
@@ -118,16 +132,12 @@ 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 < ParamTypeRecsSize; I++) {
-    auto TR = ParamTypeRecs[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) {
-      // 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.
+      // All overload types in a DXIL Op are required to be of the same type.
       if (!OverloadParamIndices.empty()) {
         bool knownType = true;
         // Ensure that the same overload type registered earlier is being used
@@ -140,7 +150,7 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) {
         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
@@ -165,31 +175,43 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) {
            "Multiple overload type specification not supported");
     OverloadParamIndex = OverloadParamIndices[0];
   }
-  // Get Constraint Records
-  std::vector<Record *> ConstrintRecs = R->getValueAsListOfDefs("constraints");
-
-  // Sort records in ascending order of Shader Model version
-  std::sort(ConstrintRecs.begin(), ConstrintRecs.end(),
-            [](Record *RecA, Record *RecB) {
-              unsigned RecAMaj = RecA->getValueAsDef("pred")
-                                     ->getValueAsDef("sm_version")
-                                     ->getValueAsInt("Major");
-              unsigned RecAMin = RecA->getValueAsDef("pred")
-                                     ->getValueAsDef("sm_version")
-                                     ->getValueAsInt("Minor");
-              unsigned RecBMaj = RecB->getValueAsDef("pred")
-                                     ->getValueAsDef("sm_version")
-                                     ->getValueAsInt("Major");
-              unsigned RecBMin = RecB->getValueAsDef("pred")
-                                     ->getValueAsDef("sm_version")
-                                     ->getValueAsInt("Minor");
-
-              return (VersionTuple(RecAMaj, RecAMin) <
-                      VersionTuple(RecBMaj, RecBMin));
-            });
-
-  for (Record *CR : ConstrintRecs) {
-    Constraints.push_back(CR);
+
+  // Get overload records
+  std::vector<Record *> Recs = R->getValueAsListOfDefs("overloads");
+
+  // Sort records in ascending order of DXIL version
+  AscendingSortByVersion(Recs);
+
+  for (Record *CR : Recs) {
+    OverloadRecs.push_back(CR);
+  }
+
+  // Get stage records
+  Recs = R->getValueAsListOfDefs("stages");
+
+  if (Recs.empty()) {
+    report_fatal_error(
+        StringRef(std::string("Atleast one specification of valid stage for ")
+                      .append(OpName)
+                      .append(" is required")),
+        /* gen_crash_diag=*/false);
+  }
+
+  // Sort records in ascending order of DXIL version
+  AscendingSortByVersion(Recs);
+
+  for (Record *CR : Recs) {
+    StageRecs.push_back(CR);
+  }
+
+  // Get attribute records
+  Recs = R->getValueAsListOfDefs("attributes");
+
+  // Sort records in ascending order of DXIL version
+  AscendingSortByVersion(Recs);
+
+  for (Record *CR : Recs) {
+    AttrRecs.push_back(CR);
   }
 
   // Get the operation class
@@ -210,16 +232,6 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) {
       assert(DefName.starts_with("int_") && "invalid intrinsic name");
       // Remove the int_ from intrinsic name.
       Intrinsic = DefName.substr(4);
-      // TODO: For now, assume that attributes of DXIL Operation are the same as
-      // that of the intrinsic. Deviations are expected to be encoded in
-      // TableGen record specification and handled accordingly here. Support to
-      // be added as needed.
-      ListInit *IntrPropList =
-          IntrinsicDef->getValueAsListInit("IntrProperties");
-      auto IntrPropListSize = IntrPropList->size();
-      for (unsigned I = 0; I < IntrPropListSize; I++) {
-        OpAttributes.emplace_back(IntrPropList->getElement(I)->getAsString());
-      }
     }
   }
 }
@@ -291,83 +303,136 @@ static std::string getOverloadKindStr(const Record *R) {
   }
 }
 
-/// Return a string representation of constraints specified for the DXIL
-/// Operation
+/// Return a string representation of valid overload information denoted
+// by input records
 //
-/// \param Recs A vector of records of TableGen class type DXILShaderModel
-/// \return std::string string representation of OverloadKind
-static std::string getConstraintString(const SmallVector<Record *> Recs) {
-  std::string ConstraintString = "";
+/// \param Recs A vector of records of TableGen Overload records
+/// \return std::string string representation of overload mask string
+///         predicated by DXIL Version. E.g.,
+//          {{{1, 0}, Mask1}, {{1, 2}, Mask2}, ...}
+static std::string getOverloadMaskString(const SmallVector<Record *> Recs) {
+  std::string MaskString = "";
   std::string Prefix = "";
-  ConstraintString.append("{");
-  // If no constraints were specified, assume the operation
-  // a) to be supported in SM 6.0 and later
+  MaskString.append("{");
+  // If no overload information records were specified, assume the operation
+  // a) to be supported in DXIL Version 1.0 and later
   // b) has no overload types
-  // c) is supported in all shader stage kinds
   if (Recs.empty()) {
-    ConstraintString.append(
-        "{{6, 0}, OverloadKind::UNDEFINED, ShaderKind::allKinds}}");
+    MaskString.append("{{1, 0}, OverloadKind::UNDEFINED}}");
+  } else {
+    for (auto Rec : Recs) {
+      unsigned Major =
+          Rec->getValueAsDef("dxil_version")->getValueAsInt("Major");
+      unsigned Minor =
+          Rec->getValueAsDef("dxil_version")->getValueAsInt("Minor");
+      MaskString.append(Prefix)
+          .append("{{")
+          .append(std::to_string(Major))
+          .append(", ")
+          .append(std::to_string(Minor).append("}, "));
+
+      std::string PipePrefix = "";
+      auto Tys = Rec->getValueAsListOfDefs("overload_types");
+      if (Tys.empty()) {
+        MaskString.append("OverloadKind::UNDEFINED");
+      }
+      for (const auto *Ty : Tys) {
+        MaskString.append(PipePrefix).append(getOverloadKindStr(Ty));
+        PipePrefix = " | ";
+      }
+
+      MaskString.append("}");
+      Prefix = ", ";
+    }
+    MaskString.append("}");
+  }
+  return MaskString;
+}
+
+/// Return a string representation of valid shader stag information denoted
+// by input records
+//
+/// \param Recs A vector of records of TableGen Stages records
+/// \return std::string string representation of stages mask string
+///         predicated by DXIL Version. E.g.,
+//          {{{1, 0}, Mask1}, {{1, 2}, Mask2}, ...}
+static std::string getStageMaskString(const SmallVector<Record *> Recs) {
+  std::string MaskString = "";
+  std::string Prefix = "";
+  MaskString.append("{");
+  // Atleast one stage information record is expected to be specified.
+  if (Recs.empty()) {
+    report_fatal_error("Atleast one specification of valid stages for "
+                       "operation must be specified",
+                       /*gen_crash_diag*/ false);
   }
-  for (auto ConstrRec : Recs) {
-    auto SMConstrRec = ConstrRec->getValueAsDef("pred");
-    unsigned Major =
-        SMConstrRec->getValueAsDef("sm_version")->getValueAsInt("Major");
-    unsigned Minor =
-        SMConstrRec->getValueAsDef("sm_version")->getValueAsInt("Minor");
-    ConstraintString.append(Prefix).append("{{")
+
+  for (auto Rec : Recs) {
+    unsigned Major = Rec->getValueAsDef("dxil_version")->getValueAsInt("Major");
+    unsigned Minor = Rec->getValueAsDef("dxil_version")->getValueAsInt("Minor");
+    MaskString.append(Prefix)
+        .append("{{")
         .append(std::to_string(Major))
         .append(", ")
         .append(std::to_string(Minor).append("}, "));
 
-    auto ConstraintList = ConstrRec->getValueAsListOfDefs("constraints");
-    std::string OverloadMaskString = "";
-    std::string StageMaskString = "";
-    for (auto Constr : ConstraintList) {
-      // All Constraints are specified as anonymous records.
-      assert(Constr->isAnonymous() &&
-             "Constraint Specification Record expected to be anonymous");
-      // Generate Overload mask for constraint of class Overloads
-      if (!Constr->getType()->getAsString().compare("Overloads")) {
-        std::string PipePrefix = "";
-        auto OLTys = Constr->getValueAsListOfDefs("overload_types");
-        if (OLTys.empty()) {
-          OverloadMaskString.append("OverloadKind::UNDEFINED");
-        }
-        for (const auto *Ty : OLTys) {
-          OverloadMaskString.append(PipePrefix).append(getOverloadKindStr(Ty));
-          PipePrefix = " | ";
-        }
-      }
-      // Generate Shader Kind mask from Shader Stages constraints
-      if (!Constr->getType()->getAsString().compare("Stages")) {
-        std::string PipePrefix = "";
-        auto Stages = Constr->getValueAsListOfDefs("stage_kinds");
-        if (Stages.empty()) {
-          StageMaskString.append("ShaderKind::allKinds");
-        }
-        for (const auto *S : Stages) {
-          StageMaskString.append(PipePrefix)
-              .append("ShaderKind::")
-              .append(S->getName());
-          PipePrefix = " | ";
-        }
-      }
+    std::string PipePrefix = "";
+    auto Stages = Rec->getValueAsListOfDefs("shader_stages");
+    if (Stages.empty()) {
+      report_fatal_error("No valid stages for operation specified",
+                         /*gen_crash_diag*/ false);
     }
-    if (OverloadMaskString.empty()) {
-      OverloadMaskString.append(" OverloadKind::UNDEFINED ");
-    }
-    if (StageMaskString.empty()) {
-      StageMaskString.append(" ShaderKind::allKinds ");
+    for (const auto *S : Stages) {
+      MaskString.append(PipePrefix).append("ShaderKind::").append(S->getName());
+      PipePrefix = " | ";
     }
 
-    ConstraintString.append(OverloadMaskString)
+    MaskString.append("}");
+    Prefix = ", ";
+  }
+  MaskString.append("}");
+  return MaskString;
+}
+
+/// Return a string representation of valid attribute information denoted
+// by input records
+//
+/// \param Recs A vector of records of TableGen Attribute records
+/// \return std::string string representation of stages mask string
+///         predicated by DXIL Version. E.g.,
+//          {{{1, 0}, Mask1}, {{1, 2}, Mask2}, ...}
+static std::string getAttributeMaskString(const SmallVector<Record *> Recs) {
+  std::string MaskString = "";
+  std::string Prefix = "";
+  MaskString.append("{");
+
+  for (auto Rec : Recs) {
+    unsigned Major = Rec->getValueAsDef("dxil_version")->getValueAsInt("Major");
+    unsigned Minor = Rec->getValueAsDef("dxil_version")->getValueAsInt("Minor");
+    MaskString.append(Prefix)
+        .append("{{")
+        .append(std::to_string(Major))
         .append(", ")
-        .append(StageMaskString);
-    ConstraintString.append("}");
+        .append(std::to_string(Minor).append("}, "));
+
+    std::string PipePrefix = "";
+    auto Attrs = Rec->getValueAsListOfDefs("op_attrs");
+    if (Attrs.empty()) {
+      MaskString.append("Attribute::None");
+    } else {
+      for (const auto *Attr : Attrs) {
+        MaskString.append(PipePrefix)
+            .append("Attribute::")
+            .append(Attr->getName());
+        PipePrefix = " | ";
+      }
+    }
+
+    MaskString.append("}");
     Prefix = ", ";
   }
-  ConstraintString.append("}");
-  return ConstraintString;
+  MaskString.append("}");
+  return MaskString;
 }
 
 /// Emit Enums of DXIL Ops
@@ -426,24 +491,6 @@ static void emitDXILIntrinsicMap(std::vector<DXILOperationDesc> &Ops,
   OS << "#endif // DXIL_OP_INTRINSIC_MAP\n";
 }
 
-/// Convert operation attribute string to Attribute enum
-///
-/// \param Attr string reference
-/// \return std::string Attribute enum string
-
-static std::string emitDXILOperationAttr(SmallVector<std::string> Attrs) {
-  for (auto Attr : Attrs) {
-    // TODO: For now just recognize IntrNoMem and IntrReadMem as valid and
-    //  ignore others.
-    if (Attr == "IntrNoMem") {
-      return "Attribute::ReadNone";
-    } else if (Attr == "IntrReadMem") {
-      return "Attribute::ReadOnly";
-    }
-  }
-  return "Attribute::None";
-}
-
 /// Emit DXIL operation table
 /// \param A vector of DXIL Ops
 /// \param Output stream
@@ -503,9 +550,10 @@ static void emitDXILOperationTable(std::vector<DXILOperationDesc> &Ops,
     OS << Prefix << "  { dxil::OpCode::" << Op.OpName << ", "
        << OpStrings.get(Op.OpName) << ", OpCodeClass::" << Op.OpClass << ", "
        << OpClassStrings.get(Op.OpClass.data()) << ", "
-       << getConstraintString(Op.Constraints) << ", "
-       << emitDXILOperationAttr(Op.OpAttributes) << ", "
-       << Op.OverloadParamIndex << ", " << Op.OpTypes.size() - 1 << ", "
+       << getOverloadMaskString(Op.OverloadRecs) << ", "
+       << getStageMaskString(Op.StageRecs) << ", "
+       << getAttributeMaskString(Op.AttrRecs) << ", " << Op.OverloadParamIndex
+       << ", " << Op.OpTypes.size() - 1 << ", "
        << Parameters.get(ParameterMap[Op.OpClass]) << " }";
     Prefix = ",\n";
   }
@@ -566,113 +614,36 @@ static void emitDXILOperationTableDataStructs(RecordKeeper &Records,
                                               raw_ostream &OS) {
   // Get Shader stage records
   std::vector<Record *> ShaderKindRecs =
-      Records.getAllDerivedDefinitions("ShaderStage");
+      Records.getAllDerivedDefinitions("DXILShaderStage");
   // Sort records by name
   llvm::sort(ShaderKindRecs,
              [](Record *A, Record *B) { return A->getName() < B->getName(); });
 
   OS << "// Valid shader kinds\n\n";
-  // Choose the type of enum ShaderKind based on the number of stages declared
-  // plus one for allKinds
+  // 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.
-  uint64_t ShaderKindCount = PowerOf2Ceil(ShaderKindRecs.size() + 1);
-  OS << "enum ShaderKind : uint" << ShaderKindCount << "_t {\n";
-  const std::string allKinds("allKinds");
-  // set unknown kind to 0
-  OS << "  Unknown = 0,\n";
+  size_t ShaderKindCount = ShaderKindRecs.size();
+  uint64_t ShaderKindTySz = PowerOf2Ceil(ShaderKindRecs.size() + 1);
+  OS << "enum ShaderKind : uint" << ShaderKindTySz << "_t {\n";
+  const std::string allStages("all_stages");
+  const std::string removed("removed");
   int shiftVal = 1;
   for (auto R : ShaderKindRecs) {
     auto Name = R->getName();
-    if (Name.compare(allKinds)) {
+    if (Name.compare(removed) == 0) {
+      OS << "  " << Name
+         << " =  0,  // Pseudo-stage indicating op not supported in any "
+            "stage\n";
+    } else if (Name.compare(allStages) == 0) {
+      OS << "  " << Name << " =  0x"
+         << utohexstr(((1 << ShaderKindCount) - 1), false, 0)
+         << ", // Pseudo-stage indicating op is supported in all stages\n";
+    } else if (Name.compare(allStages)) {
       OS << "  " << Name << " = 1 << " << std::to_string(shiftVal++) << ",\n";
     }
   }
-  // allkinds is set to (1 << ShaderKindCount) - 1, with all bits set denoting
-  // support for all stages
-  OS << "  " << allKinds << " =  0x"
-     << utohexstr(((1 << shiftVal) - 1), false, 0) << "\n";
   OS << "}; // enum ShaderKind\n\n";
-
-  // 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",   "UserDefineType", "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 OverloadKindCount = PowerOf2Ceil(OverloadKindList.size());
-  OS << "enum OverloadKind : uint" << OverloadKindCount << "_t {\n";
-  OS << "    UNDEFINED = 0,\n";
-  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 Constraints that encapsulate overload and shader kind
-  // constraints predicated on shader model version, if any.
-  OS << "struct OpConstraints { \n \
-            Version ShaderModelVer; \n";
-  OS << "             uint" << OverloadKindCount << "_t ValidTys; \n";
-  OS << "             uint" << ShaderKindCount << "_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<OpConstraints> Constraints; \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::UNDEFINED:  \n \
-      return \"void\";  \n \
-    case OverloadKind::ObjectType: \n \
-    case OverloadKind::UserDefineType: \n \
-      break; \n \
-    } \n \
-    llvm_unreachable(\"invalid overload type for name\"); \n \
-  }\n\n";
 }
 
 /// Entry function call that invokes the functionality of this TableGen backend

>From 61ffa4753dc9067602f0fd2c48d52fffe44c4cf7 Mon Sep 17 00:00:00 2001
From: Bharadwaj Yadavalli <Bharadwaj.Yadavalli at microsoft.com>
Date: Fri, 26 Jul 2024 20:37:21 +0000
Subject: [PATCH 12/12] Use Twine to construct message in report_fatal_error()

---
 llvm/lib/Target/DirectX/DXILOpBuilder.cpp | 32 +++++++++--------------
 llvm/utils/TableGen/DXILEmitter.cpp       | 15 +++++------
 2 files changed, 19 insertions(+), 28 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
index bcc39a19924ab..367fd732a277b 100644
--- a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
@@ -322,9 +322,8 @@ static int getPropIndex(const std::vector<T> PropList,
       return I;
     }
   }
-  report_fatal_error(
-      StringRef(DXILVer.getAsString().append(": Unknown DXIL Version")),
-      /*gen_crash_diag*/ false);
+  report_fatal_error(Twine(DXILVer.getAsString()) + ": Unknown DXIL Version",
+                     /*gen_crash_diag*/ false);
 
   return -1;
 }
@@ -360,17 +359,16 @@ CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode, Type *ReturnTy,
   // per the specified types for the operation
   if ((ValidTyMask != OverloadKind::UNDEFINED) &&
       (ValidTyMask & (uint16_t)Kind) == 0) {
-    report_fatal_error(
-        StringRef(std::string("Invalid Overload Type for DXIL operation - ")
-                      .append(getOpCodeName((OpCode)))),
-        /* gen_crash_diag=*/false);
+    report_fatal_error(Twine("Invalid Overload Type for DXIL operation - ") +
+                           getOpCodeName(OpCode),
+                       /* gen_crash_diag=*/false);
   }
 
   // Ensure Environment type is known
   if (ShaderEnv == Triple::UnknownEnvironment) {
     report_fatal_error(
-        StringRef(DXILVer.getAsString().append(
-            ": Unknown Compilation Target Shader Stage specified ")),
+        Twine(DXILVer.getAsString() +
+              ": Unknown Compilation Target Shader Stage specified "),
         /*gen_crash_diag*/ false);
   }
 
@@ -383,11 +381,9 @@ CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode, Type *ReturnTy,
   // Ensure valid shader stage properties are specified
   if (ValidShaderKindMask == ShaderKind::removed) {
     report_fatal_error(
-        StringRef(
-            DXILVer.getAsString()
-                .append(
-                    ": Unsupported Target Shader Stage for DXIL operation - ")
-                .append(getOpCodeName((OpCode)))),
+        Twine(DXILVer.getAsString() +
+              ": Unsupported Target Shader Stage for DXIL operation - " +
+              getOpCodeName(OpCode)),
         /*gen_crash_diag*/ false);
   }
 
@@ -398,11 +394,9 @@ CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode, Type *ReturnTy,
   if (!(ValidShaderKindMask & ModuleStagekind)) {
     auto ShaderEnvStr = Triple(TargetTripleStr).getEnvironmentName();
     report_fatal_error(
-        StringRef(std::string(ShaderEnvStr)
-                      .append(" : Invalid Shader Stage for DXIL operation - ")
-                      .append(getOpCodeName(OpCode))
-                      .append(" for DXIL Version ")
-                      .append(DXILVer.getAsString())),
+        Twine(ShaderEnvStr + " : Invalid Shader Stage for DXIL operation - ") +
+            getOpCodeName(OpCode) + " for DXIL Version " +
+            DXILVer.getAsString(),
         /*gen_crash_diag*/ false);
   }
 
diff --git a/llvm/utils/TableGen/DXILEmitter.cpp b/llvm/utils/TableGen/DXILEmitter.cpp
index 35b29675e2c04..e78599b195b4c 100644
--- a/llvm/utils/TableGen/DXILEmitter.cpp
+++ b/llvm/utils/TableGen/DXILEmitter.cpp
@@ -190,11 +190,9 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) {
   Recs = R->getValueAsListOfDefs("stages");
 
   if (Recs.empty()) {
-    report_fatal_error(
-        StringRef(std::string("Atleast one specification of valid stage for ")
-                      .append(OpName)
-                      .append(" is required")),
-        /* gen_crash_diag=*/false);
+    report_fatal_error(Twine("Atleast one specification of valid stage for ") +
+                           OpName + " is required",
+                       /* gen_crash_diag=*/false);
   }
 
   // Sort records in ascending order of DXIL version
@@ -218,10 +216,9 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) {
   OpClass = R->getValueAsDef("OpClass")->getName();
 
   if (!OpClass.str().compare("UnknownOpClass")) {
-    report_fatal_error(
-        StringRef(std::string("Unspecified DXIL OpClass for DXIL operation - ")
-                      .append(OpName)),
-        /* gen_crash_diag=*/false);
+    report_fatal_error(Twine("Unspecified DXIL OpClass for DXIL operation - ") +
+                           OpName,
+                       /* gen_crash_diag=*/false);
   }
 
   const RecordVal *RV = R->getValue("LLVMIntrinsic");



More information about the llvm-commits mailing list