Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions llvm/docs/SPIRVUsage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,8 @@ Below is a list of supported SPIR-V extensions, sorted alphabetically by their e
- Adds predicated load and store instructions that conditionally read from or write to memory based on a boolean predicate.
* - ``SPV_KHR_maximal_reconvergence``
- Adds execution mode and capability to enable maximal reconvergence.
* - ``SPV_ALTERA_blocking_pipes``
- Adds new pipe read and write functions that have blocking semantics instead of the non-blocking semantics of the existing pipe read/write functions.

SPIR-V representation in LLVM IR
================================
Expand Down
11 changes: 11 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2390,6 +2390,15 @@ static bool generateBindlessImageINTELInst(const SPIRV::IncomingCall *Call,
return buildBindlessImageINTELInst(Call, Opcode, MIRBuilder, GR);
}

static bool generateBlockingPipesInst(const SPIRV::IncomingCall *Call,
MachineIRBuilder &MIRBuilder,
SPIRVGlobalRegistry *GR) {
const SPIRV::DemangledBuiltin *Builtin = Call->Builtin;
unsigned Opcode =
SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;
return buildOpFromWrapper(MIRBuilder, Opcode, Call, Register(0));
}

static bool
generateTernaryBitwiseFunctionINTELInst(const SPIRV::IncomingCall *Call,
MachineIRBuilder &MIRBuilder,
Expand Down Expand Up @@ -3050,6 +3059,8 @@ std::optional<bool> lowerBuiltin(const StringRef DemangledCall,
return generatePipeInst(Call.get(), MIRBuilder, GR);
case SPIRV::PredicatedLoadStore:
return generatePredicatedLoadStoreInst(Call.get(), MIRBuilder, GR);
case SPIRV::BlockingPipes:
return generateBlockingPipesInst(Call.get(), MIRBuilder, GR);
}
return false;
}
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVBuiltins.td
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ def TernaryBitwiseINTEL : BuiltinGroup;
def Block2DLoadStore : BuiltinGroup;
def Pipe : BuiltinGroup;
def PredicatedLoadStore : BuiltinGroup;
def BlockingPipes : BuiltinGroup;

//===----------------------------------------------------------------------===//
// Class defining a demangled builtin record. The information in the record
Expand Down Expand Up @@ -1174,6 +1175,10 @@ defm : DemangledNativeBuiltin<"clock_read_sub_group", OpenCL_std, KernelClock, 0
defm : DemangledNativeBuiltin<"clock_read_hilo_device", OpenCL_std, KernelClock, 0, 0, OpReadClockKHR>;
defm : DemangledNativeBuiltin<"clock_read_hilo_work_group", OpenCL_std, KernelClock, 0, 0, OpReadClockKHR>;
defm : DemangledNativeBuiltin<"clock_read_hilo_sub_group", OpenCL_std, KernelClock, 0, 0, OpReadClockKHR>;

//SPV_ALTERA_blocking_pipes
defm : DemangledNativeBuiltin<"__spirv_WritePipeBlockingINTEL", OpenCL_std, BlockingPipes, 0, 0, OpWritePipeBlockingALTERA>;
defm : DemangledNativeBuiltin<"__spirv_ReadPipeBlockingINTEL", OpenCL_std, BlockingPipes, 0, 0, OpReadPipeBlockingALTERA>;
defm : DemangledNativeBuiltin<"__spirv_ReadClockKHR", OpenCL_std, KernelClock, 1, 1, OpReadClockKHR>;

//===----------------------------------------------------------------------===//
Expand Down
4 changes: 3 additions & 1 deletion llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,9 @@ static const std::map<std::string, SPIRV::Extension::Extension, std::less<>>
{"SPV_KHR_maximal_reconvergence",
SPIRV::Extension::Extension::SPV_KHR_maximal_reconvergence},
{"SPV_INTEL_kernel_attributes",
SPIRV::Extension::Extension::SPV_INTEL_kernel_attributes}};
SPIRV::Extension::Extension::SPV_INTEL_kernel_attributes},
{"SPV_ALTERA_blocking_pipes",
SPIRV::Extension::Extension::SPV_ALTERA_blocking_pipes}};

