Skip to content

Commit 50a27ce

Browse files
authored
[SPIR-V] Support all the instructions of SPV_KHR_integer_dot_product (#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 ```
1 parent a907008 commit 50a27ce

7 files changed

+310
-11
lines changed

Diff for: llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp

+88-9
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,15 @@ struct ImageQueryBuiltin {
132132
#define GET_ImageQueryBuiltins_DECL
133133
#define GET_ImageQueryBuiltins_IMPL
134134

135+
struct IntegerDotProductBuiltin {
136+
StringRef Name;
137+
uint32_t Opcode;
138+
bool IsSwapReq;
139+
};
140+
141+
#define GET_IntegerDotProductBuiltins_DECL
142+
#define GET_IntegerDotProductBuiltins_IMPL
143+
135144
struct ConvertBuiltin {
136145
StringRef Name;
137146
InstructionSet::InstructionSet Set;
@@ -1579,20 +1588,84 @@ static bool generateCastToPtrInst(const SPIRV::IncomingCall *Call,
15791588
return true;
15801589
}
15811590

1582-
static bool generateDotOrFMulInst(const SPIRV::IncomingCall *Call,
1591+
static bool generateDotOrFMulInst(const StringRef DemangledCall,
1592+
const SPIRV::IncomingCall *Call,
15831593
MachineIRBuilder &MIRBuilder,
15841594
SPIRVGlobalRegistry *GR) {
15851595
if (Call->isSpirvOp())
15861596
return buildOpFromWrapper(MIRBuilder, SPIRV::OpDot, Call,
15871597
GR->getSPIRVTypeID(Call->ReturnType));
1588-
unsigned Opcode = GR->getSPIRVTypeForVReg(Call->Arguments[0])->getOpcode();
1589-
bool IsVec = Opcode == SPIRV::OpTypeVector;
1598+
1599+
bool IsVec = GR->getSPIRVTypeForVReg(Call->Arguments[0])->getOpcode() ==
1600+
SPIRV::OpTypeVector;
15901601
// Use OpDot only in case of vector args and OpFMul in case of scalar args.
1591-
MIRBuilder.buildInstr(IsVec ? SPIRV::OpDot : SPIRV::OpFMulS)
1592-
.addDef(Call->ReturnRegister)
1593-
.addUse(GR->getSPIRVTypeID(Call->ReturnType))
1594-
.addUse(Call->Arguments[0])
1595-
.addUse(Call->Arguments[1]);
1602+
uint32_t OC = IsVec ? SPIRV::OpDot : SPIRV::OpFMulS;
1603+
bool IsSwapReq = false;
1604+
1605+
const auto *ST =
1606+
static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());
1607+
if (GR->isScalarOrVectorOfType(Call->ReturnRegister, SPIRV::OpTypeInt) &&
1608+
(ST->canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
1609+
ST->isAtLeastSPIRVVer(VersionTuple(1, 6)))) {
1610+
const SPIRV::DemangledBuiltin *Builtin = Call->Builtin;
1611+
const SPIRV::IntegerDotProductBuiltin *IntDot =
1612+
SPIRV::lookupIntegerDotProductBuiltin(Builtin->Name);
1613+
if (IntDot) {
1614+
OC = IntDot->Opcode;
1615+
IsSwapReq = IntDot->IsSwapReq;
1616+
} else if (IsVec) {
1617+
// Handling "dot" and "dot_acc_sat" builtins which use vectors of
1618+
// integers.
1619+
LLVMContext &Ctx = MIRBuilder.getContext();
1620+
SmallVector<StringRef, 10> TypeStrs;
1621+
SPIRV::parseBuiltinTypeStr(TypeStrs, DemangledCall, Ctx);
1622+
bool IsFirstSigned = TypeStrs[0].trim()[0] != 'u';
1623+
bool IsSecondSigned = TypeStrs[1].trim()[0] != 'u';
1624+
1625+
if (Call->BuiltinName == "dot") {
1626+
if (IsFirstSigned && IsSecondSigned)
1627+
OC = SPIRV::OpSDot;
1628+
else if (!IsFirstSigned && !IsSecondSigned)
1629+
OC = SPIRV::OpUDot;
1630+
else {
1631+
OC = SPIRV::OpSUDot;
1632+
if (!IsFirstSigned)
1633+
IsSwapReq = true;
1634+
}
1635+
} else if (Call->BuiltinName == "dot_acc_sat") {
1636+
if (IsFirstSigned && IsSecondSigned)
1637+
OC = SPIRV::OpSDotAccSat;
1638+
else if (!IsFirstSigned && !IsSecondSigned)
1639+
OC = SPIRV::OpUDotAccSat;
1640+
else {
1641+
OC = SPIRV::OpSUDotAccSat;
1642+
if (!IsFirstSigned)
1643+
IsSwapReq = true;
1644+
}
1645+
}
1646+
}
1647+
}
1648+
1649+
MachineInstrBuilder MIB = MIRBuilder.buildInstr(OC)
1650+
.addDef(Call->ReturnRegister)
1651+
.addUse(GR->getSPIRVTypeID(Call->ReturnType));
1652+
1653+
if (IsSwapReq) {
1654+
MIB.addUse(Call->Arguments[1]);
1655+
MIB.addUse(Call->Arguments[0]);
1656+
// needed for dot_acc_sat* builtins
1657+
for (size_t i = 2; i < Call->Arguments.size(); ++i)
1658+
MIB.addUse(Call->Arguments[i]);
1659+
} else {
1660+
for (size_t i = 0; i < Call->Arguments.size(); ++i)
1661+
MIB.addUse(Call->Arguments[i]);
1662+
}
1663+
1664+
// Add Packed Vector Format for Integer dot product builtins if arguments are
1665+
// scalar
1666+
if (!IsVec && OC != SPIRV::OpFMulS)
1667+
MIB.addImm(0);
1668+
15961669
return true;
15971670
}
15981671

@@ -2576,6 +2649,11 @@ mapBuiltinToOpcode(const StringRef DemangledCall,
25762649
if (const auto *R = SPIRV::lookupGroupUniformBuiltin(Call->Builtin->Name))
25772650
return std::make_tuple(Call->Builtin->Group, R->Opcode, 0);
25782651
break;
2652+
case SPIRV::IntegerDot:
2653+
if (const auto *R =
2654+
SPIRV::lookupIntegerDotProductBuiltin(Call->Builtin->Name))
2655+
return std::make_tuple(Call->Builtin->Group, R->Opcode, 0);
2656+
break;
25792657
case SPIRV::WriteImage:
25802658
return std::make_tuple(Call->Builtin->Group, SPIRV::OpImageWrite, 0);
25812659
case SPIRV::Select:
@@ -2635,7 +2713,8 @@ std::optional<bool> lowerBuiltin(const StringRef DemangledCall,
26352713
case SPIRV::CastToPtr:
26362714
return generateCastToPtrInst(Call.get(), MIRBuilder);
26372715
case SPIRV::Dot:
2638-
return generateDotOrFMulInst(Call.get(), MIRBuilder, GR);
2716+
case SPIRV::IntegerDot:
2717+
return generateDotOrFMulInst(DemangledCall, Call.get(), MIRBuilder, GR);
26392718
case SPIRV::Wave:
26402719
return generateWaveInst(Call.get(), MIRBuilder, GR);
26412720
case SPIRV::ICarryBorrow:

Diff for: llvm/lib/Target/SPIRV/SPIRVBuiltins.td

+47
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ def Variable : BuiltinGroup;
4242
def Atomic : BuiltinGroup;
4343
def Barrier : BuiltinGroup;
4444
def Dot : BuiltinGroup;
45+
def IntegerDot : BuiltinGroup;
4546
def Wave : BuiltinGroup;
4647
def GetQuery : BuiltinGroup;
4748
def ImageSizeQuery : BuiltinGroup;
@@ -101,6 +102,8 @@ def lookupBuiltin : SearchIndex {
101102
// Dot builtin record:
102103
def : DemangledBuiltin<"dot", OpenCL_std, Dot, 2, 2>;
103104
def : DemangledBuiltin<"__spirv_Dot", OpenCL_std, Dot, 2, 2>;
105+
def : DemangledBuiltin<"dot_acc_sat", OpenCL_std, IntegerDot, 3, 3>;
106+
def : DemangledBuiltin<"__spirv_DotAccSat", OpenCL_std, IntegerDot, 3, 3>;
104107

105108
// Image builtin records:
106109
def : DemangledBuiltin<"read_imagei", OpenCL_std, ReadImage, 2, 4>;
@@ -1715,3 +1718,47 @@ class CLMemoryFenceFlags<bits<32> value> {
17151718
def CLK_LOCAL_MEM_FENCE : CLMemoryFenceFlags<0x1>;
17161719
def CLK_GLOBAL_MEM_FENCE : CLMemoryFenceFlags<0x2>;
17171720
def CLK_IMAGE_MEM_FENCE : CLMemoryFenceFlags<0x4>;
1721+
1722+
//===----------------------------------------------------------------------===//
1723+
// Class defining dot builtins that should be translated into a
1724+
// SPIR-V instruction using SPIR-V 1.6 or SPV_KHR_integer_dot_product extension.
1725+
//
1726+
// name is the demangled name of the given builtin.
1727+
// opcode specifies the SPIR-V operation code of the generated instruction.
1728+
// isSwapRequired specifies if the operands need to be swapped (the SPIR-V extension
1729+
// has only one instruction for arguments of different signedness).
1730+
//===----------------------------------------------------------------------===//
1731+
class IntegerDotProductBuiltin<string name, Op operation> {
1732+
string Name = name;
1733+
Op Opcode = operation;
1734+
bit IsSwapReq = !not(!eq(!find(name, "_us"), -1));
1735+
}
1736+
1737+
// Table gathering all the integer dot product builtins.
1738+
def IntegerDotProductBuiltins : GenericTable {
1739+
let FilterClass = "IntegerDotProductBuiltin";
1740+
let Fields = ["Name", "Opcode", "IsSwapReq"];
1741+
}
1742+
1743+
// Function to lookup group builtins by their name and set.
1744+
def lookupIntegerDotProductBuiltin : SearchIndex {
1745+
let Table = IntegerDotProductBuiltins;
1746+
let Key = ["Name"];
1747+
}
1748+
1749+
// Multiclass used to define incoming builtin records for the SPV_KHR_integer_dot_product extension.
1750+
multiclass DemangledIntegerDotProductBuiltin<string name, bits<8> minNumArgs, bits<8> maxNumArgs, Op operation> {
1751+
def : DemangledBuiltin<!strconcat("dot", name), OpenCL_std, IntegerDot, minNumArgs, maxNumArgs>;
1752+
def : IntegerDotProductBuiltin<!strconcat("dot", name), operation>;
1753+
}
1754+
1755+
// cl_khr_integer_dot_product
1756+
defm : DemangledIntegerDotProductBuiltin<"_4x8packed_uu_uint", 2, 3, OpUDot>;
1757+
defm : DemangledIntegerDotProductBuiltin<"_4x8packed_ss_int", 2, 3, OpSDot>;
1758+
defm : DemangledIntegerDotProductBuiltin<"_4x8packed_us_int", 2, 3, OpSUDot>;
1759+
defm : DemangledIntegerDotProductBuiltin<"_4x8packed_su_int", 2, 3, OpSUDot>;
1760+
1761+
defm : DemangledIntegerDotProductBuiltin<"_acc_sat_4x8packed_uu_uint", 3, 4, OpUDotAccSat>;
1762+
defm : DemangledIntegerDotProductBuiltin<"_acc_sat_4x8packed_ss_int", 3, 4, OpSDotAccSat>;
1763+
defm : DemangledIntegerDotProductBuiltin<"_acc_sat_4x8packed_us_int", 3, 4, OpSUDotAccSat>;
1764+
defm : DemangledIntegerDotProductBuiltin<"_acc_sat_4x8packed_su_int", 3, 4, OpSUDotAccSat>;

Diff for: llvm/lib/Target/SPIRV/SPIRVInstrInfo.td

+12-2
Original file line numberDiff line numberDiff line change
@@ -530,8 +530,18 @@ defm OpISubBorrow: BinOpTypedGen<"OpISubBorrow", 150, subc, 0, 1>;
530530
def OpUMulExtended: BinOp<"OpUMulExtended", 151>;
531531
def OpSMulExtended: BinOp<"OpSMulExtended", 152>;
532532

533-
def OpSDot: BinOp<"OpSDot", 4450>;
534-
def OpUDot: BinOp<"OpUDot", 4451>;
533+
def OpSDot: Op<4450, (outs ID:$res), (ins TYPE:$type, ID:$vec1, ID:$vec2, variable_ops),
534+
"$res = OpSDot $type $vec1 $vec2">;
535+
def OpUDot: Op<4451, (outs ID:$res), (ins TYPE:$type, ID:$vec1, ID:$vec2, variable_ops),
536+
"$res = OpUDot $type $vec1 $vec2">;
537+
def OpSUDot: Op<4452, (outs ID:$res), (ins TYPE:$type, ID:$vec1, ID:$vec2, variable_ops),
538+
"$res = OpSUDot $type $vec1 $vec2">;
539+
def OpSDotAccSat: Op<4453, (outs ID:$res), (ins TYPE:$type, ID:$vec1, ID:$vec2, ID:$acc, variable_ops),
540+
"$res = OpSDotAccSat $type $vec1 $vec2 $acc">;
541+
def OpUDotAccSat: Op<4454, (outs ID:$res), (ins TYPE:$type, ID:$vec1, ID:$vec2, ID:$acc, variable_ops),
542+
"$res = OpUDotAccSat $type $vec1 $vec2 $acc">;
543+
def OpSUDotAccSat: Op<4455, (outs ID:$res), (ins TYPE:$type, ID:$vec1, ID:$vec2, ID:$acc, variable_ops),
544+
"$res = OpSUDotAccSat $type $vec1 $vec2 $acc">;
535545

536546
// 3.42.14 Bit Instructions
537547

Diff for: llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -1692,6 +1692,10 @@ void addInstrRequirements(const MachineInstr &MI,
16921692
break;
16931693
case SPIRV::OpSDot:
16941694
case SPIRV::OpUDot:
1695+
case SPIRV::OpSUDot:
1696+
case SPIRV::OpSDotAccSat:
1697+
case SPIRV::OpUDotAccSat:
1698+
case SPIRV::OpSUDotAccSat:
16951699
AddDotProductRequirements(MI, Reqs, ST);
16961700
break;
16971701
case SPIRV::OpImageRead: {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32v1.6-unknown-unknown %s -o - | FileCheck %s
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32v1.6-unknown-unknown %s -o - -filetype=obj | spirv-val %}
3+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_integer_dot_product %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-EXT
4+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_integer_dot_product %s -o - -filetype=obj | spirv-val %}
5+
6+
; CHECK: Capability DotProduct
7+
; CHECK: Capability DotProductInput4x8Bit
8+
; CHECK-EXT: OpExtension "SPV_KHR_integer_dot_product"
9+
; CHECK-NOT: OpExtension "SPV_KHR_integer_dot_product"
10+
11+
; CHECK: Name %[[#SignedA:]] "ia"
12+
; CHECK: Name %[[#UnsignedA:]] "ua"
13+
; CHECK: Name %[[#SignedB:]] "ib"
14+
; CHECK: Name %[[#UnsignedB:]] "ub"
15+
16+
; CHECK: SDot %[[#]] %[[#SignedA]] %[[#SignedB]]
17+
; CHECK: SUDot %[[#]] %[[#SignedA]] %[[#UnsignedB]]
18+
; CHECK: SUDot %[[#]] %[[#SignedB]] %[[#UnsignedA]]
19+
; CHECK: UDot %[[#]] %[[#UnsignedA]] %[[#UnsignedB]]
20+
21+
; CHECK: SDotAccSat %[[#]] %[[#SignedA]] %[[#SignedB]] %[[#]]
22+
; CHECK: SUDotAccSat %[[#]] %[[#SignedA]] %[[#UnsignedB]] %[[#]]
23+
; CHECK: SUDotAccSat %[[#]] %[[#SignedB]] %[[#UnsignedA]] %[[#]]
24+
; CHECK: UDotAccSat %[[#]] %[[#UnsignedA]] %[[#UnsignedB]] %[[#]]
25+
26+
define spir_kernel void @test(<4 x i8> %ia, <4 x i8> %ua, <4 x i8> %ib, <4 x i8> %ub, <4 x i8> %ires, <4 x i8> %ures) {
27+
entry:
28+
%call = tail call spir_func i32 @_Z3dotDv4_cS_(<4 x i8> %ia, <4 x i8> %ib) #2
29+
%call1 = tail call spir_func i32 @_Z3dotDv4_cDv4_h(<4 x i8> %ia, <4 x i8> %ub) #2
30+
%call2 = tail call spir_func i32 @_Z3dotDv4_hDv4_c(<4 x i8> %ua, <4 x i8> %ib) #2
31+
%call3 = tail call spir_func i32 @_Z3dotDv4_hS_(<4 x i8> %ua, <4 x i8> %ub) #2
32+
%call4 = tail call spir_func i32 @_Z11dot_acc_satDv4_cS_i(<4 x i8> %ia, <4 x i8> %ib, i32 %call2) #2
33+
%call5 = tail call spir_func i32 @_Z11dot_acc_satDv4_cDv4_hi(<4 x i8> %ia, <4 x i8> %ub, i32 %call4) #2
34+
%call6 = tail call spir_func i32 @_Z11dot_acc_satDv4_hDv4_ci(<4 x i8> %ua, <4 x i8> %ib, i32 %call5) #2
35+
%call7 = tail call spir_func i32 @_Z11dot_acc_satDv4_hS_j(<4 x i8> %ua, <4 x i8> %ub, i32 %call3) #2
36+
ret void
37+
}
38+
39+
declare spir_func i32 @_Z3dotDv4_cS_(<4 x i8>, <4 x i8>)
40+
declare spir_func i32 @_Z3dotDv4_cDv4_h(<4 x i8>, <4 x i8>)
41+
declare spir_func i32 @_Z3dotDv4_hDv4_c(<4 x i8>, <4 x i8>)
42+
declare spir_func i32 @_Z3dotDv4_hS_(<4 x i8>, <4 x i8>)
43+
declare spir_func i32 @_Z11dot_acc_satDv4_cS_i(<4 x i8>, <4 x i8>, i32)
44+
declare spir_func i32 @_Z11dot_acc_satDv4_cDv4_hi(<4 x i8>, <4 x i8>, i32)
45+
declare spir_func i32 @_Z11dot_acc_satDv4_hDv4_ci(<4 x i8>, <4 x i8>, i32)
46+
declare spir_func i32 @_Z11dot_acc_satDv4_hS_j(<4 x i8>, <4 x i8>, i32)
47+
48+
!llvm.module.flags = !{!0}
49+
!opencl.ocl.version = !{!1}
50+
!opencl.spir.version = !{!1}
51+
52+
!0 = !{i32 1, !"wchar_size", i32 4}
53+
!1 = !{i32 2, i32 0}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32v1.6-unknown-unknown %s -o - | FileCheck %s
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32v1.6-unknown-unknown %s -o - -filetype=obj | spirv-val %}
3+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_integer_dot_product %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-EXT
4+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_integer_dot_product %s -o - -filetype=obj | spirv-val %}
5+
6+
; CHECK: Capability DotProduct
7+
; CHECK: Capability DotProductInput4x8BitPacked
8+
; CHECK-EXT: OpExtension "SPV_KHR_integer_dot_product"
9+
; CHECK-NOT: OpExtension "SPV_KHR_integer_dot_product"
10+
11+
; CHECK: Name %[[#SignedA:]] "ia"
12+
; CHECK: Name %[[#UnsignedA:]] "ua"
13+
; CHECK: Name %[[#SignedB:]] "ib"
14+
; CHECK: Name %[[#UnsignedB:]] "ub"
15+
16+
; CHECK: SDot %[[#]] %[[#SignedA]] %[[#SignedB]] 0
17+
; CHECK: SUDot %[[#]] %[[#SignedA]] %[[#UnsignedB]] 0
18+
; CHECK: SUDot %[[#]] %[[#SignedB]] %[[#UnsignedA]] 0
19+
; CHECK: UDot %[[#]] %[[#UnsignedA]] %[[#UnsignedB]] 0
20+
21+
; CHECK: SDotAccSat %[[#]] %[[#SignedA]] %[[#SignedB]] %[[#]] 0
22+
; CHECK: SUDotAccSat %[[#]] %[[#SignedA]] %[[#UnsignedB]] %[[#]] 0
23+
; CHECK: SUDotAccSat %[[#]] %[[#SignedB]] %[[#UnsignedA]] %[[#]] 0
24+
; CHECK: UDotAccSat %[[#]] %[[#UnsignedA]] %[[#UnsignedB]] %[[#]] 0
25+
26+
define spir_kernel void @test(i32 %ia, i32 %ua, i32 %ib, i32 %ub, i32 %ires, i32 %ures) {
27+
entry:
28+
%call = tail call spir_func i32 @_Z20dot_4x8packed_ss_intjj(i32 %ia, i32 %ib) #2
29+
%call1 = tail call spir_func i32 @_Z20dot_4x8packed_su_intjj(i32 %ia, i32 %ub) #2
30+
%call2 = tail call spir_func i32 @_Z20dot_4x8packed_us_intjj(i32 %ua, i32 %ib) #2
31+
%call3 = tail call spir_func i32 @_Z21dot_4x8packed_uu_uintjj(i32 %ua, i32 %ub) #2
32+
%call4 = tail call spir_func i32 @_Z28dot_acc_sat_4x8packed_ss_intjji(i32 %ia, i32 %ib, i32 %ires) #2
33+
%call5 = tail call spir_func i32 @_Z28dot_acc_sat_4x8packed_su_intjji(i32 %ia, i32 %ub, i32 %ires) #2
34+
%call6 = tail call spir_func i32 @_Z28dot_acc_sat_4x8packed_us_intjji(i32 %ua, i32 %ib, i32 %ires) #2
35+
%call7 = tail call spir_func i32 @_Z29dot_acc_sat_4x8packed_uu_uintjjj(i32 %ua, i32 %ub, i32 %ures) #2
36+
ret void
37+
}
38+
39+
declare spir_func i32 @_Z20dot_4x8packed_ss_intjj(i32, i32)
40+
declare spir_func i32 @_Z20dot_4x8packed_su_intjj(i32, i32)
41+
declare spir_func i32 @_Z20dot_4x8packed_us_intjj(i32, i32)
42+
declare spir_func i32 @_Z21dot_4x8packed_uu_uintjj(i32, i32)
43+
declare spir_func i32 @_Z28dot_acc_sat_4x8packed_ss_intjji(i32, i32, i32)
44+
declare spir_func i32 @_Z28dot_acc_sat_4x8packed_su_intjji(i32, i32, i32)
45+
declare spir_func i32 @_Z28dot_acc_sat_4x8packed_us_intjji(i32, i32, i32)
46+
declare spir_func i32 @_Z29dot_acc_sat_4x8packed_uu_uintjjj(i32, i32, i32)
47+
48+
!llvm.module.flags = !{!0}
49+
!opencl.ocl.version = !{!1}
50+
!opencl.spir.version = !{!1}
51+
52+
!0 = !{i32 1, !"wchar_size", i32 4}
53+
!1 = !{i32 2, i32 0}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32v1.6-unknown-unknown %s -o - | FileCheck %s
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32v1.6-unknown-unknown %s -o - -filetype=obj | spirv-val %}
3+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_integer_dot_product %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-EXT
4+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_integer_dot_product %s -o - -filetype=obj | spirv-val %}
5+
6+
; CHECK: Capability DotProduct
7+
; CHECK: Capability DotProductInputAll
8+
; CHECK-EXT: OpExtension "SPV_KHR_integer_dot_product"
9+
; CHECK-NOT: OpExtension "SPV_KHR_integer_dot_product"
10+
11+
; CHECK: Name %[[#SignedA:]] "ia"
12+
; CHECK: Name %[[#UnsignedA:]] "ua"
13+
; CHECK: Name %[[#SignedB:]] "ib"
14+
; CHECK: Name %[[#UnsignedB:]] "ub"
15+
16+
; CHECK: SDot %[[#]] %[[#SignedA]] %[[#SignedB]]
17+
; CHECK: SUDot %[[#]] %[[#SignedA]] %[[#UnsignedB]]
18+
; CHECK: SUDot %[[#]] %[[#SignedB]] %[[#UnsignedA]]
19+
; CHECK: UDot %[[#]] %[[#UnsignedA]] %[[#UnsignedB]]
20+
21+
; CHECK: SDotAccSat %[[#]] %[[#SignedA]] %[[#SignedB]] %[[#]]
22+
; CHECK: SUDotAccSat %[[#]] %[[#SignedA]] %[[#UnsignedB]] %[[#]]
23+
; CHECK: SUDotAccSat %[[#]] %[[#SignedB]] %[[#UnsignedA]] %[[#]]
24+
; CHECK: UDotAccSat %[[#]] %[[#UnsignedA]] %[[#UnsignedB]] %[[#]]
25+
26+
define spir_kernel void @test(<2 x i16> %ia, <2 x i16> %ua, <2 x i16> %ib, <2 x i16> %ub, <2 x i16> %ires, <2 x i16> %ures) {
27+
entry:
28+
%call = tail call spir_func i32 @_Z3dotDv2_sS_(<2 x i16> %ia, <2 x i16> %ib) #2
29+
%call1 = tail call spir_func i32 @_Z3dotDv2_sDv2_t(<2 x i16> %ia, <2 x i16> %ub) #2
30+
%call2 = tail call spir_func i32 @_Z3dotDv2_tDv2_s(<2 x i16> %ua, <2 x i16> %ib) #2
31+
%call3 = tail call spir_func i32 @_Z3dotDv2_tS_(<2 x i16> %ua, <2 x i16> %ub) #2
32+
%call4 = tail call spir_func i32 @_Z11dot_acc_satDv2_sS_i(<2 x i16> %ia, <2 x i16> %ib, i32 %call2) #2
33+
%call5 = tail call spir_func i32 @_Z11dot_acc_satDv2_sDv2_ti(<2 x i16> %ia, <2 x i16> %ub, i32 %call4) #2
34+
%call6 = tail call spir_func i32 @_Z11dot_acc_satDv2_tDv2_si(<2 x i16> %ua, <2 x i16> %ib, i32 %call5) #2
35+
%call7 = tail call spir_func i32 @_Z11dot_acc_satDv2_tS_j(<2 x i16> %ua, <2 x i16> %ub, i32 %call3) #2
36+
ret void
37+
}
38+
39+
declare spir_func i32 @_Z3dotDv2_sS_(<2 x i16>, <2 x i16>)
40+
declare spir_func i32 @_Z3dotDv2_sDv2_t(<2 x i16>, <2 x i16>)
41+
declare spir_func i32 @_Z3dotDv2_tDv2_s(<2 x i16>, <2 x i16>)
42+
declare spir_func i32 @_Z3dotDv2_tS_(<2 x i16>, <2 x i16>)
43+
declare spir_func i32 @_Z11dot_acc_satDv2_sS_i(<2 x i16>, <2 x i16>, i32)
44+
declare spir_func i32 @_Z11dot_acc_satDv2_sDv2_ti(<2 x i16>, <2 x i16>, i32)
45+
declare spir_func i32 @_Z11dot_acc_satDv2_tDv2_si(<2 x i16>, <2 x i16>, i32)
46+
declare spir_func i32 @_Z11dot_acc_satDv2_tS_j(<2 x i16>, <2 x i16>, i32)
47+
48+
!llvm.module.flags = !{!0}
49+
!opencl.ocl.version = !{!1}
50+
!opencl.spir.version = !{!1}
51+
52+
!0 = !{i32 1, !"wchar_size", i32 4}
53+
!1 = !{i32 2, i32 0}

0 commit comments

Comments
 (0)