Skip to content

Commit d847a70

Browse files
Steffen LarsenSidorov, Dmitry
authored andcommitted
[Backport to 20] Implement SPV_INTEL_ternary_bitwise_function (KhronosGroup#3103)
This commit implements support for bi-directional translation of the `BitwiseFunctionINTEL` operation added in https://github.khronos.org/SPIRV-Registry/extensions/INTEL/SPV_INTEL_ternary_bitwise_function.html together with the corresponding capability. Signed-off-by: Larsen, Steffen <steffen.larsen@intel.com>
1 parent 35d5180 commit d847a70

File tree

4 files changed

+135
-0
lines changed

4 files changed

+135
-0
lines changed

lib/SPIRV/libSPIRV/SPIRVInstruction.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4604,5 +4604,60 @@ class SPIRVFmaKHRInstBase : public SPIRVInstTemplateBase {
46044604
typedef SPIRVInstTemplate<SPIRVFmaKHRInstBase, OpFmaKHR, true, 6, false>
46054605
SPIRVFmaKHR;
46064606

4607+
class SPIRVTernaryBitwiseFunctionINTELInst : public SPIRVInstTemplateBase {
4608+
public:
4609+
void validate() const override {
4610+
SPIRVInstruction::validate();
4611+
SPIRVErrorLog &SPVErrLog = this->getModule()->getErrorLog();
4612+
std::string InstName = "BitwiseFunctionINTEL";
4613+
4614+
const SPIRVType *ResTy = this->getType();
4615+
SPVErrLog.checkError(
4616+
ResTy->isTypeInt() || (ResTy->isTypeVector() &&
4617+
ResTy->getVectorComponentType()->isTypeInt()),
4618+
SPIRVEC_InvalidInstruction,
4619+
InstName + "\nResult type must be an integer scalar or vector.\n");
4620+
4621+
auto CommonArgCheck = [this, ResTy, &InstName,
4622+
&SPVErrLog](size_t ArgI, const char *ArgPlacement) {
4623+
SPIRVValue *Arg =
4624+
const_cast<SPIRVTernaryBitwiseFunctionINTELInst *>(this)->getOperand(
4625+
ArgI);
4626+
SPVErrLog.checkError(
4627+
Arg->getType() == ResTy, SPIRVEC_InvalidInstruction,
4628+
InstName + "\n" + ArgPlacement +
4629+
" argument must be the same as the result type.\n");
4630+
};
4631+
4632+
CommonArgCheck(0, "First");
4633+
CommonArgCheck(1, "Second");
4634+
CommonArgCheck(2, "Third");
4635+
4636+
SPIRVValue *LUTIndexArg =
4637+
const_cast<SPIRVTernaryBitwiseFunctionINTELInst *>(this)->getOperand(3);
4638+
const SPIRVType *LUTIndexArgTy = LUTIndexArg->getType();
4639+
SPVErrLog.checkError(
4640+
LUTIndexArgTy->isTypeInt(32), SPIRVEC_InvalidInstruction,
4641+
InstName + "\nFourth argument must be a 32-bit integer scalar.\n");
4642+
SPVErrLog.checkError(
4643+
isConstantOpCode(LUTIndexArg->getOpCode()), SPIRVEC_InvalidInstruction,
4644+
InstName + "\nFourth argument must be constant instruction.\n");
4645+
}
4646+
4647+
std::optional<ExtensionID> getRequiredExtension() const override {
4648+
return ExtensionID::SPV_INTEL_ternary_bitwise_function;
4649+
}
4650+
SPIRVCapVec getRequiredCapability() const override {
4651+
return getVec(CapabilityTernaryBitwiseFunctionINTEL);
4652+
}
4653+
};
4654+
4655+
#define _SPIRV_OP(x, ...) \
4656+
typedef SPIRVInstTemplate<SPIRVTernaryBitwiseFunctionINTELInst, \
4657+
Op##x##INTEL, __VA_ARGS__> \
4658+
SPIRV##x##INTEL;
4659+
_SPIRV_OP(BitwiseFunction, true, 7)
4660+
#undef _SPIRV_OP
4661+
46074662
} // namespace SPIRV
46084663
#endif // SPIRV_LIBSPIRV_SPIRVINSTRUCTION_H

lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,7 @@ template <> inline void SPIRVMap<Capability, std::string>::init() {
655655
add(CapabilitySubgroupMatrixMultiplyAccumulateINTEL,
656656
"SubgroupMatrixMultiplyAccumulateINTEL");
657657
add(CapabilityFMAKHR, "FMAKHR");
658+
add(CapabilityTernaryBitwiseFunctionINTEL, "TernaryBitwiseFunctionINTEL");
658659
// From spirv_internal.hpp
659660
add(internal::CapabilityTokenTypeINTEL, "TokenTypeINTEL");
660661
add(internal::CapabilityJointMatrixINTEL, "JointMatrixINTEL");

lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,7 @@ _SPIRV_OP(SpecConstantTargetINTEL, 6251)
587587
_SPIRV_OP(SpecConstantArchitectureINTEL, 6252)
588588
_SPIRV_OP(SpecConstantCapabilitiesINTEL, 6253)
589589
_SPIRV_OP(ConditionalCopyObjectINTEL, 6254)
590+
_SPIRV_OP(BitwiseFunctionINTEL, 6242)
590591
_SPIRV_OP(GroupIMulKHR, 6401)
591592
_SPIRV_OP(GroupFMulKHR, 6402)
592593
_SPIRV_OP(GroupBitwiseAndKHR, 6403)
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
; RUN: llvm-as %s -o %t.bc
2+
; RUN: llvm-spirv %t.bc --spirv-ext=+SPV_INTEL_ternary_bitwise_function -o %t.spv
3+
; RUN: llvm-spirv %t.spv --to-text -o %t.spt
4+
; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV
5+
6+
; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
7+
; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM
8+
9+
; RUN: not llvm-spirv %t.bc 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
10+
; CHECK-ERROR: RequiresExtension: Feature requires the following SPIR-V extension:
11+
; CHECK-ERROR-NEXT: SPV_INTEL_ternary_bitwise_function
12+
13+
; CHECK-SPIRV-NOT: Name [[#]] "_Z28__spirv_BitwiseFunctionINTELiiij"
14+
; CHECK-SPIRV-NOT: Name [[#]] "_Z28__spirv_BitwiseFunctionINTELDv4_iS_S_j"
15+
16+
; CHECK-SPIRV-DAG: Capability TernaryBitwiseFunctionINTEL
17+
; CHECK-SPIRV-DAG: Extension "SPV_INTEL_ternary_bitwise_function"
18+
19+
; CHECK-SPIRV-DAG: TypeInt [[#TYPEINT:]] 32 0
20+
; CHECK-SPIRV-DAG: TypeVector [[#TYPEINTVEC4:]] [[#TYPEINT]] 4
21+
; CHECK-SPIRV-DAG: Constant [[#TYPEINT]] [[#ScalarLUT:]] 24
22+
; CHECK-SPIRV-DAG: Constant [[#TYPEINT]] [[#VecLUT:]] 42
23+
24+
; CHECK-SPIRV: Load [[#TYPEINT]] [[#ScalarA:]]
25+
; CHECK-SPIRV: Load [[#TYPEINT]] [[#ScalarB:]]
26+
; CHECK-SPIRV: Load [[#TYPEINT]] [[#ScalarC:]]
27+
; CHECK-SPIRV: BitwiseFunctionINTEL [[#TYPEINT]] {{.*}} [[#ScalarA]] [[#ScalarB]] [[#ScalarC]] [[#ScalarLUT]]
28+
; CHECK-SPIRV: Load [[#TYPEINTVEC4]] [[#VecA:]]
29+
; CHECK-SPIRV: Load [[#TYPEINTVEC4]] [[#VecB:]]
30+
; CHECK-SPIRV: Load [[#TYPEINTVEC4]] [[#VecC:]]
31+
; CHECK-SPIRV: BitwiseFunctionINTEL [[#TYPEINTVEC4]] {{.*}} [[#VecA]] [[#VecB]] [[#VecC]] [[#VecLUT]]
32+
33+
; CHECK-LLVM: %[[ScalarA:.*]] = load i32, ptr
34+
; CHECK-LLVM: %[[ScalarB:.*]] = load i32, ptr
35+
; CHECK-LLVM: %[[ScalarC:.*]] = load i32, ptr
36+
; CHECK-LLVM: call spir_func i32 @_Z28__spirv_BitwiseFunctionINTELiiii(i32 %[[ScalarA]], i32 %[[ScalarB]], i32 %[[ScalarC]], i32 24)
37+
; CHECK-LLVM: %[[VecA:.*]] = load <4 x i32>, ptr
38+
; CHECK-LLVM: %[[VecB:.*]] = load <4 x i32>, ptr
39+
; CHECK-LLVM: %[[VecC:.*]] = load <4 x i32>, ptr
40+
; CHECK-LLVM: call spir_func <4 x i32> @_Z28__spirv_BitwiseFunctionINTELDv4_iS_S_i(<4 x i32> %[[VecA]], <4 x i32> %[[VecB]], <4 x i32> %[[VecC]], i32 42)
41+
42+
target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
43+
target triple = "spir"
44+
45+
; Function Attrs: nounwind readnone
46+
define spir_kernel void @fooScalar() {
47+
entry:
48+
%argA = alloca i32
49+
%argB = alloca i32
50+
%argC = alloca i32
51+
%A = load i32, ptr %argA
52+
%B = load i32, ptr %argB
53+
%C = load i32, ptr %argC
54+
%res = call spir_func i32 @_Z28__spirv_BitwiseFunctionINTELiiii(i32 %A, i32 %B, i32 %C, i32 24)
55+
ret void
56+
}
57+
58+
; Function Attrs: nounwind readnone
59+
define spir_kernel void @fooVec() {
60+
entry:
61+
%argA = alloca <4 x i32>
62+
%argB = alloca <4 x i32>
63+
%argC = alloca <4 x i32>
64+
%A = load <4 x i32>, ptr %argA
65+
%B = load <4 x i32>, ptr %argB
66+
%C = load <4 x i32>, ptr %argC
67+
%res = call spir_func <4 x i32> @_Z28__spirv_BitwiseFunctionINTELDv4_iS_S_i(<4 x i32> %A, <4 x i32> %B, <4 x i32> %C, i32 42)
68+
ret void
69+
}
70+
71+
declare dso_local spir_func i32 @_Z28__spirv_BitwiseFunctionINTELiiii(i32, i32, i32, i32)
72+
declare dso_local spir_func <4 x i32> @_Z28__spirv_BitwiseFunctionINTELDv4_iS_S_i(<4 x i32>, <4 x i32>, <4 x i32>, i32)
73+
74+
!llvm.module.flags = !{!0}
75+
!opencl.spir.version = !{!1}
76+
77+
!0 = !{i32 1, !"wchar_size", i32 4}
78+
!1 = !{i32 1, i32 2}

0 commit comments

Comments
 (0)