bool SPIRVExtensionsParser::parse(cl::Option &O, StringRef ArgName,
StringRef ArgValue,
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -993,3 +993,9 @@ def OpPredicatedLoadINTEL: Op<6528, (outs ID:$res), (ins TYPE:$resType, ID:$ptr,
"$res = OpPredicatedLoadINTEL $resType $ptr $predicate $default_value">;
def OpPredicatedStoreINTEL: Op<6529, (outs), (ins ID:$ptr, ID:$object, ID:$predicate, variable_ops),
"OpPredicatedStoreINTEL $ptr $object $predicate">;

//SPV_ALTERA_blocking_pipes
def OpReadPipeBlockingALTERA :Op<5946, (outs), (ins ID:$pipe, ID:$pointer, ID:$packetSize, ID:$packetAlignment),
"OpReadPipeBlockingALTERA $pipe $pointer $packetSize $packetAlignment">;
def OpWritePipeBlockingALTERA :Op<5946, (outs), (ins ID:$pipe, ID:$pointer, ID:$packetSize, ID:$packetAlignment),
"OpWritePipeBlockingALTERA $pipe $pointer $packetSize $packetAlignment">;
7 changes: 7 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1885,6 +1885,13 @@ void addInstrRequirements(const MachineInstr &MI,
Reqs.addCapability(
SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
break;
case SPIRV::OpReadPipeBlockingALTERA:
case SPIRV::OpWritePipeBlockingALTERA:
if (ST.canUseExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes)) {
Reqs.addExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes);
Reqs.addCapability(SPIRV::Capability::BlockingPipesALTERA);
}
break;
case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:
if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
report_fatal_error("OpCooperativeMatrixGetElementCoordINTEL requires the "
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ defm SPV_KHR_shader_clock : ExtensionOperand<54, [EnvVulkan, EnvOpenCL]>;
defm SPV_INTEL_unstructured_loop_controls : ExtensionOperand<55, [EnvOpenCL]>;
defm SPV_EXT_demote_to_helper_invocation : ExtensionOperand<56, [EnvVulkan]>;
defm SPV_INTEL_fpga_reg : ExtensionOperand<57, [EnvOpenCL]>;
defm SPV_INTEL_blocking_pipes : ExtensionOperand<58, [EnvOpenCL]>;
defm SPV_ALTERA_blocking_pipes : ExtensionOperand<58, [EnvOpenCL]>;
defm SPV_GOOGLE_user_type : ExtensionOperand<59, [EnvVulkan]>;
defm SPV_KHR_physical_storage_buffer : ExtensionOperand<60, [EnvVulkan]>;
defm SPV_INTEL_kernel_attributes : ExtensionOperand<61, [EnvOpenCL]>;
Expand Down Expand Up @@ -611,6 +611,7 @@ defm TensorFloat32RoundingINTEL : CapabilityOperand<6425, 0, 0, [SPV_INTEL_tenso
defm BFloat16TypeKHR : CapabilityOperand<5116, 0, 0, [SPV_KHR_bfloat16], []>;
defm BFloat16DotProductKHR : CapabilityOperand<5117, 0, 0, [SPV_KHR_bfloat16], [BFloat16TypeKHR]>;
defm BFloat16CooperativeMatrixKHR : CapabilityOperand<5118, 0, 0, [SPV_KHR_bfloat16], [BFloat16TypeKHR, CooperativeMatrixKHR]>;
defm BlockingPipesALTERA : CapabilityOperand<5945, 0, 0, [SPV_ALTERA_blocking_pipes], []>;

//===----------------------------------------------------------------------===//
// Multiclass used to define SourceLanguage enum values and at the same time
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_ALTERA_blocking_pipes %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV
; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_ALTERA_blocking_pipes %s -o - -filetype=obj | spirv-val %}

%opencl.pipe_ro_t = type opaque
%opencl.pipe_wo_t = type opaque

; CHECK-SPIRV: OpCapability BlockingPipesALTERA
; CHECK-SPIRV: OpExtension "SPV_ALTERA_blocking_pipes"
; CHECK-SPIRV: %[[PipeRTy:[0-9]+]] = OpTypePipe ReadOnly
; CHECK-SPIRV: %[[PipeWTy:[0-9]+]] = OpTypePipe WriteOnly
; CHECK-SPIRV: %[[PipeR1:[0-9]+]] = OpLoad %[[PipeRTy]] %[[#]] Aligned 8
; CHECK-SPIRV: OpReadPipeBlockingALTERA %[[PipeR1]] %[[#]] %[[#]] %[[#]]
; CHECK-SPIRV: %[[PipeR2:[0-9]+]] = OpLoad %[[PipeRTy]] %[[#]] Aligned 8
; CHECK-SPIRV: OpReadPipeBlockingALTERA %[[PipeR2]] %[[#]] %[[#]] %[[#]]
; CHECK-SPIRV: %[[PipeW1:[0-9]+]] = OpLoad %[[PipeWTy]] %[[#]] Aligned 8
; CHECK-SPIRV: OpWritePipeBlockingALTERA %[[PipeW1]] %[[#]] %[[#]] %[[#]]
; CHECK-SPIRV: %[[PipeW2:[0-9]+]] = OpLoad %[[PipeWTy]] %[[#]] Aligned 8
; CHECK-SPIRV: OpWritePipeBlockingALTERA %[[PipeW2]] %[[#]] %[[#]] %[[#]]

define spir_func void @foo(target("spirv.Pipe", 0) %p, ptr addrspace(1) %ptr) {
entry:
%p.addr = alloca target("spirv.Pipe", 0), align 8
%ptr.addr = alloca ptr addrspace(1), align 8
store target("spirv.Pipe", 0) %p, target("spirv.Pipe", 0)* %p.addr, align 8
store ptr addrspace(1) %ptr, ptr %ptr.addr, align 8
%0 = load target("spirv.Pipe", 0), target("spirv.Pipe", 0)* %p.addr, align 8
%1 = load ptr addrspace(1), ptr %ptr.addr, align 8
%2 = addrspacecast ptr addrspace(1) %1 to ptr addrspace(4)
call spir_func void @_Z29__spirv_ReadPipeBlockingINTELIiEv8ocl_pipePiii(target("spirv.Pipe", 0) %0, ptr addrspace(4) %2, i32 4, i32 4)
ret void
}

declare dso_local spir_func void @_Z29__spirv_ReadPipeBlockingINTELIiEv8ocl_pipePiii(target("spirv.Pipe", 0), ptr addrspace(4), i32, i32)

define spir_func void @bar(target("spirv.Pipe", 0) %p, ptr addrspace(1) %ptr) {
entry:
%p.addr = alloca target("spirv.Pipe", 0), align 8
%ptr.addr = alloca ptr addrspace(1), align 8
store target("spirv.Pipe", 0) %p, target("spirv.Pipe", 0)* %p.addr, align 8
store ptr addrspace(1) %ptr, ptr %ptr.addr, align 8
%0 = load target("spirv.Pipe", 0), target("spirv.Pipe", 0)* %p.addr, align 8
%1 = load ptr addrspace(1), ptr %ptr.addr, align 8
%2 = addrspacecast ptr addrspace(1) %1 to ptr addrspace(4)
call spir_func void @_Z29__spirv_ReadPipeBlockingINTELIiEv8ocl_pipePvii(target("spirv.Pipe", 0) %0, ptr addrspace(4) %2, i32 4, i32 4)
ret void
}

declare dso_local spir_func void @_Z29__spirv_ReadPipeBlockingINTELIiEv8ocl_pipePvii(target("spirv.Pipe", 0), ptr addrspace(4), i32, i32)

define spir_func void @boo(target("spirv.Pipe", 1) %p, ptr addrspace(1) %ptr) {
entry:
%p.addr = alloca target("spirv.Pipe", 1), align 8
%ptr.addr = alloca ptr addrspace(1), align 8
store target("spirv.Pipe", 1) %p, target("spirv.Pipe", 1)* %p.addr, align 8
store ptr addrspace(1) %ptr, ptr %ptr.addr, align 8
%0 = load target("spirv.Pipe", 1), target("spirv.Pipe", 1)* %p.addr, align 8
%1 = load ptr addrspace(1), ptr %ptr.addr, align 8
%2 = addrspacecast ptr addrspace(1) %1 to ptr addrspace(4)
call spir_func void @_Z30__spirv_WritePipeBlockingINTELIKiEv8ocl_pipePiii(target("spirv.Pipe", 1) %0, ptr addrspace(4) %2, i32 4, i32 4)
ret void
}

declare dso_local spir_func void @_Z30__spirv_WritePipeBlockingINTELIKiEv8ocl_pipePiii(target("spirv.Pipe", 1), ptr addrspace(4), i32, i32)

define spir_func void @baz(target("spirv.Pipe", 1) %p, ptr addrspace(1) %ptr) {
entry:
%p.addr = alloca target("spirv.Pipe", 1), align 8
%ptr.addr = alloca ptr addrspace(1), align 8
store target("spirv.Pipe", 1) %p, target("spirv.Pipe", 1)* %p.addr, align 8
store ptr addrspace(1) %ptr, ptr %ptr.addr, align 8
%0 = load target("spirv.Pipe", 1), target("spirv.Pipe", 1)* %p.addr, align 8
%1 = load ptr addrspace(1), ptr %ptr.addr, align 8
%2 = addrspacecast ptr addrspace(1) %1 to ptr addrspace(4)
call spir_func void @_Z30__spirv_WritePipeBlockingINTELIKiEv8ocl_pipePvii(target("spirv.Pipe", 1) %0, ptr addrspace(4) %2, i32 4, i32 4)
ret void
}

declare dso_local spir_func void @_Z30__spirv_WritePipeBlockingINTELIKiEv8ocl_pipePvii(target("spirv.Pipe", 1), ptr addrspace(4), i32, i32)

; CHECK-LLVM: declare spir_func void @__read_pipe_2_bl(ptr addrspace(1), ptr addrspace(4), i32, i32)
; CHECK-LLVM: declare spir_func void @__write_pipe_2_bl(ptr addrspace(1), ptr addrspace(4), i32, i32)

define linkonce_odr dso_local spir_func void @WritePipeBLockingi9Pointer(ptr addrspace(4) align 2 dereferenceable(2) %_Data) {
entry:
%_Data.addr = alloca ptr addrspace(4), align 8
%_WPipe = alloca target("spirv.Pipe", 1), align 8
%_Data.addr.ascast = addrspacecast ptr %_Data.addr to ptr addrspace(4)
%_WPipe.ascast = addrspacecast target("spirv.Pipe", 1)* %_WPipe to target("spirv.Pipe", 1) addrspace(4)*
store ptr addrspace(4) %_Data, ptr addrspace(4) %_Data.addr.ascast, align 8
%0 = bitcast target("spirv.Pipe", 1)* %_WPipe to ptr
%1 = load target("spirv.Pipe", 1), target("spirv.Pipe", 1) addrspace(4)* %_WPipe.ascast, align 8
%2 = load ptr addrspace(4), ptr addrspace(4) %_Data.addr.ascast, align 8
call spir_func void @_Z30__spirv_WritePipeBlockingINTELIDU9_Ev8ocl_pipePKT_ii(target("spirv.Pipe", 1) %1, ptr addrspace(4) %2, i32 2, i32 2)
ret void
}

declare dso_local spir_func void @_Z30__spirv_WritePipeBlockingINTELIDU9_Ev8ocl_pipePKT_ii(target("spirv.Pipe", 1), ptr addrspace(4), i32, i32)

10 changes: 5 additions & 5 deletions mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ def SPV_INTEL_fpga_buffer_location : I32EnumAttrCase<"SPV_INTEL_fp
def SPV_INTEL_arbitrary_precision_fixed_point : I32EnumAttrCase<"SPV_INTEL_arbitrary_precision_fixed_point", 4019>;
def SPV_INTEL_usm_storage_classes : I32EnumAttrCase<"SPV_INTEL_usm_storage_classes", 4020>;
def SPV_INTEL_io_pipes : I32EnumAttrCase<"SPV_INTEL_io_pipes", 4021>;
def SPV_INTEL_blocking_pipes : I32EnumAttrCase<"SPV_INTEL_blocking_pipes", 4022>;
def SPV_ALTERA_blocking_pipes : I32EnumAttrCase<"SPV_ALTERA_blocking_pipes", 4022>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kuhar apologies, I haven't realized, that renaming affects existing MLIR flow before merging. Would it cause any issues?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if this affects anything, but in general MLIR changes are better submitted separately as we don't share code paths with the spirv llvm backend

def SPV_INTEL_fpga_reg : I32EnumAttrCase<"SPV_INTEL_fpga_reg", 4023>;
def SPV_INTEL_long_constant_composite : I32EnumAttrCase<"SPV_INTEL_long_constant_composite", 4024>;
def SPV_INTEL_optnone : I32EnumAttrCase<"SPV_INTEL_optnone", 4025>;
Expand Down Expand Up @@ -465,7 +465,7 @@ def SPIRV_ExtensionAttr :
SPV_INTEL_kernel_attributes, SPV_INTEL_fpga_memory_accesses,
SPV_INTEL_fpga_cluster_attributes, SPV_INTEL_loop_fuse,
SPV_INTEL_fpga_buffer_location, SPV_INTEL_arbitrary_precision_fixed_point,
SPV_INTEL_usm_storage_classes, SPV_INTEL_io_pipes, SPV_INTEL_blocking_pipes,
SPV_INTEL_usm_storage_classes, SPV_INTEL_io_pipes, SPV_ALTERA_blocking_pipes,
SPV_INTEL_fpga_reg, SPV_INTEL_long_constant_composite, SPV_INTEL_optnone,
SPV_INTEL_debug_module, SPV_INTEL_fp_fast_math_mode,
SPV_INTEL_memory_access_aliasing, SPV_INTEL_split_barrier,
Expand Down Expand Up @@ -807,9 +807,9 @@ def SPIRV_C_IOPipesINTEL : I32EnumAttrCase<"IOPip
Extension<[SPV_INTEL_io_pipes]>
];
}
def SPIRV_C_BlockingPipesINTEL : I32EnumAttrCase<"BlockingPipesINTEL", 5945> {
def SPIRV_C_BlockingPipesALTERA : I32EnumAttrCase<"BlockingPipesALTERA", 5945> {
list<Availability> availability = [
Extension<[SPV_INTEL_blocking_pipes]>
Extension<[SPV_ALTERA_blocking_pipes]>
];
}
def SPIRV_C_FPGARegINTEL : I32EnumAttrCase<"FPGARegINTEL", 5948> {
Expand Down Expand Up @@ -1519,7 +1519,7 @@ def SPIRV_CapabilityAttr :
SPIRV_C_FPGAMemoryAccessesINTEL, SPIRV_C_FPGAClusterAttributesINTEL,
SPIRV_C_LoopFuseINTEL, SPIRV_C_MemoryAccessAliasingINTEL,
SPIRV_C_FPGABufferLocationINTEL, SPIRV_C_ArbitraryPrecisionFixedPointINTEL,
SPIRV_C_USMStorageClassesINTEL, SPIRV_C_IOPipesINTEL, SPIRV_C_BlockingPipesINTEL,
SPIRV_C_USMStorageClassesINTEL, SPIRV_C_IOPipesINTEL, SPIRV_C_BlockingPipesALTERA,
SPIRV_C_FPGARegINTEL, SPIRV_C_DotProductInputAll,
SPIRV_C_DotProductInput4x8BitPacked, SPIRV_C_DotProduct, SPIRV_C_RayCullMaskKHR,
SPIRV_C_CooperativeMatrixKHR, SPIRV_C_ReplicatedCompositesEXT,
Expand Down