Skip to content

Commit f802acf

Browse files
[SPIR-V] Add SPV_INTEL_predicated_io extension (#161591)
This PR introduces the support for the SPIR-V extension `SPV_INTEL_predicated_io`. This extension adds predicated load and store instructions. Predicated load performs load from memory if predicate is true; otherwise, it uses default_value as a result. Predicated store performs store of value to memory if predicate is true; otherwise, it does nothing. Reference Specification: https://github.com/intel/llvm/blob/sycl/sycl/doc/design/spirv-extensions/SPV_INTEL_predicated_io.asciidoc
1 parent 86ad98c commit f802acf

File tree

9 files changed

+99
-1
lines changed

9 files changed

+99
-1
lines changed

llvm/docs/SPIRVUsage.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,8 @@ Below is a list of supported SPIR-V extensions, sorted alphabetically by their e
233233
- Adds support for 4-bit integer type, and allow this type to be used in cooperative matrices.
234234
* - ``SPV_KHR_float_controls2``
235235
- Adds execution modes and decorations to control floating-point computations in both kernels and shaders. It can be used on whole modules and individual instructions.
236+
* - ``SPV_INTEL_predicated_io``
237+
- Adds predicated load and store instructions that conditionally read from or write to memory based on a boolean predicate.
236238

237239
SPIR-V representation in LLVM IR
238240
================================

llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,17 @@ void SPIRVInstPrinter::printInst(const MCInst *MI, uint64_t Address,
284284
}
285285
break;
286286
}
287+
case SPIRV::OpPredicatedLoadINTEL:
288+
case SPIRV::OpPredicatedStoreINTEL: {
289+
const unsigned NumOps = MI->getNumOperands();
290+
if (NumOps > NumFixedOps) {
291+
OS << ' ';
292+
printSymbolicOperand<OperandCategory::MemoryOperandOperand>(
293+
MI, NumOps - 1, OS);
294+
break;
295+
}
296+
break;
297+
}
287298
default:
288299
printRemainingVariableOps(MI, NumFixedOps, OS);
289300
break;

llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2419,6 +2419,27 @@ static bool generatePipeInst(const SPIRV::IncomingCall *Call,
24192419
return buildPipeInst(Call, Opcode, Scope, MIRBuilder, GR);
24202420
}
24212421

2422+
static bool generatePredicatedLoadStoreInst(const SPIRV::IncomingCall *Call,
2423+
MachineIRBuilder &MIRBuilder,
2424+
SPIRVGlobalRegistry *GR) {
2425+
const SPIRV::DemangledBuiltin *Builtin = Call->Builtin;
2426+
unsigned Opcode =
2427+
SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;
2428+
2429+
bool IsSet = Opcode != SPIRV::OpPredicatedStoreINTEL;
2430+
unsigned ArgSz = Call->Arguments.size();
2431+
SmallVector<uint32_t, 1> ImmArgs;
2432+
MachineRegisterInfo *MRI = MIRBuilder.getMRI();
2433+
// Memory operand is optional and is literal.
2434+
if (ArgSz > 3)
2435+
ImmArgs.push_back(
2436+
getConstFromIntrinsic(Call->Arguments[/*Literal index*/ 3], MRI));
2437+
2438+
Register TypeReg = GR->getSPIRVTypeID(Call->ReturnType);
2439+
return buildOpFromWrapper(MIRBuilder, Opcode, Call,
2440+
IsSet ? TypeReg : Register(0), ImmArgs);
2441+
}
2442+
24222443
static bool buildNDRange(const SPIRV::IncomingCall *Call,
24232444
MachineIRBuilder &MIRBuilder,
24242445
SPIRVGlobalRegistry *GR) {
@@ -3019,6 +3040,8 @@ std::optional<bool> lowerBuiltin(const StringRef DemangledCall,
30193040
return generate2DBlockIOINTELInst(Call.get(), MIRBuilder, GR);
30203041
case SPIRV::Pipe:
30213042
return generatePipeInst(Call.get(), MIRBuilder, GR);
3043+
case SPIRV::PredicatedLoadStore:
3044+
return generatePredicatedLoadStoreInst(Call.get(), MIRBuilder, GR);
30223045
}
30233046
return false;
30243047
}

llvm/lib/Target/SPIRV/SPIRVBuiltins.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ def BindlessINTEL : BuiltinGroup;
7070
def TernaryBitwiseINTEL : BuiltinGroup;
7171
def Block2DLoadStore : BuiltinGroup;
7272
def Pipe : BuiltinGroup;
73+
def PredicatedLoadStore : BuiltinGroup;
7374

