Skip to content

Commit f04bfbc

Browse files
[SPIRV] Support for SPV_INTEL_ternary_bitwise_function (llvm#134866)
Adds support for the SPV_INTEL_ternary_bitwise_function extension, adding; * the OpBitwiseFunctionINTEL SPIR-V instruction, a ternary bitwise function where the operation performed is determined by a look-up table index, * and the corresponding TernaryBitwiseFunctionINTEL capability. See https://github.khronos.org/SPIRV-Registry/extensions/INTEL/SPV_INTEL_ternary_bitwise_function.html. Signed-off-by: Larsen, Steffen <[email protected]>
1 parent f46d641 commit f04bfbc

File tree

8 files changed

+116
-1
lines changed

8 files changed

+116
-1
lines changed

llvm/docs/SPIRVUsage.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ list of supported SPIR-V extensions, sorted alphabetically by their extension na
209209
- Adds the ability to declare extended instruction sets that have no semantic impact and can be safely removed from a module.
210210
* - ``SPV_INTEL_fp_max_error``
211211
- Adds the ability to specify the maximum error for floating-point operations.
212+
* - ``SPV_INTEL_ternary_bitwise_function``
213+
- Adds a bitwise instruction on three operands and a look-up table index for specifying the bitwise operation to perform.
212214

213215
To enable multiple extensions, list them separated by comma. For example, to enable support for atomic operations on floating-point numbers and arbitrary precision integers, use:
214216

llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,6 +1058,24 @@ static bool buildBindlessImageINTELInst(const SPIRV::IncomingCall *Call,
10581058
return true;
10591059
}
10601060

1061+
/// Helper function for building Intel's OpBitwiseFunctionINTEL instruction.
1062+
static bool buildTernaryBitwiseFunctionINTELInst(
1063+
const SPIRV::IncomingCall *Call, unsigned Opcode,
1064+
MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR) {
1065+
// Generate SPIRV instruction accordingly.
1066+
if (Call->isSpirvOp())
1067+
return buildOpFromWrapper(MIRBuilder, Opcode, Call,
1068+
GR->getSPIRVTypeID(Call->ReturnType));
1069+
1070+
auto MIB = MIRBuilder.buildInstr(Opcode)
1071+
.addDef(Call->ReturnRegister)
1072+
.addUse(GR->getSPIRVTypeID(Call->ReturnType));
1073+
for (unsigned i = 0; i < Call->Arguments.size(); ++i)
1074+
MIB.addUse(Call->Arguments[i]);
1075+
1076+
return true;
1077+
}
1078+
10611079
static unsigned getNumComponentsForDim(SPIRV::Dim::Dim dim) {
10621080
switch (dim) {
10631081
case SPIRV::Dim::DIM_1D:
@@ -2264,6 +2282,18 @@ static bool generateBindlessImageINTELInst(const SPIRV::IncomingCall *Call,
22642282
return buildBindlessImageINTELInst(Call, Opcode, MIRBuilder, GR);
22652283
}
22662284

2285+
static bool
2286+
generateTernaryBitwiseFunctionINTELInst(const SPIRV::IncomingCall *Call,
2287+
MachineIRBuilder &MIRBuilder,
2288+
SPIRVGlobalRegistry *GR) {
2289+
// Lookup the instruction opcode in the TableGen records.
2290+
const SPIRV::DemangledBuiltin *Builtin = Call->Builtin;
2291+
unsigned Opcode =
2292+
SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;
2293+
2294+
return buildTernaryBitwiseFunctionINTELInst(Call, Opcode, MIRBuilder, GR);
2295+
}
2296+
22672297
static bool buildNDRange(const SPIRV::IncomingCall *Call,
22682298
MachineIRBuilder &MIRBuilder,
22692299
SPIRVGlobalRegistry *GR) {
@@ -2845,6 +2875,8 @@ std::optional<bool> lowerBuiltin(const StringRef DemangledCall,
28452875
return generateExtendedBitOpsInst(Call.get(), MIRBuilder, GR);
28462876
case SPIRV::BindlessINTEL:
28472877
return generateBindlessImageINTELInst(Call.get(), MIRBuilder, GR);
2878+
case SPIRV::TernaryBitwiseINTEL:
2879+
return generateTernaryBitwiseFunctionINTELInst(Call.get(), MIRBuilder, GR);
28482880
}
28492881
return false;
28502882
}

llvm/lib/Target/SPIRV/SPIRVBuiltins.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ def CoopMatr : BuiltinGroup;
6767
def ICarryBorrow : BuiltinGroup;
6868
def ExtendedBitOps : BuiltinGroup;
6969
def BindlessINTEL : BuiltinGroup;
70+
def TernaryBitwiseINTEL : BuiltinGroup;
7071

7172
//===----------------------------------------------------------------------===//
7273
// Class defining a demangled builtin record. The information in the record
@@ -714,6 +715,9 @@ defm : DemangledNativeBuiltin<"__spirv_ConvertHandleToImageINTEL", OpenCL_std, B
714715
defm : DemangledNativeBuiltin<"__spirv_ConvertHandleToSamplerINTEL", OpenCL_std, BindlessINTEL, 1, 1, OpConvertHandleToSamplerINTEL>;
715716
defm : DemangledNativeBuiltin<"__spirv_ConvertHandleToSampledImageINTEL", OpenCL_std, BindlessINTEL, 1, 1, OpConvertHandleToSampledImageINTEL>;
716717

718+
// SPV_INTEL_ternary_bitwise_function builtin records:
719+
defm : DemangledNativeBuiltin<"__spirv_BitwiseFunctionINTEL", OpenCL_std, TernaryBitwiseINTEL, 4, 4, OpBitwiseFunctionINTEL>;
720+
717721
//===----------------------------------------------------------------------===//
718722
// Class defining a work/sub group builtin that should be translated into a
719723
// SPIR-V instruction using the defined properties.

llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,9 @@ static const std::map<std::string, SPIRV::Extension::Extension, std::less<>>
9292
{"SPV_INTEL_long_composites",
9393
SPIRV::Extension::Extension::SPV_INTEL_long_composites},
9494
{"SPV_INTEL_fp_max_error",
95-
SPIRV::Extension::Extension::SPV_INTEL_fp_max_error}};
95+
SPIRV::Extension::Extension::SPV_INTEL_fp_max_error},
96+
{"SPV_INTEL_ternary_bitwise_function",
97+
SPIRV::Extension::Extension::SPV_INTEL_ternary_bitwise_function}};
9698

