[llvm] [SPIR-V] Support all the instructions of SPV_KHR_integer_dot_product (PR #123792)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 21 09:50:55 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-spir-v
Author: Viktoria Maximova (vmaksimo)
<details>
<summary>Changes</summary>
This continues the work on dot product instructions already started in
3cdac06.
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:
- (modified) llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp (+88-9)
- (modified) llvm/lib/Target/SPIRV/SPIRVBuiltins.td (+47)
- (modified) llvm/lib/Target/SPIRV/SPIRVInstrInfo.td (+12-2)
- (modified) llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp (+4)
- (added) llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_integer_dot_product/SPV_KHR_integer_dot_product_OCLtoSPIRV_char4.ll (+54)
- (added) llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_integer_dot_product/SPV_KHR_integer_dot_product_OCLtoSPIRV_int.ll (+53)
- (added) llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_integer_dot_product/SPV_KHR_integer_dot_product_OCLtoSPIRV_short2.ll (+54)
``````````diff
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]
``````````
</details>
https://github.com/llvm/llvm-project/pull/123792
More information about the llvm-commits
mailing list