Skip to content

Commit f646fce

Browse files
Implement SPV_INTEL_ternary_bitwise_function (#3104)
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 <[email protected]>
1 parent e867990 commit f646fce

File tree

6 files changed

+137
-1
lines changed

6 files changed

+137
-1
lines changed

include/LLVMSPIRVExtensions.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,4 @@ EXT(SPV_INTEL_bindless_images)
7777
EXT(SPV_INTEL_2d_block_io)
7878
EXT(SPV_INTEL_subgroup_matrix_multiply_accumulate)
7979
EXT(SPV_KHR_bfloat16)
80+
EXT(SPV_INTEL_ternary_bitwise_function)

lib/SPIRV/libSPIRV/SPIRVInstruction.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4415,5 +4415,60 @@ class SPIRVSubgroupMatrixMultiplyAccumulateINTELInst
44154415
_SPIRV_OP(SubgroupMatrixMultiplyAccumulate, true, 7, true, 4)
44164416
#undef _SPIRV_OP
44174417

4418+
class SPIRVTernaryBitwiseFunctionINTELInst : public SPIRVInstTemplateBase {
4419+
public:
4420+
void validate() const override {
4421+
SPIRVInstruction::validate();
4422+
SPIRVErrorLog &SPVErrLog = this->getModule()->getErrorLog();
4423+
std::string InstName = "BitwiseFunctionINTEL";
4424+
4425+
const SPIRVType *ResTy = this->getType();
4426+
SPVErrLog.checkError(
4427+
ResTy->isTypeInt() || (ResTy->isTypeVector() &&
4428+
ResTy->getVectorComponentType()->isTypeInt()),
4429+
SPIRVEC_InvalidInstruction,
4430+
InstName + "\nResult type must be an integer scalar or vector.\n");
4431+
4432+
auto CommonArgCheck = [this, ResTy, &InstName,
4433+
&SPVErrLog](size_t ArgI, const char *ArgPlacement) {
4434+
SPIRVValue *Arg =
4435+
const_cast<SPIRVTernaryBitwiseFunctionINTELInst *>(this)->getOperand(
4436+
ArgI);
4437+
SPVErrLog.checkError(
4438+
Arg->getType() == ResTy, SPIRVEC_InvalidInstruction,
4439+
InstName + "\n" + ArgPlacement +
4440+
" argument must be the same as the result type.\n");
4441+
};
4442+
4443+
CommonArgCheck(0, "First");
4444+
CommonArgCheck(1, "Second");
4445+
CommonArgCheck(2, "Third");
4446+
4447+
SPIRVValue *LUTIndexArg =
4448+
const_cast<SPIRVTernaryBitwiseFunctionINTELInst *>(this)->getOperand(3);
4449+
const SPIRVType *LUTIndexArgTy = LUTIndexArg->getType();
4450+
SPVErrLog.checkError(
4451+
LUTIndexArgTy->isTypeInt(32), SPIRVEC_InvalidInstruction,
4452+
InstName + "\nFourth argument must be a 32-bit integer scalar.\n");
4453+
SPVErrLog.checkError(
4454+
isConstantOpCode(LUTIndexArg->getOpCode()), SPIRVEC_InvalidInstruction,
4455+
InstName + "\nFourth argument must be constant instruction.\n");
4456+
}
4457+
4458+
std::optional<ExtensionID> getRequiredExtension() const override {
4459+
return ExtensionID::SPV_INTEL_ternary_bitwise_function;
4460+
}
4461+
SPIRVCapVec getRequiredCapability() const override {
4462+
return getVec(CapabilityTernaryBitwiseFunctionINTEL);
4463+
}
4464+
};
4465+
4466+
#define _SPIRV_OP(x, ...) \
4467+
typedef SPIRVInstTemplate<SPIRVTernaryBitwiseFunctionINTELInst, \
4468+
Op##x##INTEL, __VA_ARGS__> \
4469+
SPIRV##x##INTEL;
4470+
_SPIRV_OP(BitwiseFunction, true, 7)
4471+
#undef _SPIRV_OP
4472+
44184473
} // namespace SPIRV
44194474
#endif // SPIRV_LIBSPIRV_SPIRVINSTRUCTION_H

lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,7 @@ template <> inline void SPIRVMap<Capability, std::string>::init() {
650650
add(CapabilitySubgroup2DBlockTransposeINTEL, "Subgroup2DBlockTransposeINTEL");
651651
add(CapabilitySubgroupMatrixMultiplyAccumulateINTEL,
652652
"SubgroupMatrixMultiplyAccumulateINTEL");
653+
add(CapabilityTernaryBitwiseFunctionINTEL, "TernaryBitwiseFunctionINTEL");
653654
// From spirv_internal.hpp
654655
add(internal::CapabilityFastCompositeINTEL, "FastCompositeINTEL");
655656
add(internal::CapabilityTokenTypeINTEL, "TokenTypeINTEL");

lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,7 @@ _SPIRV_OP(Subgroup2DBlockLoadTransposeINTEL, 6233)
579579
_SPIRV_OP(Subgroup2DBlockPrefetchINTEL, 6234)
580580
_SPIRV_OP(Subgroup2DBlockStoreINTEL, 6235)
581581
_SPIRV_OP(SubgroupMatrixMultiplyAccumulateINTEL, 6237)
582+
_SPIRV_OP(BitwiseFunctionINTEL, 6242)
582583
_SPIRV_OP(GroupIMulKHR, 6401)
583584
_SPIRV_OP(GroupFMulKHR, 6402)
584585
_SPIRV_OP(GroupBitwiseAndKHR, 6403)

spirv-headers-tag.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0e710677989b4326ac974fd80c5308191ed80965
1+
8c88e0c4c94a21de825efccba5f99a862b049825
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)