[llvm] 8cf8565 - [DirectX] Make DXILOpBuilder's API more useable
via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 2 15:13:19 PDT 2024
Author: Justin Bogner
Date: 2024-08-02T15:13:16-07:00
New Revision: 8cf85653b6f5c90b83f8a5741baad5725d6c6932
URL: https://github.com/llvm/llvm-project/commit/8cf85653b6f5c90b83f8a5741baad5725d6c6932
DIFF: https://github.com/llvm/llvm-project/commit/8cf85653b6f5c90b83f8a5741baad5725d6c6932.diff
LOG: [DirectX] Make DXILOpBuilder's API more useable
This adjusts the DXILOpBuilder API in a couple of ways:
1. Remove the need to call `getOverloadTy` before creating Ops
2. Introduce `tryCreateOp` to parallel `createOp` but propagate errors
3. Introduce specialized createOp methods for each DXIL Op
This will simplify usage of the builder in upcoming changes, and also allows us
to propagate errors via DiagnosticInfo rather than using fatal errors.
Pull Request: https://github.com/llvm/llvm-project/pull/101250
Added:
Modified:
llvm/lib/Target/DirectX/DXIL.td
llvm/lib/Target/DirectX/DXILOpBuilder.cpp
llvm/lib/Target/DirectX/DXILOpBuilder.h
llvm/lib/Target/DirectX/DXILOpLowering.cpp
llvm/test/CodeGen/DirectX/acos_error.ll
llvm/test/CodeGen/DirectX/asin_error.ll
llvm/test/CodeGen/DirectX/atan_error.ll
llvm/test/CodeGen/DirectX/ceil_error.ll
llvm/test/CodeGen/DirectX/cos_error.ll
llvm/test/CodeGen/DirectX/cosh_error.ll
llvm/test/CodeGen/DirectX/dot2_error.ll
llvm/test/CodeGen/DirectX/dot3_error.ll
llvm/test/CodeGen/DirectX/dot4_error.ll
llvm/test/CodeGen/DirectX/exp2_error.ll
llvm/test/CodeGen/DirectX/flattened_thread_id_in_group_error.ll
llvm/test/CodeGen/DirectX/floor_error.ll
llvm/test/CodeGen/DirectX/frac_error.ll
llvm/test/CodeGen/DirectX/group_id_error.ll
llvm/test/CodeGen/DirectX/isinf_error.ll
llvm/test/CodeGen/DirectX/log2_error.ll
llvm/test/CodeGen/DirectX/round_error.ll
llvm/test/CodeGen/DirectX/rsqrt_error.ll
llvm/test/CodeGen/DirectX/sin_error.ll
llvm/test/CodeGen/DirectX/sinh_error.ll
llvm/test/CodeGen/DirectX/sqrt_error.ll
llvm/test/CodeGen/DirectX/tan_error.ll
llvm/test/CodeGen/DirectX/tanh_error.ll
llvm/test/CodeGen/DirectX/thread_id_error.ll
llvm/test/CodeGen/DirectX/thread_id_in_group_error.ll
llvm/test/CodeGen/DirectX/trunc_error.ll
llvm/utils/TableGen/DXILEmitter.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td
index a66f5b6470934..67015cff78a79 100644
--- a/llvm/lib/Target/DirectX/DXIL.td
+++ b/llvm/lib/Target/DirectX/DXIL.td
@@ -318,7 +318,7 @@ class DXILOp<int opcode, DXILOpClass opclass> {
def Abs : DXILOp<6, unary> {
let Doc = "Returns the absolute value of the input.";
let LLVMIntrinsic = int_fabs;
- let arguments = [LLVMMatchType<0>];
+ let arguments = [overloadTy];
let result = overloadTy;
let overloads = [Overloads<DXIL1_0, [halfTy, floatTy, doubleTy]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
@@ -338,7 +338,7 @@ def IsInf : DXILOp<9, isSpecialFloat> {
def Cos : DXILOp<12, unary> {
let Doc = "Returns cosine(theta) for theta in radians.";
let LLVMIntrinsic = int_cos;
- let arguments = [LLVMMatchType<0>];
+ let arguments = [overloadTy];
let result = overloadTy;
let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
@@ -348,7 +348,7 @@ def Cos : DXILOp<12, unary> {
def Sin : DXILOp<13, unary> {
let Doc = "Returns sine(theta) for theta in radians.";
let LLVMIntrinsic = int_sin;
- let arguments = [LLVMMatchType<0>];
+ let arguments = [overloadTy];
let result = overloadTy;
let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
@@ -358,7 +358,7 @@ def Sin : DXILOp<13, unary> {
def Tan : DXILOp<14, unary> {
let Doc = "Returns tangent(theta) for theta in radians.";
let LLVMIntrinsic = int_tan;
- let arguments = [LLVMMatchType<0>];
+ let arguments = [overloadTy];
let result = overloadTy;
let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
@@ -368,7 +368,7 @@ def Tan : DXILOp<14, unary> {
def ACos : DXILOp<15, unary> {
let Doc = "Returns the arccosine of the specified value.";
let LLVMIntrinsic = int_acos;
- let arguments = [LLVMMatchType<0>];
+ let arguments = [overloadTy];
let result = overloadTy;
let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
@@ -378,7 +378,7 @@ def ACos : DXILOp<15, unary> {
def ASin : DXILOp<16, unary> {
let Doc = "Returns the arcsine of the specified value.";
let LLVMIntrinsic = int_asin;
- let arguments = [LLVMMatchType<0>];
+ let arguments = [overloadTy];
let result = overloadTy;
let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
@@ -388,7 +388,7 @@ def ASin : DXILOp<16, unary> {
def ATan : DXILOp<17, unary> {
let Doc = "Returns the arctangent of the specified value.";
let LLVMIntrinsic = int_atan;
- let arguments = [LLVMMatchType<0>];
+ let arguments = [overloadTy];
let result = overloadTy;
let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
@@ -398,7 +398,7 @@ def ATan : DXILOp<17, unary> {
def HCos : DXILOp<18, unary> {
let Doc = "Returns the hyperbolic cosine of the specified value.";
let LLVMIntrinsic = int_cosh;
- let arguments = [LLVMMatchType<0>];
+ let arguments = [overloadTy];
let result = overloadTy;
let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
@@ -408,7 +408,7 @@ def HCos : DXILOp<18, unary> {
def HSin : DXILOp<19, unary> {
let Doc = "Returns the hyperbolic sine of the specified value.";
let LLVMIntrinsic = int_sinh;
- let arguments = [LLVMMatchType<0>];
+ let arguments = [overloadTy];
let result = overloadTy;
let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
@@ -418,7 +418,7 @@ def HSin : DXILOp<19, unary> {
def HTan : DXILOp<20, unary> {
let Doc = "Returns the hyperbolic tan of the specified value.";
let LLVMIntrinsic = int_tanh;
- let arguments = [LLVMMatchType<0>];
+ let arguments = [overloadTy];
let result = overloadTy;
let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
@@ -429,7 +429,7 @@ 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 arguments = [overloadTy];
let result = overloadTy;
let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
@@ -440,7 +440,7 @@ 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 arguments = [overloadTy];
let result = overloadTy;
let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
@@ -450,7 +450,7 @@ def Frac : DXILOp<22, unary> {
def Log2 : DXILOp<23, unary> {
let Doc = "Returns the base-2 logarithm of the specified value.";
let LLVMIntrinsic = int_log2;
- let arguments = [LLVMMatchType<0>];
+ let arguments = [overloadTy];
let result = overloadTy;
let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
@@ -461,7 +461,7 @@ 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 arguments = [overloadTy];
let result = overloadTy;
let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
@@ -472,7 +472,7 @@ 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 arguments = [overloadTy];
let result = overloadTy;
let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
@@ -483,7 +483,7 @@ 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 arguments = [overloadTy];
let result = overloadTy;
let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
@@ -494,7 +494,7 @@ 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 arguments = [overloadTy];
let result = overloadTy;
let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
@@ -505,7 +505,7 @@ 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 arguments = [overloadTy];
let result = overloadTy;
let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
@@ -515,7 +515,7 @@ def Ceil : DXILOp<28, unary> {
def Trunc : DXILOp<29, unary> {
let Doc = "Returns the specified value truncated to the integer component.";
let LLVMIntrinsic = int_trunc;
- let arguments = [LLVMMatchType<0>];
+ let arguments = [overloadTy];
let result = overloadTy;
let overloads = [Overloads<DXIL1_0, [halfTy, floatTy]>];
let stages = [Stages<DXIL1_0, [all_stages]>];
@@ -525,7 +525,7 @@ def Trunc : DXILOp<29, unary> {
def Rbits : DXILOp<30, unary> {
let Doc = "Returns the specified value with its bits reversed.";
let LLVMIntrinsic = int_bitreverse;
- let arguments = [LLVMMatchType<0>];
+ let arguments = [overloadTy];
let result = overloadTy;
let overloads =
[Overloads<DXIL1_0, [i16Ty, i32Ty, i64Ty]>];
@@ -536,7 +536,7 @@ def Rbits : DXILOp<30, unary> {
def FMax : DXILOp<35, binary> {
let Doc = "Float maximum. FMax(a,b) = a > b ? a : b";
let LLVMIntrinsic = int_maxnum;
- let arguments = [LLVMMatchType<0>, LLVMMatchType<0>];
+ let arguments = [overloadTy, overloadTy];
let result = overloadTy;
let overloads =
[Overloads<DXIL1_0, [halfTy, floatTy, doubleTy]>];
@@ -547,7 +547,7 @@ def FMax : DXILOp<35, binary> {
def FMin : DXILOp<36, binary> {
let Doc = "Float minimum. FMin(a,b) = a < b ? a : b";
let LLVMIntrinsic = int_minnum;
- let arguments = [LLVMMatchType<0>, LLVMMatchType<0>];
+ let arguments = [overloadTy, overloadTy];
let result = overloadTy;
let overloads =
[Overloads<DXIL1_0, [halfTy, floatTy, doubleTy]>];
@@ -558,7 +558,7 @@ def FMin : DXILOp<36, binary> {
def SMax : DXILOp<37, binary> {
let Doc = "Signed integer maximum. SMax(a,b) = a > b ? a : b";
let LLVMIntrinsic = int_smax;
- let arguments = [LLVMMatchType<0>, LLVMMatchType<0>];
+ let arguments = [overloadTy, overloadTy];
let result = overloadTy;
let overloads =
[Overloads<DXIL1_0, [i16Ty, i32Ty, i64Ty]>];
@@ -569,7 +569,7 @@ def SMax : DXILOp<37, binary> {
def SMin : DXILOp<38, binary> {
let Doc = "Signed integer minimum. SMin(a,b) = a < b ? a : b";
let LLVMIntrinsic = int_smin;
- let arguments = [LLVMMatchType<0>, LLVMMatchType<0>];
+ let arguments = [overloadTy, overloadTy];
let result = overloadTy;
let overloads =
[Overloads<DXIL1_0, [i16Ty, i32Ty, i64Ty]>];
@@ -580,7 +580,7 @@ def SMin : DXILOp<38, binary> {
def UMax : DXILOp<39, binary> {
let Doc = "Unsigned integer maximum. UMax(a,b) = a > b ? a : b";
let LLVMIntrinsic = int_umax;
- let arguments = [LLVMMatchType<0>, LLVMMatchType<0>];
+ let arguments = [overloadTy, overloadTy];
let result = overloadTy;
let overloads =
[Overloads<DXIL1_0, [i16Ty, i32Ty, i64Ty]>];
@@ -591,7 +591,7 @@ def UMax : DXILOp<39, binary> {
def UMin : DXILOp<40, binary> {
let Doc = "Unsigned integer minimum. UMin(a,b) = a < b ? a : b";
let LLVMIntrinsic = int_umin;
- let arguments = [LLVMMatchType<0>, LLVMMatchType<0>];
+ let arguments = [overloadTy, overloadTy];
let result = overloadTy;
let overloads =
[Overloads<DXIL1_0, [i16Ty, i32Ty, i64Ty]>];
@@ -603,7 +603,7 @@ 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 arguments = [overloadTy, overloadTy, overloadTy];
let result = overloadTy;
let overloads =
[Overloads<DXIL1_0, [halfTy, floatTy, doubleTy]>];
@@ -615,7 +615,7 @@ 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 arguments = [overloadTy, overloadTy, overloadTy];
let result = overloadTy;
let overloads =
[Overloads<DXIL1_0, [i16Ty, i32Ty, i64Ty]>];
@@ -627,7 +627,7 @@ 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 arguments = [overloadTy, overloadTy, overloadTy];
let result = overloadTy;
let overloads =
[Overloads<DXIL1_0, [i16Ty, i32Ty, i64Ty]>];
diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
index a03701be743c7..42df7c90cb337 100644
--- a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp
@@ -208,8 +208,8 @@ static StructType *getHandleType(LLVMContext &Ctx) {
Ctx);
}
-static Type *getTypeFromParameterKind(ParameterKind Kind, Type *OverloadTy) {
- auto &Ctx = OverloadTy->getContext();
+static Type *getTypeFromParameterKind(ParameterKind Kind, LLVMContext &Ctx,
+ Type *OverloadTy) {
switch (Kind) {
case ParameterKind::Void:
return Type::getVoidTy(Ctx);
@@ -285,28 +285,26 @@ static ShaderKind getShaderKindEnum(Triple::EnvironmentType EnvType) {
/// the following prototype
/// OverloadType dx.op.<opclass>.<return-type>(int opcode, <param types>)
/// <param-types> are constructed from types in Prop.
-/// \param Prop Structure containing DXIL Operation properties based on
-/// its specification in DXIL.td.
-/// \param OverloadTy Return type to be used to construct DXIL function type.
static FunctionType *getDXILOpFunctionType(const OpCodeProperty *Prop,
- Type *ReturnTy, Type *OverloadTy) {
+ LLVMContext &Context,
+ Type *OverloadTy) {
SmallVector<Type *> ArgTys;
const ParameterKind *ParamKinds = getOpCodeParameterKind(*Prop);
- // Add ReturnTy as return type of the function
- ArgTys.emplace_back(ReturnTy);
+ assert(Prop->NumOfParameters && "No return type?");
+ // Add return type of the function
+ Type *ReturnTy = getTypeFromParameterKind(ParamKinds[0], Context, OverloadTy);
// Add DXIL Opcode value type viz., Int32 as first argument
- ArgTys.emplace_back(Type::getInt32Ty(OverloadTy->getContext()));
+ ArgTys.emplace_back(Type::getInt32Ty(Context));
// Add DXIL Operation parameter types as specified in DXIL properties
- for (unsigned I = 0; I < Prop->NumOfParameters; ++I) {
+ for (unsigned I = 1; I < Prop->NumOfParameters; ++I) {
ParameterKind Kind = ParamKinds[I];
- ArgTys.emplace_back(getTypeFromParameterKind(Kind, OverloadTy));
+ ArgTys.emplace_back(getTypeFromParameterKind(Kind, Context, OverloadTy));
}
- return FunctionType::get(
- ArgTys[0], ArrayRef<Type *>(&ArgTys[1], ArgTys.size() - 1), false);
+ return FunctionType::get(ReturnTy, ArgTys, /*isVarArg=*/false);
}
/// Get index of the property from PropList valid for the most recent
@@ -347,107 +345,91 @@ DXILOpBuilder::DXILOpBuilder(Module &M, IRBuilderBase &B) : M(M), B(B) {
}
}
-CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode, Type *ReturnTy,
- Type *OverloadTy,
- SmallVector<Value *> Args) {
+static Error makeOpError(dxil::OpCode OpCode, Twine Msg) {
+ return make_error<StringError>(
+ Twine("Cannot create ") + getOpCodeName(OpCode) + " operation: " + Msg,
+ inconvertibleErrorCode());
+}
+Expected<CallInst *> DXILOpBuilder::tryCreateOp(dxil::OpCode OpCode,
+ ArrayRef<Value *> Args,
+ Type *RetTy) {
const OpCodeProperty *Prop = getOpCodeProperty(OpCode);
+
+ Type *OverloadTy = nullptr;
+ if (Prop->OverloadParamIndex == 0) {
+ if (!RetTy)
+ return makeOpError(OpCode, "Op overloaded on unknown return type");
+ OverloadTy = RetTy;
+ } else if (Prop->OverloadParamIndex > 0) {
+ // The index counts including the return type
+ unsigned ArgIndex = Prop->OverloadParamIndex - 1;
+ if (static_cast<unsigned>(ArgIndex) >= Args.size())
+ return makeOpError(OpCode, "Wrong number of arguments");
+ OverloadTy = Args[ArgIndex]->getType();
+ }
+ FunctionType *DXILOpFT =
+ getDXILOpFunctionType(Prop, M.getContext(), OverloadTy);
+
std::optional<size_t> OlIndexOrErr =
getPropIndex(ArrayRef(Prop->Overloads), DXILVersion);
- if (!OlIndexOrErr.has_value()) {
- report_fatal_error(Twine(getOpCodeName(OpCode)) +
- ": No valid overloads found for DXIL Version - " +
- DXILVersion.getAsString(),
- /*gen_crash_diag*/ false);
- }
+ if (!OlIndexOrErr.has_value())
+ return makeOpError(OpCode, Twine("No valid overloads for DXIL version ") +
+ DXILVersion.getAsString());
+
uint16_t ValidTyMask = Prop->Overloads[*OlIndexOrErr].ValidTys;
- OverloadKind Kind = getOverloadKind(OverloadTy);
+ // If we don't have an overload type, use the function's return type. This is
+ // a bit of a hack, but it's necessary to get the type suffix on unoverloaded
+ // DXIL ops correct, like `dx.op.threadId.i32`.
+ OverloadKind Kind =
+ getOverloadKind(OverloadTy ? OverloadTy : DXILOpFT->getReturnType());
// 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(Twine("Invalid Overload Type for DXIL operation - ") +
- getOpCodeName(OpCode),
- /* gen_crash_diag=*/false);
- }
+ (ValidTyMask & (uint16_t)Kind) == 0)
+ return makeOpError(OpCode, "Invalid overload type");
// Perform necessary checks to ensure Opcode is valid in the targeted shader
// kind
std::optional<size_t> StIndexOrErr =
getPropIndex(ArrayRef(Prop->Stages), DXILVersion);
- if (!StIndexOrErr.has_value()) {
- report_fatal_error(Twine(getOpCodeName(OpCode)) +
- ": No valid stages found for DXIL Version - " +
- DXILVersion.getAsString(),
- /*gen_crash_diag*/ false);
- }
+ if (!StIndexOrErr.has_value())
+ return makeOpError(OpCode, Twine("No valid stage for DXIL version ") +
+ DXILVersion.getAsString());
+
uint16_t ValidShaderKindMask = Prop->Stages[*StIndexOrErr].ValidStages;
// Ensure valid shader stage properties are specified
- if (ValidShaderKindMask == ShaderKind::removed) {
- report_fatal_error(
- Twine(DXILVersion.getAsString()) +
- ": Unsupported Target Shader Stage for DXIL operation - " +
- getOpCodeName(OpCode),
- /*gen_crash_diag*/ false);
- }
+ if (ValidShaderKindMask == ShaderKind::removed)
+ return makeOpError(OpCode, "Operation has been removed");
// Shader stage need not be validated since getShaderKindEnum() fails
// for unknown shader stage.
// Verify the target shader stage is valid for the DXIL operation
ShaderKind ModuleStagekind = getShaderKindEnum(ShaderStage);
- if (!(ValidShaderKindMask & ModuleStagekind)) {
- auto ShaderEnvStr = Triple::getEnvironmentTypeName(ShaderStage);
- report_fatal_error(Twine(ShaderEnvStr) +
- " : Invalid Shader Stage for DXIL operation - " +
- getOpCodeName(OpCode) + " for DXIL Version " +
- DXILVersion.getAsString(),
- /*gen_crash_diag*/ false);
- }
+ if (!(ValidShaderKindMask & ModuleStagekind))
+ return makeOpError(OpCode, "Invalid stage");
std::string DXILFnName = constructOverloadName(Kind, OverloadTy, *Prop);
- FunctionCallee DXILFn;
- // Get the function with name DXILFnName, if one exists
- if (auto *Func = M.getFunction(DXILFnName)) {
- DXILFn = FunctionCallee(Func);
- } else {
- // Construct and add a function with name DXILFnName
- FunctionType *DXILOpFT = getDXILOpFunctionType(Prop, ReturnTy, OverloadTy);
- DXILFn = M.getOrInsertFunction(DXILFnName, DXILOpFT);
- }
+ FunctionCallee DXILFn = M.getOrInsertFunction(DXILFnName, DXILOpFT);
- return B.CreateCall(DXILFn, Args);
-}
-
-Type *DXILOpBuilder::getOverloadTy(dxil::OpCode OpCode, FunctionType *FT) {
+ // We need to inject the opcode as the first argument.
+ SmallVector<Value *> OpArgs;
+ OpArgs.push_back(B.getInt32(llvm::to_underlying(OpCode)));
+ OpArgs.append(Args.begin(), Args.end());
- const OpCodeProperty *Prop = getOpCodeProperty(OpCode);
- // If DXIL Op has no overload parameter, just return the
- // precise return type specified.
- if (Prop->OverloadParamIndex < 0) {
- return 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);
- }
+ return B.CreateCall(DXILFn, OpArgs);
+}
- const ParameterKind *ParamKinds = getOpCodeParameterKind(*Prop);
- auto Kind = ParamKinds[Prop->OverloadParamIndex];
- // For ResRet and CBufferRet, OverloadTy is in field of StructType.
- if (Kind == ParameterKind::CBufferRet ||
- Kind == ParameterKind::ResourceRet) {
- auto *ST = cast<StructType>(OverloadType);
- OverloadType = ST->getElementType(0);
- }
- return OverloadType;
+CallInst *DXILOpBuilder::createOp(dxil::OpCode OpCode, ArrayRef<Value *> &Args,
+ Type *RetTy) {
+ Expected<CallInst *> Result = tryCreateOp(OpCode, Args, RetTy);
+ if (Error E = Result.takeError())
+ llvm_unreachable("Invalid arguments for operation");
+ return *Result;
}
const char *DXILOpBuilder::getOpCodeName(dxil::OpCode DXILOp) {
diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.h b/llvm/lib/Target/DirectX/DXILOpBuilder.h
index abb9a8d2b4cf8..ff66f39a3ceb3 100644
--- a/llvm/lib/Target/DirectX/DXILOpBuilder.h
+++ b/llvm/lib/Target/DirectX/DXILOpBuilder.h
@@ -15,6 +15,7 @@
#include "DXILConstants.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/TargetParser/Triple.h"
+#include "llvm/Support/Error.h"
namespace llvm {
class Module;
@@ -23,29 +24,44 @@ class CallInst;
class Value;
class Type;
class FunctionType;
-class Use;
namespace dxil {
class DXILOpBuilder {
public:
DXILOpBuilder(Module &M, IRBuilderBase &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 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,
- Type *OverloadTy, SmallVector<Value *> Args);
- Type *getOverloadTy(dxil::OpCode OpCode, FunctionType *FT);
+
+ /// Create a call instruction for the given DXIL op. The arguments
+ /// must be valid for an overload of the operation.
+ CallInst *createOp(dxil::OpCode Op, ArrayRef<Value *> &Args,
+ Type *RetTy = nullptr);
+
+#define DXIL_OPCODE(Op, Name) \
+ CallInst *create##Name##Op(ArrayRef<Value *> &Args, Type *RetTy = nullptr) { \
+ return createOp(dxil::OpCode(Op), Args, RetTy); \
+ }
+#include "DXILOperation.inc"
+
+ /// Try to create a call instruction for the given DXIL op. Fails if the
+ /// overload is invalid.
+ Expected<CallInst *> tryCreateOp(dxil::OpCode Op, ArrayRef<Value *> Args,
+ Type *RetTy = nullptr);
+#define DXIL_OPCODE(Op, Name) \
+ Expected<CallInst *> tryCreate##Name##Op(ArrayRef<Value *> &Args, \
+ Type *RetTy = nullptr) { \
+ return tryCreateOp(dxil::OpCode(Op), Args, RetTy); \
+ }
+#include "DXILOperation.inc"
+
+ /// Return the name of the given opcode.
static const char *getOpCodeName(dxil::OpCode DXILOp);
private:
+ /// Gets a specific overload type of the function for the given DXIL op. If
+ /// the operation is not overloaded, \c OverloadType may be nullptr.
+ FunctionType *getOpFunctionType(dxil::OpCode OpCode,
+ Type *OverloadType = nullptr);
+
Module &M;
IRBuilderBase &B;
VersionTuple DXILVersion;
diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
index 0c0edde43a277..5f84cdcfda6de 100644
--- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
@@ -16,6 +16,7 @@
#include "DirectX.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Intrinsics.h"
@@ -74,16 +75,13 @@ 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.getOverloadTy(DXILOp, F.getFunctionType());
+ DXILOpBuilder OpBuilder(M, B);
for (User *U : make_early_inc_range(F.users())) {
CallInst *CI = dyn_cast<CallInst>(U);
if (!CI)
continue;
SmallVector<Value *> Args;
- Value *DXILOpArg = B.getInt32(static_cast<unsigned>(DXILOp));
- Args.emplace_back(DXILOpArg);
B.SetInsertPoint(CI);
if (isVectorArgExpansion(F)) {
SmallVector<Value *> NewArgs = argVectorFlatten(CI, B);
@@ -91,10 +89,18 @@ 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);
+ Expected<CallInst *> OpCallOrErr = OpBuilder.tryCreateOp(DXILOp, Args,
+ F.getReturnType());
+ if (Error E = OpCallOrErr.takeError()) {
+ std::string Message(toString(std::move(E)));
+ DiagnosticInfoUnsupported Diag(*CI->getFunction(), Message,
+ CI->getDebugLoc());
+ M.getContext().diagnose(Diag);
+ continue;
+ }
+ CallInst *OpCall = *OpCallOrErr;
- CI->replaceAllUsesWith(DXILCI);
+ CI->replaceAllUsesWith(OpCall);
CI->eraseFromParent();
}
if (F.user_empty())
diff --git a/llvm/test/CodeGen/DirectX/acos_error.ll b/llvm/test/CodeGen/DirectX/acos_error.ll
index 4125709a57e7a..cba49cd0c7260 100644
--- a/llvm/test/CodeGen/DirectX/acos_error.ll
+++ b/llvm/test/CodeGen/DirectX/acos_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function acos_double
+; CHECK-SAME: Cannot create ACos operation: Invalid overload type
define noundef double @acos_double(double noundef %a) {
entry:
diff --git a/llvm/test/CodeGen/DirectX/asin_error.ll b/llvm/test/CodeGen/DirectX/asin_error.ll
index de63b0d6be027..78408ea7b64c5 100644
--- a/llvm/test/CodeGen/DirectX/asin_error.ll
+++ b/llvm/test/CodeGen/DirectX/asin_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function asin_double
+; CHECK-SAME: Cannot create ASin operation: Invalid overload type
define noundef double @asin_double(double noundef %a) {
entry:
diff --git a/llvm/test/CodeGen/DirectX/atan_error.ll b/llvm/test/CodeGen/DirectX/atan_error.ll
index c320868ef4e57..b51e2eb5af7d8 100644
--- a/llvm/test/CodeGen/DirectX/atan_error.ll
+++ b/llvm/test/CodeGen/DirectX/atan_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function atan_double
+; CHECK-SAME: Cannot create ATan operation: Invalid overload type
define noundef double @atan_double(double noundef %a) {
entry:
diff --git a/llvm/test/CodeGen/DirectX/ceil_error.ll b/llvm/test/CodeGen/DirectX/ceil_error.ll
index da6f083550186..0188b6d8d5c76 100644
--- a/llvm/test/CodeGen/DirectX/ceil_error.ll
+++ b/llvm/test/CodeGen/DirectX/ceil_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function ceil_double
+; CHECK-SAME: Cannot create Ceil operation: Invalid overload type
define noundef double @ceil_double(double noundef %a) {
entry:
diff --git a/llvm/test/CodeGen/DirectX/cos_error.ll b/llvm/test/CodeGen/DirectX/cos_error.ll
index 6bb85a7cec1e3..6e3513490f781 100644
--- a/llvm/test/CodeGen/DirectX/cos_error.ll
+++ b/llvm/test/CodeGen/DirectX/cos_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function cos_double
+; CHECK-SAME: Cannot create Cos operation: Invalid overload type
define noundef double @cos_double(double noundef %a) {
entry:
diff --git a/llvm/test/CodeGen/DirectX/cosh_error.ll b/llvm/test/CodeGen/DirectX/cosh_error.ll
index 4c5f0c7146ab5..604e9686043f8 100644
--- a/llvm/test/CodeGen/DirectX/cosh_error.ll
+++ b/llvm/test/CodeGen/DirectX/cosh_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function cosh_double
+; CHECK-SAME: Cannot create HCos operation: Invalid overload type
define noundef double @cosh_double(double noundef %a) {
entry:
diff --git a/llvm/test/CodeGen/DirectX/dot2_error.ll b/llvm/test/CodeGen/DirectX/dot2_error.ll
index 54780d18e71fb..97b025d36f018 100644
--- a/llvm/test/CodeGen/DirectX/dot2_error.ll
+++ b/llvm/test/CodeGen/DirectX/dot2_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function dot_double2
+; CHECK-SAME: Cannot create Dot2 operation: Invalid overload type
define noundef double @dot_double2(<2 x double> noundef %a, <2 x double> noundef %b) {
entry:
diff --git a/llvm/test/CodeGen/DirectX/dot3_error.ll b/llvm/test/CodeGen/DirectX/dot3_error.ll
index 242716b0b71ba..3b5dc41ebeb6b 100644
--- a/llvm/test/CodeGen/DirectX/dot3_error.ll
+++ b/llvm/test/CodeGen/DirectX/dot3_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function dot_double3
+; CHECK-SAME: Cannot create Dot3 operation: Invalid overload type
define noundef double @dot_double3(<3 x double> noundef %a, <3 x double> noundef %b) {
entry:
diff --git a/llvm/test/CodeGen/DirectX/dot4_error.ll b/llvm/test/CodeGen/DirectX/dot4_error.ll
index 731adda153def..0a5969616220e 100644
--- a/llvm/test/CodeGen/DirectX/dot4_error.ll
+++ b/llvm/test/CodeGen/DirectX/dot4_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function dot_double4
+; CHECK-SAME: Cannot create Dot4 operation: Invalid overload type
define noundef double @dot_double4(<4 x double> noundef %a, <4 x double> noundef %b) {
entry:
diff --git a/llvm/test/CodeGen/DirectX/exp2_error.ll b/llvm/test/CodeGen/DirectX/exp2_error.ll
index 4d13f936eb6be..94e577932fe98 100644
--- a/llvm/test/CodeGen/DirectX/exp2_error.ll
+++ b/llvm/test/CodeGen/DirectX/exp2_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function exp2_double
+; CHECK-SAME: Cannot create Exp2 operation: Invalid overload type
define noundef double @exp2_double(double noundef %a) #0 {
entry:
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 9abea5e82868f..b5cc913f3f3dd 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
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function test_flattened_thread_id_in_group
+; CHECK-SAME: Cannot create FlattenedThreadIdInGroup operation: Invalid stage
target triple = "dxil-pc-shadermodel6.7-library"
diff --git a/llvm/test/CodeGen/DirectX/floor_error.ll b/llvm/test/CodeGen/DirectX/floor_error.ll
index e3190e5afb63f..7b4646fc5e103 100644
--- a/llvm/test/CodeGen/DirectX/floor_error.ll
+++ b/llvm/test/CodeGen/DirectX/floor_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function floor_double
+; CHECK-SAME: Cannot create Floor operation: Invalid overload type
define noundef double @floor_double(double noundef %a) {
entry:
diff --git a/llvm/test/CodeGen/DirectX/frac_error.ll b/llvm/test/CodeGen/DirectX/frac_error.ll
index 1bc3558ab0c9a..4d997516467b5 100644
--- a/llvm/test/CodeGen/DirectX/frac_error.ll
+++ b/llvm/test/CodeGen/DirectX/frac_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function frac_double
+; CHECK-SAME: Cannot create Frac operation: Invalid overload type
; Function Attrs: noinline nounwind optnone
define noundef double @frac_double(double noundef %a) #0 {
diff --git a/llvm/test/CodeGen/DirectX/group_id_error.ll b/llvm/test/CodeGen/DirectX/group_id_error.ll
index 2a6adcf2a9362..e438984eeb805 100644
--- a/llvm/test/CodeGen/DirectX/group_id_error.ll
+++ b/llvm/test/CodeGen/DirectX/group_id_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function test_group_id
+; CHECK-SAME: Cannot create GroupId operation: Invalid stage
target triple = "dxil-pc-shadermodel6.7-pixel"
diff --git a/llvm/test/CodeGen/DirectX/isinf_error.ll b/llvm/test/CodeGen/DirectX/isinf_error.ll
index 39b83554d74d0..1a9fa653109d3 100644
--- a/llvm/test/CodeGen/DirectX/isinf_error.ll
+++ b/llvm/test/CodeGen/DirectX/isinf_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function isinf_double
+; CHECK-SAME: Cannot create IsInf operation: Invalid overload type
define noundef i1 @isinf_double(double noundef %a) #0 {
entry:
diff --git a/llvm/test/CodeGen/DirectX/log2_error.ll b/llvm/test/CodeGen/DirectX/log2_error.ll
index b8876854d389f..fee8514214851 100644
--- a/llvm/test/CodeGen/DirectX/log2_error.ll
+++ b/llvm/test/CodeGen/DirectX/log2_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function log2_double
+; CHECK-SAME: Cannot create Log2 operation: Invalid overload type
define noundef double @log2_double(double noundef %a) {
entry:
diff --git a/llvm/test/CodeGen/DirectX/round_error.ll b/llvm/test/CodeGen/DirectX/round_error.ll
index 9d2a4e778a924..081a5eb9e1f7f 100644
--- a/llvm/test/CodeGen/DirectX/round_error.ll
+++ b/llvm/test/CodeGen/DirectX/round_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function round_double
+; CHECK-SAME: Cannot create Round operation: Invalid overload type
define noundef double @round_double(double noundef %a) #0 {
entry:
diff --git a/llvm/test/CodeGen/DirectX/rsqrt_error.ll b/llvm/test/CodeGen/DirectX/rsqrt_error.ll
index 5e29e37113d19..85d452f436533 100644
--- a/llvm/test/CodeGen/DirectX/rsqrt_error.ll
+++ b/llvm/test/CodeGen/DirectX/rsqrt_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function rsqrt_double
+; CHECK-SAME: Cannot create RSqrt operation: Invalid overload type
; Function Attrs: noinline nounwind optnone
define noundef double @rsqrt_double(double noundef %a) #0 {
diff --git a/llvm/test/CodeGen/DirectX/sin_error.ll b/llvm/test/CodeGen/DirectX/sin_error.ll
index 0e20031501365..f1af604309c48 100644
--- a/llvm/test/CodeGen/DirectX/sin_error.ll
+++ b/llvm/test/CodeGen/DirectX/sin_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function sin_double
+; CHECK-SAME: Cannot create Sin operation: Invalid overload type
define noundef double @sin_double(double noundef %a) #0 {
entry:
@@ -11,4 +12,3 @@ entry:
%1 = call double @llvm.sin.f64(double %0)
ret double %1
}
-
diff --git a/llvm/test/CodeGen/DirectX/sinh_error.ll b/llvm/test/CodeGen/DirectX/sinh_error.ll
index 06aeca0339261..01b6e2f168572 100644
--- a/llvm/test/CodeGen/DirectX/sinh_error.ll
+++ b/llvm/test/CodeGen/DirectX/sinh_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function sinh_double
+; CHECK-SAME: Cannot create HSin operation: Invalid overload type
define noundef double @sinh_double(double noundef %a) {
entry:
diff --git a/llvm/test/CodeGen/DirectX/sqrt_error.ll b/llvm/test/CodeGen/DirectX/sqrt_error.ll
index 1477abc62c13a..af1b0d0cc5144 100644
--- a/llvm/test/CodeGen/DirectX/sqrt_error.ll
+++ b/llvm/test/CodeGen/DirectX/sqrt_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function sqrt_double
+; CHECK-SAME: Cannot create Sqrt operation: Invalid overload type
define noundef double @sqrt_double(double noundef %a) {
entry:
diff --git a/llvm/test/CodeGen/DirectX/tan_error.ll b/llvm/test/CodeGen/DirectX/tan_error.ll
index fa03e531bd672..3a310e8652a89 100644
--- a/llvm/test/CodeGen/DirectX/tan_error.ll
+++ b/llvm/test/CodeGen/DirectX/tan_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function tan_double
+; CHECK-SAME: Cannot create Tan operation: Invalid overload type
define noundef double @tan_double(double noundef %a) #0 {
entry:
diff --git a/llvm/test/CodeGen/DirectX/tanh_error.ll b/llvm/test/CodeGen/DirectX/tanh_error.ll
index 933ffbc87e23f..b72e590aa78a9 100644
--- a/llvm/test/CodeGen/DirectX/tanh_error.ll
+++ b/llvm/test/CodeGen/DirectX/tanh_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function tanh_double
+; CHECK-SAME: Cannot create HTan operation: Invalid overload type
define noundef double @tanh_double(double noundef %a) {
entry:
diff --git a/llvm/test/CodeGen/DirectX/thread_id_error.ll b/llvm/test/CodeGen/DirectX/thread_id_error.ll
index 6928932328fbe..f973b5a1bf280 100644
--- a/llvm/test/CodeGen/DirectX/thread_id_error.ll
+++ b/llvm/test/CodeGen/DirectX/thread_id_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function test_thread_id
+; CHECK-SAME: Cannot create ThreadId operation: Invalid stage
target triple = "dxil-pc-shadermodel6.7-library"
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 8b63fd7bae543..74a45ac3285d8 100644
--- a/llvm/test/CodeGen/DirectX/thread_id_in_group_error.ll
+++ b/llvm/test/CodeGen/DirectX/thread_id_in_group_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function test_thread_id_in_group
+; CHECK-SAME: Cannot create ThreadIdInGroup operation: Invalid stage
target triple = "dxil-pc-shadermodel6.7-vertex"
diff --git a/llvm/test/CodeGen/DirectX/trunc_error.ll b/llvm/test/CodeGen/DirectX/trunc_error.ll
index ccc7b1df879ee..a4b48e102758b 100644
--- a/llvm/test/CodeGen/DirectX/trunc_error.ll
+++ b/llvm/test/CodeGen/DirectX/trunc_error.ll
@@ -1,7 +1,8 @@
; 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
+; CHECK: in function trunc_double
+; CHECK-SAME: Cannot create Trunc operation: Invalid overload type
define noundef double @trunc_double(double noundef %a) {
entry:
diff --git a/llvm/utils/TableGen/DXILEmitter.cpp b/llvm/utils/TableGen/DXILEmitter.cpp
index 8e54ead5ac484..53791618e80fe 100644
--- a/llvm/utils/TableGen/DXILEmitter.cpp
+++ b/llvm/utils/TableGen/DXILEmitter.cpp
@@ -132,49 +132,25 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) {
// resolve an LLVMMatchType in accordance with convention outlined in
// the comment before the definition of class LLVMMatchType in
// llvm/IR/Intrinsics.td
- SmallVector<int> OverloadParamIndices;
+ OverloadParamIndex = -1; // A sigil meaning none.
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) {
- // All overload types in a DXIL Op are required to be of the same type.
- if (!OverloadParamIndices.empty()) {
- [[maybe_unused]] bool knownType = true;
- // Ensure that the same overload type registered earlier is being used
- for (auto Idx : OverloadParamIndices) {
- if (TR != ParamTypeRecs[Idx]) {
- knownType = false;
- break;
- }
- }
- assert(knownType && "Specification of multiple
diff ering overload "
- "parameter types not yet supported");
- } else {
- OverloadParamIndices.push_back(i);
+ if (OverloadParamIndex != -1) {
+ assert(TR == ParamTypeRecs[OverloadParamIndex] &&
+ "Specification of multiple
diff ering overload parameter types "
+ "is not supported");
}
+ // Keep the earliest parameter index we see, but if it was the return type
+ // overwrite it with the first overloaded argument.
+ if (OverloadParamIndex <= 0)
+ OverloadParamIndex = i;
}
- // Populate OpTypes array according to the type specification
- if (TR->isAnonymous()) {
- // Check prior overload types exist
- assert(!OverloadParamIndices.empty() &&
- "No prior overloaded parameter found to match.");
- // 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(ParamTypeRecs[OLParamIndex]);
- } else {
- // A non-anonymous type. Just record it in OpTypes
- OpTypes.emplace_back(TR);
- }
- }
-
- // Set the index of the overload parameter, if any.
- OverloadParamIndex = -1; // default; indicating none
- if (!OverloadParamIndices.empty()) {
- assert(OverloadParamIndices.size() == 1 &&
- "Multiple overload type specification not supported");
- OverloadParamIndex = OverloadParamIndices[0];
+ if (TR->isAnonymous())
+ PrintFatalError(TR, "Only concrete types are allowed here");
+ OpTypes.emplace_back(TR);
}
// Get overload records
@@ -490,8 +466,7 @@ static void emitDXILOperationTable(std::vector<DXILOperationDesc> &Ops,
ClassSet.insert(Op.OpClass);
OpClassStrings.add(Op.OpClass.data());
SmallVector<ParameterKind> ParamKindVec;
- // ParamKindVec is a vector of parameters. Skip return type at index 0
- for (unsigned i = 1; i < Op.OpTypes.size(); i++) {
+ for (unsigned i = 0; i < Op.OpTypes.size(); i++) {
ParamKindVec.emplace_back(getParameterKind(Op.OpTypes[i]));
}
ParameterMap[Op.OpClass] = ParamKindVec;
@@ -511,23 +486,13 @@ static void emitDXILOperationTable(std::vector<DXILOperationDesc> &Ops,
OS << " static const OpCodeProperty OpCodeProps[] = {\n";
std::string Prefix = "";
for (auto &Op : Ops) {
- // Consider Op.OverloadParamIndex as the overload parameter index, by
- // default
- auto OLParamIdx = Op.OverloadParamIndex;
- // If no overload parameter index is set, treat first parameter type as
- // overload type - unless the Op has no parameters, in which case treat the
- // return type - as overload parameter to emit the appropriate overload kind
- // enum.
- if (OLParamIdx < 0) {
- OLParamIdx = (Op.OpTypes.size() > 1) ? 1 : 0;
- }
OS << Prefix << " { dxil::OpCode::" << Op.OpName << ", "
<< OpStrings.get(Op.OpName) << ", OpCodeClass::" << Op.OpClass << ", "
<< OpClassStrings.get(Op.OpClass.data()) << ", "
<< getOverloadMaskString(Op.OverloadRecs) << ", "
<< getStageMaskString(Op.StageRecs) << ", "
<< getAttributeMaskString(Op.AttrRecs) << ", " << Op.OverloadParamIndex
- << ", " << Op.OpTypes.size() - 1 << ", "
+ << ", " << Op.OpTypes.size() << ", "
<< Parameters.get(ParameterMap[Op.OpClass]) << " }";
Prefix = ",\n";
}
More information about the llvm-commits
mailing list