7475
//===----------------------------------------------------------------------===//
7576
// Class defining a demangled builtin record. The information in the record
@@ -752,6 +753,10 @@ defm : DemangledNativeBuiltin<"__spirv_Subgroup2DBlockLoadTransformINTEL", OpenC
752753
defm : DemangledNativeBuiltin<"__spirv_Subgroup2DBlockPrefetchINTEL", OpenCL_std, Block2DLoadStore, 9, 9, OpSubgroup2DBlockPrefetchINTEL>;
753754
defm : DemangledNativeBuiltin<"__spirv_Subgroup2DBlockStoreINTEL", OpenCL_std, Block2DLoadStore, 10, 10, OpSubgroup2DBlockStoreINTEL>;
754755

756+
// SPV_INTEL_predicated_io builtin records
757+
defm : DemangledNativeBuiltin<"__spirv_PredicatedLoadINTEL", OpenCL_std, PredicatedLoadStore, 3, 4, OpPredicatedLoadINTEL>;
758+
defm : DemangledNativeBuiltin<"__spirv_PredicatedStoreINTEL", OpenCL_std, PredicatedLoadStore, 3, 4, OpPredicatedStoreINTEL>;
759+
755760
//===----------------------------------------------------------------------===//
756761
// Class defining a work/sub group builtin that should be translated into a
757762
// 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
@@ -151,7 +151,9 @@ static const std::map<std::string, SPIRV::Extension::Extension, std::less<>>
151151
{"SPV_KHR_bfloat16", SPIRV::Extension::Extension::SPV_KHR_bfloat16},
152152
{"SPV_EXT_relaxed_printf_string_address_space",
153153
SPIRV::Extension::Extension::
154-
SPV_EXT_relaxed_printf_string_address_space}};
154+
SPV_EXT_relaxed_printf_string_address_space},
155+
{"SPV_INTEL_predicated_io",
156+
SPIRV::Extension::Extension::SPV_INTEL_predicated_io}};
155157

156158
bool SPIRVExtensionsParser::parse(cl::Option &O, StringRef ArgName,
157159
StringRef ArgValue,

llvm/lib/Target/SPIRV/SPIRVInstrInfo.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -987,3 +987,9 @@ def OpSubgroup2DBlockPrefetchINTEL: Op<6234, (outs), (ins ID:$element_size, ID:$
987987
def OpSubgroup2DBlockStoreINTEL: Op<6235, (outs), (ins ID:$element_size, ID:$block_width, ID:$block_height,
988988
ID:$block_count, ID:$src_ptr, ID:$dst_base_ptr, ID:$memory_width, ID:$memory_height, ID:$memory_pitch, ID:$coord),
989989
"OpSubgroup2DBlockStoreINTEL $element_size $block_width $block_height $block_count $src_ptr $dst_base_ptr $memory_width $memory_height $memory_pitch $coord">;
990+
991+
// SPV_INTEL_predicated_io
992+
def OpPredicatedLoadINTEL: Op<6528, (outs ID:$res), (ins TYPE:$resType, ID:$ptr, ID:$predicate, ID:$default_value, variable_ops),
993+
"$res = OpPredicatedLoadINTEL $resType $ptr $predicate $default_value">;
994+
def OpPredicatedStoreINTEL: Op<6529, (outs), (ins ID:$ptr, ID:$object, ID:$predicate, variable_ops),
995+
"OpPredicatedStoreINTEL $ptr $object $predicate">;

llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2035,6 +2035,17 @@ void addInstrRequirements(const MachineInstr &MI,
20352035
// TODO: Add UntypedPointersKHR when implemented.
20362036
break;
20372037
}
2038+
case SPIRV::OpPredicatedLoadINTEL:
2039+
case SPIRV::OpPredicatedStoreINTEL: {
2040+
if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_predicated_io))
2041+
report_fatal_error(
2042+
"OpPredicated[Load/Store]INTEL instructions require "
2043+
"the following SPIR-V extension: SPV_INTEL_predicated_io",
2044+
false);
2045+
Reqs.addExtension(SPIRV::Extension::SPV_INTEL_predicated_io);
2046+
Reqs.addCapability(SPIRV::Capability::PredicatedIOINTEL);
2047+
break;
2048+
}
20382049

20392050
default:
20402051
break;

llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@ defm SPV_INTEL_int4 : ExtensionOperand<123, [EnvOpenCL]>;
385385
defm SPV_KHR_float_controls2 : ExtensionOperand<124, [EnvVulkan, EnvOpenCL]>;
386386
defm SPV_INTEL_tensor_float32_conversion : ExtensionOperand<125, [EnvOpenCL]>;
387387
defm SPV_KHR_bfloat16 : ExtensionOperand<126, [EnvVulkan, EnvOpenCL]>;
388+
defm SPV_INTEL_predicated_io : ExtensionOperand<127, [EnvOpenCL]>;
388389

