-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[SPIR-V] Support all the instructions of SPV_KHR_integer_dot_product #123792
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SPIR-V] Support all the instructions of SPV_KHR_integer_dot_product #123792
Conversation
This continues the work on dot product instructions already started in 3cdac06. This change adds support for all OpenCL integer dot product builtins.
|
@llvm/pr-subscribers-backend-spir-v Author: Viktoria Maximova (vmaksimo) ChangesThis continues the work on dot product instructions already started in This change adds support for all OpenCL integer dot product builtins. Patch is 20.92 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/123792.diff 7 Files Affected:
diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index b52c793e57e968..22d681c56730d4 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -132,6 +132,15 @@ struct ImageQueryBuiltin {
#define GET_ImageQueryBuiltins_DECL
#define GET_ImageQueryBuiltins_IMPL
+struct IntegerDotProductBuiltin {
+ StringRef Name;
+ uint32_t Opcode;
+ bool IsSwapReq;
+};
+
+#define GET_IntegerDotProductBuiltins_DECL
+#define GET_IntegerDotProductBuiltins_IMPL
+
struct ConvertBuiltin {
StringRef Name;
InstructionSet::InstructionSet Set;
@@ -1579,20 +1588,84 @@ static bool generateCastToPtrInst(const SPIRV::IncomingCall *Call,
return true;
}
-static bool generateDotOrFMulInst(const SPIRV::IncomingCall *Call,
+static bool generateDotOrFMulInst(const StringRef DemangledCall,
+ const SPIRV::IncomingCall *Call,
MachineIRBuilder &MIRBuilder,
SPIRVGlobalRegistry *GR) {
if (Call->isSpirvOp())
return buildOpFromWrapper(MIRBuilder, SPIRV::OpDot, Call,
GR->getSPIRVTypeID(Call->ReturnType));
- unsigned Opcode = GR->getSPIRVTypeForVReg(Call->Arguments[0])->getOpcode();
- bool IsVec = Opcode == SPIRV::OpTypeVector;
+
+ bool IsVec = GR->getSPIRVTypeForVReg(Call->Arguments[0])->getOpcode() ==
+ SPIRV::OpTypeVector;
// Use OpDot only in case of vector args and OpFMul in case of scalar args.
- MIRBuilder.buildInstr(IsVec ? SPIRV::OpDot : SPIRV::OpFMulS)
- .addDef(Call->ReturnRegister)
- .addUse(GR->getSPIRVTypeID(Call->ReturnType))
- .addUse(Call->Arguments[0])
- .addUse(Call->Arguments[1]);
+ uint32_t OC = IsVec ? SPIRV::OpDot : SPIRV::OpFMulS;
+ bool IsSwapReq = false;
+
+ const auto *ST =
+ static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());
+ if (GR->isScalarOrVectorOfType(Call->ReturnRegister, SPIRV::OpTypeInt) &&
+ (ST->canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
+ ST->isAtLeastSPIRVVer(VersionTuple(1, 6)))) {
+ const SPIRV::DemangledBuiltin *Builtin = Call->Builtin;
+ const SPIRV::IntegerDotProductBuiltin *IntDot =
+ SPIRV::lookupIntegerDotProductBuiltin(Builtin->Name);
+ if (IntDot) {
+ OC = IntDot->Opcode;
+ IsSwapReq = IntDot->IsSwapReq;
+ } else if (IsVec) {
+ // Handling "dot" and "dot_acc_sat" builtins which use vectors of
+ // integers.
+ LLVMContext &Ctx = MIRBuilder.getContext();
+ SmallVector<StringRef, 10> TypeStrs;
+ SPIRV::parseBuiltinTypeStr(TypeStrs, DemangledCall, Ctx);
+ bool IsFirstSigned = TypeStrs[0].trim()[0] != 'u';
+ bool IsSecondSigned = TypeStrs[1].trim()[0] != 'u';
+
+ if (Call->BuiltinName == "dot") {
+ if (IsFirstSigned && IsSecondSigned)
+ OC = SPIRV::OpSDot;
+ else if (!IsFirstSigned && !IsSecondSigned)
+ OC = SPIRV::OpUDot;
+ else {
+ OC = SPIRV::OpSUDot;
+ if (!IsFirstSigned)
+ IsSwapReq = true;
+ }
+ } else if (Call->BuiltinName == "dot_acc_sat") {
+ if (IsFirstSigned && IsSecondSigned)
+ OC = SPIRV::OpSDotAccSat;
+ else if (!IsFirstSigned && !IsSecondSigned)
+ OC = SPIRV::OpUDotAccSat;
+ else {
+ OC = SPIRV::OpSUDotAccSat;
+ if (!IsFirstSigned)
+ IsSwapReq = true;
+ }
+ }
+ }
+ }
+
+ MachineInstrBuilder MIB = MIRBuilder.buildInstr(OC)
+ .addDef(Call->ReturnRegister)
+ .addUse(GR->getSPIRVTypeID(Call->ReturnType));
+
+ if (IsSwapReq) {
+ MIB.addUse(Call->Arguments[1]);
+ MIB.addUse(Call->Arguments[0]);
+ // needed for dot_acc_sat* builtins
+ for (size_t i = 2; i < Call->Arguments.size(); ++i)
+ MIB.addUse(Call->Arguments[i]);
+ } else {
+ for (size_t i = 0; i < Call->Arguments.size(); ++i)
+ MIB.addUse(Call->Arguments[i]);
+ }
+
+ // Add Packed Vector Format for Integer dot product builtins if arguments are
+ // scalar
+ if (!IsVec && OC != SPIRV::OpFMulS)
+ MIB.addImm(0);
+
return true;
}
@@ -2582,6 +2655,11 @@ mapBuiltinToOpcode(const StringRef DemangledCall,
if (const auto *R = SPIRV::lookupGroupUniformBuiltin(Call->Builtin->Name))
return std::make_tuple(Call->Builtin->Group, R->Opcode, 0);
break;
+ case SPIRV::IntegerDot:
+ if (const auto *R =
+ SPIRV::lookupIntegerDotProductBuiltin(Call->Builtin->Name))
+ return std::make_tuple(Call->Builtin->Group, R->Opcode, 0);
+ break;
case SPIRV::WriteImage:
return std::make_tuple(Call->Builtin->Group, SPIRV::OpImageWrite, 0);
case SPIRV::Select:
@@ -2641,7 +2719,8 @@ std::optional<bool> lowerBuiltin(const StringRef DemangledCall,
case SPIRV::CastToPtr:
return generateCastToPtrInst(Call.get(), MIRBuilder);
case SPIRV::Dot:
- return generateDotOrFMulInst(Call.get(), MIRBuilder, GR);
+ case SPIRV::IntegerDot:
+ return generateDotOrFMulInst(DemangledCall, Call.get(), MIRBuilder, GR);
case SPIRV::Wave:
return generateWaveInst(Call.get(), MIRBuilder, GR);
case SPIRV::ICarryBorrow:
diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
index af3901c0e621eb..9a682bb36416b7 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
@@ -42,6 +42,7 @@ def Variable : BuiltinGroup;
def Atomic : BuiltinGroup;
def Barrier : BuiltinGroup;
def Dot : BuiltinGroup;
+def IntegerDot : BuiltinGroup;
def Wave : BuiltinGroup;
def GetQuery : BuiltinGroup;
def ImageSizeQuery : BuiltinGroup;
@@ -101,6 +102,8 @@ def lookupBuiltin : SearchIndex {
// Dot builtin record:
def : DemangledBuiltin<"dot", OpenCL_std, Dot, 2, 2>;
def : DemangledBuiltin<"__spirv_Dot", OpenCL_std, Dot, 2, 2>;
+def : DemangledBuiltin<"dot_acc_sat", OpenCL_std, IntegerDot, 3, 3>;
+def : DemangledBuiltin<"__spirv_DotAccSat", OpenCL_std, IntegerDot, 3, 3>;
// Image builtin records:
def : DemangledBuiltin<"read_imagei", OpenCL_std, ReadImage, 2, 4>;
@@ -1715,3 +1718,47 @@ class CLMemoryFenceFlags<bits<32> value> {
def CLK_LOCAL_MEM_FENCE : CLMemoryFenceFlags<0x1>;
def CLK_GLOBAL_MEM_FENCE : CLMemoryFenceFlags<0x2>;
def CLK_IMAGE_MEM_FENCE : CLMemoryFenceFlags<0x4>;
+
+//===----------------------------------------------------------------------===//
+// Class defining dot builtins that should be translated into a
+// SPIR-V instruction using the SPV_KHR_integer_dot_product extension.
+//
+// name is the demangled name of the given builtin.
+// opcode specifies the SPIR-V operation code of the generated instruction.
+// isSwapRequired specifies if the operands need to be swapped (the SPIR-V extension
+// has only one instruction for arguments of different signedness).
+//===----------------------------------------------------------------------===//
+class IntegerDotProductBuiltin<string name, Op operation> {
+ string Name = name;
+ Op Opcode = operation;
+ bit IsSwapReq = !not(!eq(!find(name, "_us"), -1));
+}
+
+// Table gathering all the integer dot product builtins.
+def IntegerDotProductBuiltins : GenericTable {
+ let FilterClass = "IntegerDotProductBuiltin";
+ let Fields = ["Name", "Opcode", "IsSwapReq"];
+}
+
+// Function to lookup group builtins by their name and set.
+def lookupIntegerDotProductBuiltin : SearchIndex {
+ let Table = IntegerDotProductBuiltins;
+ let Key = ["Name"];
+}
+
+// Multiclass used to define incoming builtin records for the SPV_KHR_integer_dot_product extension.
+multiclass DemangledIntegerDotProductBuiltin<string name, bits<8> minNumArgs, bits<8> maxNumArgs, Op operation> {
+ def : DemangledBuiltin<!strconcat("dot", name), OpenCL_std, IntegerDot, minNumArgs, maxNumArgs>;
+ def : IntegerDotProductBuiltin<!strconcat("dot", name), operation>;
+}
+
+// cl_khr_integer_dot_product
+defm : DemangledIntegerDotProductBuiltin<"_4x8packed_uu_uint", 2, 3, OpUDot>;
+defm : DemangledIntegerDotProductBuiltin<"_4x8packed_ss_int", 2, 3, OpSDot>;
+defm : DemangledIntegerDotProductBuiltin<"_4x8packed_us_int", 2, 3, OpSUDot>;
+defm : DemangledIntegerDotProductBuiltin<"_4x8packed_su_int", 2, 3, OpSUDot>;
+
+defm : DemangledIntegerDotProductBuiltin<"_acc_sat_4x8packed_uu_uint", 3, 4, OpUDotAccSat>;
+defm : DemangledIntegerDotProductBuiltin<"_acc_sat_4x8packed_ss_int", 3, 4, OpSDotAccSat>;
+defm : DemangledIntegerDotProductBuiltin<"_acc_sat_4x8packed_us_int", 3, 4, OpSUDotAccSat>;
+defm : DemangledIntegerDotProductBuiltin<"_acc_sat_4x8packed_su_int", 3, 4, OpSUDotAccSat>;
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td
index 1bc35c6e57a4f6..981e224a663993 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td
+++ b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td
@@ -530,8 +530,18 @@ defm OpISubBorrow: BinOpTypedGen<"OpISubBorrow", 150, subc, 0, 1>;
def OpUMulExtended: BinOp<"OpUMulExtended", 151>;
def OpSMulExtended: BinOp<"OpSMulExtended", 152>;
-def OpSDot: BinOp<"OpSDot", 4450>;
-def OpUDot: BinOp<"OpUDot", 4451>;
+def OpSDot: Op<4450, (outs ID:$res), (ins TYPE:$type, ID:$vec1, ID:$vec2, variable_ops),
+ "$res = OpSDot $type $vec1 $vec2">;
+def OpUDot: Op<4451, (outs ID:$res), (ins TYPE:$type, ID:$vec1, ID:$vec2, variable_ops),
+ "$res = OpUDot $type $vec1 $vec2">;
+def OpSUDot: Op<4452, (outs ID:$res), (ins TYPE:$type, ID:$vec1, ID:$vec2, variable_ops),
+ "$res = OpSUDot $type $vec1 $vec2">;
+def OpSDotAccSat: Op<4453, (outs ID:$res), (ins TYPE:$type, ID:$vec1, ID:$vec2, ID:$acc, variable_ops),
+ "$res = OpSDotAccSat $type $vec1 $vec2 $acc">;
+def OpUDotAccSat: Op<4454, (outs ID:$res), (ins TYPE:$type, ID:$vec1, ID:$vec2, ID:$acc, variable_ops),
+ "$res = OpUDotAccSat $type $vec1 $vec2 $acc">;
+def OpSUDotAccSat: Op<4455, (outs ID:$res), (ins TYPE:$type, ID:$vec1, ID:$vec2, ID:$acc, variable_ops),
+ "$res = OpSUDotAccSat $type $vec1 $vec2 $acc">;
// 3.42.14 Bit Instructions
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index bc00d5032544fd..631a65d7678938 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -1690,6 +1690,10 @@ void addInstrRequirements(const MachineInstr &MI,
break;
case SPIRV::OpSDot:
case SPIRV::OpUDot:
+ case SPIRV::OpSUDot:
+ case SPIRV::OpSDotAccSat:
+ case SPIRV::OpUDotAccSat:
+ case SPIRV::OpSUDotAccSat:
AddDotProductRequirements(MI, Reqs, ST);
break;
case SPIRV::OpImageRead: {
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_integer_dot_product/SPV_KHR_integer_dot_product_OCLtoSPIRV_char4.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_integer_dot_product/SPV_KHR_integer_dot_product_OCLtoSPIRV_char4.ll
new file mode 100644
index 00000000000000..f2e31437219148
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_integer_dot_product/SPV_KHR_integer_dot_product_OCLtoSPIRV_char4.ll
@@ -0,0 +1,54 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_integer_dot_product %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_integer_dot_product %s -o - -filetype=obj | spirv-val %}
+
+; CHECK: Capability DotProduct
+; CHECK: Capability DotProductInput4x8Bit
+
+; CHECK: Name %[[#SignedA:]] "ia"
+; CHECK: Name %[[#UnsignedA:]] "ua"
+; CHECK: Name %[[#SignedB:]] "ib"
+; CHECK: Name %[[#UnsignedB:]] "ub"
+
+; CHECK: SDot %[[#]] %[[#SignedA]] %[[#SignedB]]
+; CHECK: SUDot %[[#]] %[[#SignedA]] %[[#UnsignedB]]
+; CHECK: SUDot %[[#]] %[[#SignedB]] %[[#UnsignedA]]
+; CHECK: UDot %[[#]] %[[#UnsignedA]] %[[#UnsignedB]]
+
+; CHECK: SDotAccSat %[[#]] %[[#SignedA]] %[[#SignedB]] %[[#]]
+; CHECK: SUDotAccSat %[[#]] %[[#SignedA]] %[[#UnsignedB]] %[[#]]
+; CHECK: SUDotAccSat %[[#]] %[[#SignedB]] %[[#UnsignedA]] %[[#]]
+; CHECK: UDotAccSat %[[#]] %[[#UnsignedA]] %[[#UnsignedB]] %[[#]]
+
+define spir_kernel void @test1(<4 x i8> %ia, <4 x i8> %ua, <4 x i8> %ib, <4 x i8> %ub, <4 x i8> %ires, <4 x i8> %ures) !kernel_arg_addr_space !3 !kernel_arg_access_qual !4 !kernel_arg_type !5 !kernel_arg_base_type !6 !kernel_arg_type_qual !7 {
+entry:
+ %call = tail call spir_func i32 @_Z3dotDv4_cS_(<4 x i8> %ia, <4 x i8> %ib) #2
+ %call1 = tail call spir_func i32 @_Z3dotDv4_cDv4_h(<4 x i8> %ia, <4 x i8> %ub) #2
+ %call2 = tail call spir_func i32 @_Z3dotDv4_hDv4_c(<4 x i8> %ua, <4 x i8> %ib) #2
+ %call3 = tail call spir_func i32 @_Z3dotDv4_hS_(<4 x i8> %ua, <4 x i8> %ub) #2
+ %call4 = tail call spir_func i32 @_Z11dot_acc_satDv4_cS_i(<4 x i8> %ia, <4 x i8> %ib, i32 %call2) #2
+ %call5 = tail call spir_func i32 @_Z11dot_acc_satDv4_cDv4_hi(<4 x i8> %ia, <4 x i8> %ub, i32 %call4) #2
+ %call6 = tail call spir_func i32 @_Z11dot_acc_satDv4_hDv4_ci(<4 x i8> %ua, <4 x i8> %ib, i32 %call5) #2
+ %call7 = tail call spir_func i32 @_Z11dot_acc_satDv4_hS_j(<4 x i8> %ua, <4 x i8> %ub, i32 %call3) #2
+ ret void
+}
+
+declare spir_func i32 @_Z3dotDv4_cS_(<4 x i8>, <4 x i8>)
+declare spir_func i32 @_Z3dotDv4_cDv4_h(<4 x i8>, <4 x i8>)
+declare spir_func i32 @_Z3dotDv4_hDv4_c(<4 x i8>, <4 x i8>)
+declare spir_func i32 @_Z3dotDv4_hS_(<4 x i8>, <4 x i8>)
+declare spir_func i32 @_Z11dot_acc_satDv4_cS_i(<4 x i8>, <4 x i8>, i32)
+declare spir_func i32 @_Z11dot_acc_satDv4_cDv4_hi(<4 x i8>, <4 x i8>, i32)
+declare spir_func i32 @_Z11dot_acc_satDv4_hDv4_ci(<4 x i8>, <4 x i8>, i32)
+declare spir_func i32 @_Z11dot_acc_satDv4_hS_j(<4 x i8>, <4 x i8>, i32)
+
+!llvm.module.flags = !{!0}
+!opencl.ocl.version = !{!1}
+!opencl.spir.version = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 2, i32 0}
+!3 = !{i32 0, i32 0, i32 0, i32 0, i32 0, i32 0}
+!4 = !{!"none", !"none", !"none", !"none", !"none", !"none"}
+!5 = !{!"char4", !"uchar4", !"char4", !"uchar4", !"char4", !"uchar4"}
+!6 = !{!"char __attribute__((ext_vector_type(4)))", !"uchar __attribute__((ext_vector_type(4)))", !"char __attribute__((ext_vector_type(4)))", !"uchar __attribute__((ext_vector_type(4)))", !"char __attribute__((ext_vector_type(4)))", !"uchar __attribute__((ext_vector_type(4)))"}
+!7 = !{!"", !"", !"", !"", !"", !""}
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_integer_dot_product/SPV_KHR_integer_dot_product_OCLtoSPIRV_int.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_integer_dot_product/SPV_KHR_integer_dot_product_OCLtoSPIRV_int.ll
new file mode 100644
index 00000000000000..0702ad22b31e8b
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_integer_dot_product/SPV_KHR_integer_dot_product_OCLtoSPIRV_int.ll
@@ -0,0 +1,53 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_integer_dot_product %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_integer_dot_product %s -o - -filetype=obj | spirv-val %}
+
+; CHECK: Capability DotProduct
+; CHECK: Capability DotProductInput4x8BitPacked
+
+; CHECK: Name %[[#SignedA:]] "ia"
+; CHECK: Name %[[#UnsignedA:]] "ua"
+; CHECK: Name %[[#SignedB:]] "ib"
+; CHECK: Name %[[#UnsignedB:]] "ub"
+
+; CHECK: SDot %[[#]] %[[#SignedA]] %[[#SignedB]] 0
+; CHECK: SUDot %[[#]] %[[#SignedA]] %[[#UnsignedB]] 0
+; CHECK: SUDot %[[#]] %[[#SignedB]] %[[#UnsignedA]] 0
+; CHECK: UDot %[[#]] %[[#UnsignedA]] %[[#UnsignedB]] 0
+
+; CHECK: SDotAccSat %[[#]] %[[#SignedA]] %[[#SignedB]] %[[#]] 0
+; CHECK: SUDotAccSat %[[#]] %[[#SignedA]] %[[#UnsignedB]] %[[#]] 0
+; CHECK: SUDotAccSat %[[#]] %[[#SignedB]] %[[#UnsignedA]] %[[#]] 0
+; CHECK: UDotAccSat %[[#]] %[[#UnsignedA]] %[[#UnsignedB]] %[[#]] 0
+
+define spir_kernel void @test1(i32 %ia, i32 %ua, i32 %ib, i32 %ub, i32 %ires, i32 %ures) !kernel_arg_addr_space !3 !kernel_arg_access_qual !4 !kernel_arg_type !5 !kernel_arg_base_type !5 !kernel_arg_type_qual !6 {
+entry:
+ %call = tail call spir_func i32 @_Z20dot_4x8packed_ss_intjj(i32 %ia, i32 %ib) #2
+ %call1 = tail call spir_func i32 @_Z20dot_4x8packed_su_intjj(i32 %ia, i32 %ub) #2
+ %call2 = tail call spir_func i32 @_Z20dot_4x8packed_us_intjj(i32 %ua, i32 %ib) #2
+ %call3 = tail call spir_func i32 @_Z21dot_4x8packed_uu_uintjj(i32 %ua, i32 %ub) #2
+ %call4 = tail call spir_func i32 @_Z28dot_acc_sat_4x8packed_ss_intjji(i32 %ia, i32 %ib, i32 %ires) #2
+ %call5 = tail call spir_func i32 @_Z28dot_acc_sat_4x8packed_su_intjji(i32 %ia, i32 %ub, i32 %ires) #2
+ %call6 = tail call spir_func i32 @_Z28dot_acc_sat_4x8packed_us_intjji(i32 %ua, i32 %ib, i32 %ires) #2
+ %call7 = tail call spir_func i32 @_Z29dot_acc_sat_4x8packed_uu_uintjjj(i32 %ua, i32 %ub, i32 %ures) #2
+ ret void
+}
+
+declare spir_func i32 @_Z20dot_4x8packed_ss_intjj(i32, i32)
+declare spir_func i32 @_Z20dot_4x8packed_su_intjj(i32, i32)
+declare spir_func i32 @_Z20dot_4x8packed_us_intjj(i32, i32)
+declare spir_func i32 @_Z21dot_4x8packed_uu_uintjj(i32, i32)
+declare spir_func i32 @_Z28dot_acc_sat_4x8packed_ss_intjji(i32, i32, i32)
+declare spir_func i32 @_Z28dot_acc_sat_4x8packed_su_intjji(i32, i32, i32)
+declare spir_func i32 @_Z28dot_acc_sat_4x8packed_us_intjji(i32, i32, i32)
+declare spir_func i32 @_Z29dot_acc_sat_4x8packed_uu_uintjjj(i32, i32, i32)
+
+!llvm.module.flags = !{!0}
+!opencl.ocl.version = !{!1}
+!opencl.spir.version = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 2, i32 0}
+!3 = !{i32 0, i32 0, i32 0, i32 0, i32 0, i32 0}
+!4 = !{!"none", !"none", !"none", !"none", !"none", !"none"}
+!5 = !{!"int", !"uint", !"int", !"uint", !"int", !"uint"}
+!6 = !{!"", !"", !"", !"", !"", !""}
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_integer_dot_product/SPV_KHR_integer_dot_product_OCLtoSPIRV_short2.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_integer_dot_product/SPV_KHR_integer_dot_product_OCLtoSPIRV_short2.ll
new file mode 100644
index 00000000000000..abb250e361e573
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_integer_dot_product/SPV_KHR_integer_dot_product_OCLtoSPIRV_short2.ll
@@ -0,0 +1,54 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_integer_dot_product %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_integer_dot_product %s -o - -filetype=obj | spirv-val %}
+
+; CHECK: Capability DotProduct
+; CHECK: Capability DotProductInputAll
+
+; CHECK: Name %[[#SignedA:]] "ia"
+; CHECK: Name %[[#UnsignedA:]] "ua"
+; CHECK: Name %[[#SignedB:]] "ib"
+; CHECK: Name %[[#UnsignedB:]] "ub"
+
+; CHECK: SDot %[[#]] %[[#SignedA]] %[[#SignedB]]
+; CHECK: SUDot %[[#]] %[[#SignedA]] %[[#UnsignedB]]
+; CHECK: SUDot %[[#]] %[[#SignedB]] %[[#UnsignedA]]
+; CHECK: UDot %[[#]] %[[#UnsignedA]] %[[#UnsignedB]]
+
+; CHECK: SDotAccSat %[[#]] %[[#SignedA]] %[[#SignedB]] %[[#]]
+; CHECK: SUDotAccSat %[[#]] %[[#SignedA]] %[[#UnsignedB]] %[[#]]
+; CHECK: SUDotAccSat %[[#]] %[[#SignedB]] %[[#UnsignedA]] %[[#]]
+; CHECK: UDotAccSat %[[#]] %[[#UnsignedA]] %[[#UnsignedB]] %[[#]]
+
+define spir_kernel void @test1(<2 x i16> %ia, <2 x i16> %ua, <2 x i16> %ib, <2 x i16> %ub, <2 x i16> %ires, <2 x i16> %ures) !kernel_arg_addr_space !3 !kernel_arg_access_qual !4 !kernel_arg_type !5 !kernel_arg_base_type !6 !kernel_arg_type_qual !7 {
+entry:
+ %call = tail call spir_func i32 @_Z3dotDv2_sS_(<2 x i16> %ia, <2 x i16> %ib) #2
+ %call1 = tail call spir_func i32 @_Z3dotDv2_sDv2_t(<2 x i16> %ia, <2 x i16> %ub) #2
+ %call2 = tail call spir_func i32 @_Z3dotDv2_tDv2_s(<2 x i16> %ua, <2 x i16> %ib) #2
+ %call3 = tail call spir_func i32 @_Z3dotDv2_tS_(<2 x i16> %ua, <2 x i16> %ub) #2
+ %call4 = tail call spir_func i32 @_Z11dot_acc_satDv2_sS_i(<2 x i16> %ia, <2 x i16> %ib, i32 %call2) #2
+ %call5 = tail call spir_func i32 @_Z11dot_acc_satDv2_sDv2_ti(<2 x i16> %ia, <2 x i16> %ub, i32 %call4) #2
+ %call6 = tail call spir_func i32 @_Z11dot_acc_satDv2_tDv2_si(<2 x i16> %ua, <2 x i16> %ib, i32 %call5) #2
+ %call7 = tail call spir_func i32 @_Z11dot_acc_satDv2_tS_j(<2 x i16> %ua, <2 x i16> %ub, i32 %call3) #2
+ ret void
+}
+
+declare spir_func i32 @_Z3dotDv2_sS_(<2 x i16>, <2 x i16>)
+declare spir_func i32 @_Z3dotDv2_sDv2_t(<2 x i16>, <2 x i16>)
+declare spir_func i32 @_Z3dotDv2_tDv2_s(<2 x i16>, <2 x i16>)
+declare spir_func i32 @_Z3dotDv2_tS_(<2 x i16>, <2 x i16>)
+declare spir_func i32 @_Z...
[truncated]
|
MrSidims
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haven't yet took a look in the details, just few initial comments
| ; CHECK: SUDotAccSat %[[#]] %[[#SignedB]] %[[#UnsignedA]] %[[#]] | ||
| ; CHECK: UDotAccSat %[[#]] %[[#UnsignedA]] %[[#UnsignedB]] %[[#]] | ||
|
|
||
| define spir_kernel void @test1(<4 x i8> %ia, <4 x i8> %ua, <4 x i8> %ib, <4 x i8> %ub, <4 x i8> %ires, <4 x i8> %ures) !kernel_arg_addr_space !3 !kernel_arg_access_qual !4 !kernel_arg_type !5 !kernel_arg_base_type !6 !kernel_arg_type_qual !7 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets keep the test(s) shorter by removing unused metadata.
| @@ -0,0 +1,54 @@ | |||
| ; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_integer_dot_product %s -o - | FileCheck %s | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add SPIR-V 1.6 command lines in the tests
…lvm#123792) This continues the work on dot product instructions already started in 3cdac06. This change adds support for all OpenCL integer dot product builtins under `cl_khr_integer_dot_product` extension, namely: ``` * dot * dot_acc_sat * dot_4x8packed_(uu/ss/su/us)_(u)int * dot_acc_sat_4x8packed_(uu/ss/su/us)_(u)int ```
This continues the work on dot product instructions already started in
3cdac06.
This change adds support for all OpenCL integer dot product builtins under
cl_khr_integer_dot_productextension, namely: