Skip to content

Commit 82eb294

Browse files
committed
[SPIR-V] Add SPV_INTEL_2d_block_io extension
Adds additional subgroup block prefetch, load, load transposed, load transformed and store instructions to read two-dimensional blocks of data from a two-dimensional region of memory, or to write two-dimensional blocks of data to a two-dimensional region of memory. Spec: https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/INTEL/SPV_INTEL_2d_block_io.asciidoc
1 parent 0285dff commit 82eb294

File tree

8 files changed

+136
-1
lines changed

8 files changed

+136
-1
lines changed

llvm/docs/SPIRVUsage.rst

+2
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ list of supported SPIR-V extensions, sorted alphabetically by their extension na
153153
- Adds atomic add instruction on floating-point numbers.
154154
* - ``SPV_EXT_shader_atomic_float_min_max``
155155
- Adds atomic min and max instruction on floating-point numbers.
156+
* - ``SPV_INTEL_2d_block_io``
157+
- Adds additional subgroup block prefetch, load, load transposed, load transformed and store instructions to read two-dimensional blocks of data from a two-dimensional region of memory, or to write two-dimensional blocks of data to a two dimensional region of memory.
156158
* - ``SPV_INTEL_arbitrary_precision_integers``
157159
- Allows generating arbitrary width integer types.
158160
* - ``SPV_INTEL_bindless_images``

llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp

+31
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 2d block io instructions.
1062+
static bool build2DBlockIOINTELInst(const SPIRV::IncomingCall *Call,
1063+
unsigned Opcode,
1064+
MachineIRBuilder &MIRBuilder,
1065+
SPIRVGlobalRegistry *GR) {
1066+
// Generate SPIRV instruction accordingly.
1067+
if (Call->isSpirvOp())
1068+
return buildOpFromWrapper(MIRBuilder, Opcode, Call, Register(0));
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,17 @@ static bool generateBindlessImageINTELInst(const SPIRV::IncomingCall *Call,
22642282
return buildBindlessImageINTELInst(Call, Opcode, MIRBuilder, GR);
22652283
}
22662284

2285+
static bool generate2DBlockIOINTELInst(const SPIRV::IncomingCall *Call,
2286+
MachineIRBuilder &MIRBuilder,
2287+
SPIRVGlobalRegistry *GR) {
2288+
// Lookup the instruction opcode in the TableGen records.
2289+
const SPIRV::DemangledBuiltin *Builtin = Call->Builtin;
2290+
unsigned Opcode =
2291+
SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;
2292+
2293+
return build2DBlockIOINTELInst(Call, Opcode, MIRBuilder, GR);
2294+
}
2295+
22672296
static bool buildNDRange(const SPIRV::IncomingCall *Call,
22682297
MachineIRBuilder &MIRBuilder,
22692298
SPIRVGlobalRegistry *GR) {
@@ -2845,6 +2874,8 @@ std::optional<bool> lowerBuiltin(const StringRef DemangledCall,
28452874
return generateExtendedBitOpsInst(Call.get(), MIRBuilder, GR);
28462875
case SPIRV::BindlessINTEL:
28472876
return generateBindlessImageINTELInst(Call.get(), MIRBuilder, GR);
2877+
case SPIRV::Block2DLoadStore:
2878+
return generate2DBlockIOINTELInst(Call.get(), MIRBuilder, GR);
28482879
}
28492880
return false;
28502881
}

llvm/lib/Target/SPIRV/SPIRVBuiltins.td

+8
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 Block2DLoadStore : BuiltinGroup;
7071

7172
//===----------------------------------------------------------------------===//
7273
// Class defining a demangled builtin record. The information in the record
@@ -714,6 +715,13 @@ 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_2d_block_io builtin records
719+
defm : DemangledNativeBuiltin<"__spirv_Subgroup2DBlockLoadINTEL", OpenCL_std, Block2DLoadStore, 10, 10, OpSubgroup2DBlockLoadINTEL>;
720+
defm : DemangledNativeBuiltin<"__spirv_Subgroup2DBlockLoadTransposeINTEL", OpenCL_std, Block2DLoadStore, 10, 10, OpSubgroup2DBlockLoadTransposeINTEL>;
721+
defm : DemangledNativeBuiltin<"__spirv_Subgroup2DBlockLoadTransformINTEL", OpenCL_std, Block2DLoadStore, 10, 10, OpSubgroup2DBlockLoadTransformINTEL>;
722+
defm : DemangledNativeBuiltin<"__spirv_Subgroup2DBlockPrefetchINTEL", OpenCL_std, Block2DLoadStore, 9, 9, OpSubgroup2DBlockPrefetchINTEL>;
723+
defm : DemangledNativeBuiltin<"__spirv_Subgroup2DBlockStoreINTEL", OpenCL_std, Block2DLoadStore, 10, 10, OpSubgroup2DBlockStoreINTEL>;
724+
717725
//===----------------------------------------------------------------------===//
718726
// Class defining a work/sub group builtin that should be translated into a
719727
// SPIR-V instruction using the defined properties.

llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp

+3-1
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_2d_block_io",
97+
SPIRV::Extension::Extension::SPV_INTEL_2d_block_io}};
9698

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

llvm/lib/Target/SPIRV/SPIRVInstrInfo.td

+17
Original file line numberDiff line numberDiff line change
@@ -928,3 +928,20 @@ 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_2d_block_io
933+
def OpSubgroup2DBlockLoadINTEL: Op<6231, (outs), (ins ID:$element_size, ID:$block_width, ID:$block_height,
934+
ID:$block_count, ID:$src_base_ptr, ID:$memory_width, ID:$memory_height, ID:$memory_pitch, ID:$coord, ID:$dst_ptr),
935+
"OpSubgroup2DBlockLoadINTEL $element_size $block_width $block_height $block_count $src_base_ptr $memory_width $memory_height $memory_pitch $coord $dst_ptr">;
936+
def OpSubgroup2DBlockLoadTransposeINTEL: Op<6233, (outs), (ins ID:$element_size, ID:$block_width, ID:$block_height,
937+
ID:$block_count, ID:$src_base_ptr, ID:$memory_width, ID:$memory_height, ID:$memory_pitch, ID:$coord, ID:$dst_ptr),
938+
"OpSubgroup2DBlockLoadTransposeINTEL $element_size $block_width $block_height $block_count $src_base_ptr $memory_width $memory_height $memory_pitch $coord $dst_ptr">;
939+
def OpSubgroup2DBlockLoadTransformINTEL: Op<6232, (outs), (ins ID:$element_size, ID:$block_width, ID:$block_height,
940+
ID:$block_count, ID:$src_base_ptr, ID:$memory_width, ID:$memory_height, ID:$memory_pitch, ID:$coord, ID:$dst_ptr),
941+
"OpSubgroup2DBlockLoadTransformINTEL $element_size $block_width $block_height $block_count $src_base_ptr $memory_width $memory_height $memory_pitch $coord $dst_ptr">;
942+
def OpSubgroup2DBlockPrefetchINTEL: Op<6234, (outs), (ins ID:$element_size, ID:$block_width, ID:$block_height,
943+
ID:$block_count, ID:$src_base_ptr, ID:$memory_width, ID:$memory_height, ID:$memory_pitch, ID:$coord),
944+
"OpSubgroup2DBlockPrefetchINTEL $element_size $block_width $block_height $block_count $src_base_ptr $memory_width $memory_height $memory_pitch $coord">;
945+
def OpSubgroup2DBlockStoreINTEL: Op<6235, (outs), (ins ID:$element_size, ID:$block_width, ID:$block_height,
946+
ID:$block_count, ID:$src_ptr, ID:$dst_base_ptr, ID:$memory_width, ID:$memory_height, ID:$memory_pitch, ID:$coord),
947+
"OpSubgroup2DBlockStoreINTEL $element_size $block_width $block_height $block_count $src_ptr $dst_base_ptr $memory_width $memory_height $memory_pitch $coord">;

llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -1739,6 +1739,30 @@ void addInstrRequirements(const MachineInstr &MI,
17391739
Reqs.addExtension(SPIRV::Extension::SPV_INTEL_bindless_images);
17401740
Reqs.addCapability(SPIRV::Capability::BindlessImagesINTEL);
17411741
break;
1742+
case SPIRV::OpSubgroup2DBlockLoadINTEL:
1743+
case SPIRV::OpSubgroup2DBlockLoadTransposeINTEL:
1744+
case SPIRV::OpSubgroup2DBlockLoadTransformINTEL:
1745+
case SPIRV::OpSubgroup2DBlockPrefetchINTEL:
1746+
case SPIRV::OpSubgroup2DBlockStoreINTEL: {
1747+
if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_2d_block_io))
1748+
report_fatal_error("OpSubgroup2DBlock[Load/LoadTranspose/LoadTransform/"
1749+
"Prefetch/Store]INTEL instructions require the "
1750+
"following SPIR-V extension: SPV_INTEL_2d_block_io",
1751+
false);
1752+
Reqs.addExtension(SPIRV::Extension::SPV_INTEL_2d_block_io);
1753+
Reqs.addCapability(SPIRV::Capability::Subgroup2DBlockIOINTEL);
1754+
1755+
const auto OpCode = MI.getOpcode();
1756+
if (OpCode == SPIRV::OpSubgroup2DBlockLoadTransposeINTEL) {
1757+
Reqs.addCapability(SPIRV::Capability::Subgroup2DBlockTransposeINTEL);
1758+
break;
1759+
}
1760+
if (OpCode == SPIRV::OpSubgroup2DBlockLoadTransformINTEL) {
1761+
Reqs.addCapability(SPIRV::Capability::Subgroup2DBlockTransformINTEL);
1762+
break;
1763+
}
1764+
break;
1765+
}
17421766
case SPIRV::OpKill: {
17431767
Reqs.addCapability(SPIRV::Capability::Shader);
17441768
} break;

llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td

+4
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_2d_block_io : ExtensionOperand<120>;
316317

317318
//===----------------------------------------------------------------------===//
318319
// Multiclass used to define Capabilities enum values and at the same time
@@ -513,6 +514,9 @@ 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 Subgroup2DBlockIOINTEL : CapabilityOperand<6228, 0, 0, [SPV_INTEL_2d_block_io], []>;
518+
defm Subgroup2DBlockTransformINTEL : CapabilityOperand<6229, 0, 0, [SPV_INTEL_2d_block_io], [Subgroup2DBlockIOINTEL]>;
519+
defm Subgroup2DBlockTransposeINTEL : CapabilityOperand<6230, 0, 0, [SPV_INTEL_2d_block_io], [Subgroup2DBlockIOINTEL]>;
516520

517521
//===----------------------------------------------------------------------===//
518522
// Multiclass used to define SourceLanguage enum values and at the same time
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
; RUN: not llc -O0 -mtriple=spirv64-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
2+
; RUN: llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_2d_block_io %s -o - | FileCheck %s
3+
4+
; CHECK-ERROR: LLVM ERROR: OpSubgroup2DBlock[Load/LoadTranspose/LoadTransform/Prefetch/Store]INTEL
5+
; CHECK-ERROR-SAME: instructions require the following SPIR-V extension: SPV_INTEL_2d_block_io
6+
7+
; CHECK: OpCapability Subgroup2DBlockIOINTEL
8+
; CHECK: OpCapability Subgroup2DBlockTransformINTEL
9+
; CHECK: OpCapability Subgroup2DBlockTransposeINTEL
10+
; CHECK: OpExtension "SPV_INTEL_2d_block_io"
11+
12+
; CHECK-DAG: %[[Int8Ty:[0-9]+]] = OpTypeInt 8 0
13+
; CHECK-DAG: %[[Int32Ty:[0-9]+]] = OpTypeInt 32 0
14+
; CHECK-DAG: %[[Const42:[0-9]+]] = OpConstant %[[Int32Ty]] 42
15+
; CHECK-DAG: %[[VoidTy:[0-9]+]] = OpTypeVoid
16+
; CHECK-DAG: %[[GlbPtrTy:[0-9]+]] = OpTypePointer CrossWorkgroup %[[Int8Ty]]
17+
; CHECK-DAG: %[[VectorTy:[0-9]+]] = OpTypeVector %[[Int32Ty]] 2
18+
; CHECK-DAG: %[[PrvPtrTy:[0-9]+]] = OpTypePointer Function %[[Int8Ty]]
19+
; CHECK: %[[BaseSrc:[0-9]+]] = OpFunctionParameter %[[GlbPtrTy]]
20+
; CHECK: %[[BaseDst:[0-9]+]] = OpFunctionParameter %[[GlbPtrTy]]
21+
; CHECK: %[[Width:[0-9]+]] = OpFunctionParameter %[[Int32Ty]]
22+
; CHECK: %[[Height:[0-9]+]] = OpFunctionParameter %[[Int32Ty]]
23+
; CHECK: %[[Pitch:[0-9]+]] = OpFunctionParameter %[[Int32Ty]]
24+
; CHECK: %[[Coord:[0-9]+]] = OpFunctionParameter %[[VectorTy]]
25+
; CHECK: %[[Dst:[0-9]+]] = OpFunctionParameter %[[PrvPtrTy]]
26+
; CHECK: %[[Src:[0-9]+]] = OpFunctionParameter %[[PrvPtrTy]]
27+
; CHECK: OpSubgroup2DBlockLoadINTEL %[[Const42]] %[[Const42]] %[[Const42]] %[[Const42]] %[[BaseSrc]] %[[Width]] %[[Height]] %[[Pitch]] %[[Coord]] %[[Dst]]
28+
; CHECK: OpSubgroup2DBlockLoadTransformINTEL %[[Const42]] %[[Const42]] %[[Const42]] %[[Const42]] %[[BaseSrc]] %[[Width]] %[[Height]] %[[Pitch]] %[[Coord]] %[[Dst]]
29+
; CHECK: OpSubgroup2DBlockLoadTransposeINTEL %[[Const42]] %[[Const42]] %[[Const42]] %[[Const42]] %[[BaseSrc]] %[[Width]] %[[Height]] %[[Pitch]] %[[Coord]] %[[Dst]]
30+
; CHECK: OpSubgroup2DBlockPrefetchINTEL %[[Const42]] %[[Const42]] %[[Const42]] %[[Const42]] %[[BaseSrc]] %[[Width]] %[[Height]] %[[Pitch]] %[[Coord]]
31+
; CHECK: OpSubgroup2DBlockStoreINTEL %[[Const42]] %[[Const42]] %[[Const42]] %[[Const42]] %[[Src]] %[[BaseDst]] %[[Width]] %[[Height]] %[[Pitch]] %[[Coord]]
32+
33+
define spir_func void @foo(ptr addrspace(1) %base_address, ptr addrspace(1) %dst_base_pointer, i32 %width, i32 %height, i32 %pitch, <2 x i32> %coord, ptr %dst_pointer, ptr %src_pointer) {
34+
entry:
35+
call spir_func void @_Z32__spirv_Subgroup2DBlockLoadINTELiiiiPU3AS1KviiiDv2_iPv(i32 42, i32 42, i32 42, i32 42, ptr addrspace(1) %base_address, i32 %width, i32 %height, i32 %pitch, <2 x i32> %coord, ptr %dst_pointer)
36+
call spir_func void @_Z41__spirv_Subgroup2DBlockLoadTransformINTELiiiiPU3AS1KviiiDv2_iPv(i32 42, i32 42, i32 42, i32 42, ptr addrspace(1) %base_address, i32 %width, i32 %height, i32 %pitch, <2 x i32> %coord, ptr %dst_pointer)
37+
call spir_func void @_Z41__spirv_Subgroup2DBlockLoadTransposeINTELiiiiPU3AS1KviiiDv2_iPv(i32 42, i32 42, i32 42, i32 42, ptr addrspace(1) %base_address, i32 %width, i32 %height, i32 %pitch, <2 x i32> %coord, ptr %dst_pointer)
38+
call spir_func void @_Z36__spirv_Subgroup2DBlockPrefetchINTELiiiiPU3AS1KviiiDv2_i(i32 42, i32 42, i32 42, i32 42, ptr addrspace(1) %base_address, i32 %width, i32 %height, i32 %pitch, <2 x i32> %coord)
39+
call spir_func void @_Z33__spirv_Subgroup2DBlockStoreINTELiiiiPKvPU3AS1viiiDv2_i(i32 42, i32 42, i32 42, i32 42, ptr %src_pointer, ptr addrspace(1) %dst_base_pointer, i32 %width, i32 %height, i32 %pitch, <2 x i32> %coord)
40+
ret void
41+
}
42+
43+
declare spir_func void @_Z32__spirv_Subgroup2DBlockLoadINTELiiiiPU3AS1KviiiDv2_iPv(i32, i32, i32, i32, ptr addrspace(1), i32, i32, i32, <2 x i32>, ptr)
44+
declare spir_func void @_Z41__spirv_Subgroup2DBlockLoadTransformINTELiiiiPU3AS1KviiiDv2_iPv(i32, i32, i32, i32, ptr addrspace(1), i32, i32, i32, <2 x i32>, ptr)
45+
declare spir_func void @_Z41__spirv_Subgroup2DBlockLoadTransposeINTELiiiiPU3AS1KviiiDv2_iPv(i32, i32, i32, i32, ptr addrspace(1), i32, i32, i32, <2 x i32>, ptr)
46+
declare spir_func void @_Z36__spirv_Subgroup2DBlockPrefetchINTELiiiiPU3AS1KviiiDv2_i(i32, i32, i32, i32, ptr addrspace(1), i32, i32, i32, <2 x i32>)
47+
declare spir_func void @_Z33__spirv_Subgroup2DBlockStoreINTELiiiiPKvPU3AS1viiiDv2_i(i32, i32, i32, i32, ptr, ptr addrspace(1), i32, i32, i32, <2 x i32>)

0 commit comments

Comments
 (0)