389390
//===----------------------------------------------------------------------===//
390391
// Multiclass used to define Capabilities enum values and at the same time
@@ -594,6 +595,7 @@ defm SubgroupMatrixMultiplyAccumulateINTEL : CapabilityOperand<6236, 0, 0, [SPV_
594595
defm Subgroup2DBlockIOINTEL : CapabilityOperand<6228, 0, 0, [SPV_INTEL_2d_block_io], []>;
595596
defm Subgroup2DBlockTransformINTEL : CapabilityOperand<6229, 0, 0, [SPV_INTEL_2d_block_io], [Subgroup2DBlockIOINTEL]>;
596597
defm Subgroup2DBlockTransposeINTEL : CapabilityOperand<6230, 0, 0, [SPV_INTEL_2d_block_io], [Subgroup2DBlockIOINTEL]>;
598+
defm PredicatedIOINTEL : CapabilityOperand<6257, 0, 0, [SPV_INTEL_predicated_io], []>;
597599
defm Int4TypeINTEL : CapabilityOperand<5112, 0, 0, [SPV_INTEL_int4], []>;
598600
defm Int4CooperativeMatrixINTEL : CapabilityOperand<5114, 0, 0, [SPV_INTEL_int4], [Int4TypeINTEL, CooperativeMatrixKHR]>;
599601
defm TensorFloat32RoundingINTEL : CapabilityOperand<6425, 0, 0, [SPV_INTEL_tensor_float32_conversion], []>;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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 -verify-machineinstrs -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_predicated_io %s -o - | FileCheck %s
3+
4+
; CHECK-ERROR: LLVM ERROR: OpPredicated[Load/Store]INTEL
5+
; CHECK-ERROR-SAME: instructions require the following SPIR-V extension: SPV_INTEL_predicated_io
6+
7+
; CHECK-DAG: Capability PredicatedIOINTEL
8+
; CHECK-DAG: Extension "SPV_INTEL_predicated_io"
9+
10+
; CHECK-DAG: %[[Int32Ty:[0-9]+]] = OpTypeInt 32 0
11+
; CHECK-DAG: %[[IntPtrTy:[0-9]+]] = OpTypePointer CrossWorkgroup %[[Int32Ty]]
12+
; CHECK-DAG: %[[BoolTy:[0-9]+]] = OpTypeBool
13+
; CHECK-DAG: %[[VoidTy:[0-9]+]] = OpTypeVoid
14+
; CHECK: %[[LoadPtr:[0-9]+]] = OpFunctionParameter %[[IntPtrTy]]
15+
; CHECK: %[[StorePtr:[0-9]+]] = OpFunctionParameter %[[IntPtrTy]]
16+
; CHECK: %[[DefaultVal:[0-9]+]] = OpFunctionParameter %[[Int32Ty]]
17+
; CHECK: %[[StoreObj:[0-9]+]] = OpFunctionParameter %[[Int32Ty]]
18+
; CHECK: %[[Predicate:[0-9]+]] = OpFunctionParameter %[[BoolTy]]
19+
; CHECK: PredicatedLoadINTEL %[[Int32Ty]] %[[LoadPtr]] %[[Predicate]] %[[DefaultVal]]
20+
; CHECK: PredicatedLoadINTEL %[[Int32Ty]] %[[LoadPtr]] %[[Predicate]] %[[DefaultVal]] None
21+
; CHECK: PredicatedStoreINTEL %[[StorePtr]] %[[StoreObj]] %[[Predicate]]
22+
; CHECK: PredicatedStoreINTEL %[[StorePtr]] %[[StoreObj]] %[[Predicate]] None
23+
24+
define spir_func void @foo(ptr addrspace(1) %load_pointer, ptr addrspace(1) %store_pointer, i32 %default_value, i32 %store_object, i1 zeroext %predicate) {
25+
entry:
26+
%1 = call spir_func i32 @_Z27__spirv_PredicatedLoadINTELPU3AS1Kibi(ptr addrspace(1) %load_pointer, i1 %predicate, i32 %default_value)
27+
%2 = call spir_func i32 @_Z27__spirv_PredicatedLoadINTELPU3AS1Kibii(ptr addrspace(1) %load_pointer, i1 %predicate, i32 %default_value, i32 0)
28+
call spir_func void @_Z28__spirv_PredicatedStoreINTELPU3AS1Kiib(ptr addrspace(1) %store_pointer, i32 %store_object, i1 %predicate)
29+
call spir_func void @_Z28__spirv_PredicatedStoreINTELPU3AS1Kiibi(ptr addrspace(1) %store_pointer, i32 %store_object, i1 %predicate, i32 0)
30+
ret void
31+
}
32+
33+
declare spir_func i32 @_Z27__spirv_PredicatedLoadINTELPU3AS1Kibi(ptr addrspace(1), i1, i32)
34+
declare spir_func i32 @_Z27__spirv_PredicatedLoadINTELPU3AS1Kibii(ptr addrspace(1), i1, i32, i32)
35+
declare spir_func void @_Z28__spirv_PredicatedStoreINTELPU3AS1Kiib(ptr addrspace(1), i32, i1)
36+
declare spir_func void @_Z28__spirv_PredicatedStoreINTELPU3AS1Kiibi(ptr addrspace(1), i32, i1, i32)

0 commit comments

Comments
 (0)