9799
bool SPIRVExtensionsParser::parse(cl::Option &O, StringRef ArgName,
98100
StringRef ArgValue,

llvm/lib/Target/SPIRV/SPIRVInstrInfo.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -928,3 +928,7 @@ def OpAliasScopeDeclINTEL: Op<5912, (outs ID:$res), (ins ID:$AliasDomain, variab
928928
"$res = OpAliasScopeDeclINTEL $AliasDomain">;
929929
def OpAliasScopeListDeclINTEL: Op<5913, (outs ID:$res), (ins variable_ops),
930930
"$res = OpAliasScopeListDeclINTEL">;
931+
932+
// SPV_INTEL_ternary_bitwise_function
933+
def OpBitwiseFunctionINTEL: Op<6242, (outs ID:$res), (ins TYPE:$type, ID:$a, ID:$b, ID:$c, ID:$lut_index),
934+
"$res = OpBitwiseFunctionINTEL $type $a $b $c $lut_index">;

llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1799,6 +1799,17 @@ void addInstrRequirements(const MachineInstr &MI,
17991799
Reqs.addCapability(SPIRV::Capability::LongCompositesINTEL);
18001800
break;
18011801
}
1802+
case SPIRV::OpBitwiseFunctionINTEL: {
1803+
if (!ST.canUseExtension(
1804+
SPIRV::Extension::SPV_INTEL_ternary_bitwise_function))
1805+
report_fatal_error(
1806+
"OpBitwiseFunctionINTEL instruction requires the following SPIR-V "
1807+
"extension: SPV_INTEL_ternary_bitwise_function",
1808+
false);
1809+
Reqs.addExtension(SPIRV::Extension::SPV_INTEL_ternary_bitwise_function);
1810+
Reqs.addCapability(SPIRV::Capability::TernaryBitwiseFunctionINTEL);
1811+
break;
1812+
}
18021813

18031814
default:
18041815
break;

llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ defm SPV_INTEL_bindless_images : ExtensionOperand<116>;
313313
defm SPV_INTEL_long_composites : ExtensionOperand<117>;
314314
defm SPV_INTEL_memory_access_aliasing : ExtensionOperand<118>;
315315
defm SPV_INTEL_fp_max_error : ExtensionOperand<119>;
316+
defm SPV_INTEL_ternary_bitwise_function : ExtensionOperand<120>;
316317

317318
//===----------------------------------------------------------------------===//
318319
// Multiclass used to define Capabilities enum values and at the same time
@@ -513,6 +514,7 @@ defm LongCompositesINTEL : CapabilityOperand<6089, 0, 0, [SPV_INTEL_long_composi
513514
defm BindlessImagesINTEL : CapabilityOperand<6528, 0, 0, [SPV_INTEL_bindless_images], []>;
514515
defm MemoryAccessAliasingINTEL : CapabilityOperand<5910, 0, 0, [SPV_INTEL_memory_access_aliasing], []>;
515516
defm FPMaxErrorINTEL : CapabilityOperand<6169, 0, 0, [SPV_INTEL_fp_max_error], []>;
517+
defm TernaryBitwiseFunctionINTEL : CapabilityOperand<6241, 0, 0, [SPV_INTEL_ternary_bitwise_function], []>;
516518

517519
//===----------------------------------------------------------------------===//
518520
// Multiclass used to define SourceLanguage enum values and at the same time
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s --spirv-ext=+SPV_INTEL_ternary_bitwise_function -o - | FileCheck %s --check-prefix=CHECK-EXTENSION
2+
; RUN: not llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-NO-EXTENSION
3+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s --spirv-ext=+SPV_INTEL_ternary_bitwise_function -o - -filetype=obj | spirv-val %}
4+
;
5+
; CHECK-NO-EXTENSION: LLVM ERROR: OpBitwiseFunctionINTEL instruction requires the following SPIR-V extension: SPV_INTEL_ternary_bitwise_function
6+
;
7+
; CHECK-EXTENSION-NOT: Name [[#]] "_Z28__spirv_BitwiseFunctionINTELiiij"
8+
; CHECK-EXTENSION-NOT: Name [[#]] "_Z28__spirv_BitwiseFunctionINTELDv4_iS_S_j"
9+
;
10+
; CHECK-EXTENSION-DAG: Capability TernaryBitwiseFunctionINTEL
11+
; CHECK-EXTENSION-DAG: Extension "SPV_INTEL_ternary_bitwise_function"
12+
; CHECK-EXTENSION-DAG: %[[#TYPEINT:]] = OpTypeInt 32 0
13+
; CHECK-EXTENSION-DAG: %[[#TYPEINTVEC4:]] = OpTypeVector %[[#TYPEINT]] 4
14+
; CHECK-EXTENSION-DAG: %[[#ScalarLUT:]] = OpConstant %[[#TYPEINT]] 24
15+
; CHECK-EXTENSION-DAG: %[[#VecLUT:]] = OpConstant %[[#TYPEINT]] 42
16+
; CHECK-EXTENSION: %[[#ScalarA:]] = OpLoad %[[#TYPEINT]]
17+
; CHECK-EXTENSION: %[[#ScalarB:]] = OpLoad %[[#TYPEINT]]
18+
; CHECK-EXTENSION: %[[#ScalarC:]] = OpLoad %[[#TYPEINT]]
19+
; CHECK-EXTENSION: %{{.*}} = OpBitwiseFunctionINTEL %[[#TYPEINT]] %[[#ScalarA]] %[[#ScalarB]] %[[#ScalarC]] %[[#ScalarLUT]]
20+
; CHECK-EXTENSION: %[[#VecA:]] = OpLoad %[[#TYPEINTVEC4]]
21+
; CHECK-EXTENSION: %[[#VecB:]] = OpLoad %[[#TYPEINTVEC4]]
22+
; CHECK-EXTENSION: %[[#VecC:]] = OpLoad %[[#TYPEINTVEC4]]
23+
; CHECK-EXTENSION: %{{.*}} = OpBitwiseFunctionINTEL %[[#TYPEINTVEC4]] %[[#VecA]] %[[#VecB]] %[[#VecC]] %[[#VecLUT]]
24+
25+
; Function Attrs: nounwind readnone
26+
define spir_kernel void @fooScalar() {
27+
entry:
28+
%argA = alloca i32
29+
%argB = alloca i32
30+
%argC = alloca i32
31+
%A = load i32, ptr %argA
32+
%B = load i32, ptr %argB
33+
%C = load i32, ptr %argC
34+
%res = call spir_func i32 @_Z28__spirv_BitwiseFunctionINTELiiii(i32 %A, i32 %B, i32 %C, i32 24)
35+
ret void
36+
}
37+
38+
; Function Attrs: nounwind readnone
39+
define spir_kernel void @fooVec() {
40+
entry:
41+
%argA = alloca <4 x i32>
42+
%argB = alloca <4 x i32>
43+
%argC = alloca <4 x i32>
44+
%A = load <4 x i32>, ptr %argA
45+
%B = load <4 x i32>, ptr %argB
46+
%C = load <4 x i32>, ptr %argC
47+
%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)
48+
ret void
49+
}
50+
51+
declare dso_local spir_func i32 @_Z28__spirv_BitwiseFunctionINTELiiii(i32, i32, i32, i32)
52+
declare dso_local spir_func <4 x i32> @_Z28__spirv_BitwiseFunctionINTELDv4_iS_S_i(<4 x i32>, <4 x i32>, <4 x i32>, i32)
53+
54+
!llvm.module.flags = !{!0}
55+
!opencl.spir.version = !{!1}
56+
57+
!0 = !{i32 1, !"wchar_size", i32 4}
58+
!1 = !{i32 1, i32 2}

0 commit comments

Comments
 (0)