Skip to content

Commit b1b2013

Browse files
committed
--Added support for the extension SPV_INTEL_blocking_pipes
--Added test file for the extension SPV_INTEL_blocking_pipes
1 parent 78408fd commit b1b2013

File tree

7 files changed

+198
-2
lines changed

7 files changed

+198
-2
lines changed

llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,8 @@ static bool buildAtomicStoreInst(const SPIRV::IncomingCall *Call,
701701
MachineIRBuilder &MIRBuilder,
702702
SPIRVGlobalRegistry *GR) {
703703
if (Call->isSpirvOp())
704-
return buildOpFromWrapper(MIRBuilder, SPIRV::OpAtomicStore, Call, Register(0));
704+
return buildOpFromWrapper(MIRBuilder, SPIRV::OpAtomicStore, Call,
705+
Register(0));
705706

706707
Register ScopeRegister =
707708
buildConstantIntReg32(SPIRV::Scope::Device, MIRBuilder, GR);
@@ -2255,6 +2256,64 @@ static bool generateExtendedBitOpsInst(const SPIRV::IncomingCall *Call,
22552256
return buildExtendedBitOpsInst(Call, Opcode, MIRBuilder, GR);
22562257
}
22572258

2259+
static bool generateBlockingPipesInst(const SPIRV::IncomingCall *Call,
2260+
MachineIRBuilder &MIRBuilder,
2261+
SPIRVGlobalRegistry *GR) {
2262+
// Lookup the instruction opcode in the TableGen records.
2263+
const SPIRV::DemangledBuiltin *Builtin = Call->Builtin;
2264+
unsigned Opcode =
2265+
SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;
2266+
2267+
if (Call->Arguments.size() < 4) {
2268+
llvm::errs() << "Not enough operands for pipe instruction\n";
2269+
return false;
2270+
}
2271+
2272+
// Retrieve Packet Size and Packet Alignment.
2273+
// Here we assume that these operands are immediate constants.
2274+
MachineRegisterInfo *MRI = MIRBuilder.getMRI();
2275+
Register packet = Call->Arguments[2];
2276+
Register packetAlignment = Call->Arguments[3];
2277+
2278+
// Get definitions
2279+
MachineInstr *PacketDefMI = MRI->getUniqueVRegDef(packet);
2280+
MachineInstr *AlignDefMI = MRI->getUniqueVRegDef(packetAlignment);
2281+
2282+
// Get types
2283+
LLT PacketType = MRI->getType(PacketDefMI->getOperand(0).getReg());
2284+
LLT AlignType = MRI->getType(AlignDefMI->getOperand(0).getReg());
2285+
2286+
// Validate types
2287+
if (!PacketType.isScalar() || PacketType.getSizeInBits() != 32) {
2288+
llvm::report_fatal_error("Packet Size must be a 32-bit integer scalar!");
2289+
}
2290+
2291+
if (!AlignType.isScalar() || AlignType.getSizeInBits() != 32) {
2292+
llvm::report_fatal_error(
2293+
"Packet Alignment must be a 32-bit integer scalar!");
2294+
}
2295+
2296+
// Get constant values
2297+
const uint32_t PacketSize = getConstFromIntrinsic(packet, MRI);
2298+
const uint32_t PacketAlignment = getConstFromIntrinsic(packetAlignment, MRI);
2299+
2300+
// 1 <= PacketAlignment <= PacketSize
2301+
// PacketSize must be evenly divisible by PacketAlignment.
2302+
if (PacketAlignment < 1 || PacketAlignment > PacketSize ||
2303+
(PacketSize % PacketAlignment != 0)) {
2304+
llvm::errs() << "Invalid packet size and alignment: "
2305+
<< "PacketSize = " << PacketSize
2306+
<< ", PacketAlignment = " << PacketAlignment << "\n";
2307+
return false;
2308+
}
2309+
2310+
auto MIB = MIRBuilder.buildInstr(Opcode);
2311+
2312+
for (unsigned i = 0; i < Call->Arguments.size(); ++i)
2313+
MIB.addUse(Call->Arguments[i]);
2314+
return true;
2315+
}
2316+
22582317
static bool generateBindlessImageINTELInst(const SPIRV::IncomingCall *Call,
22592318
MachineIRBuilder &MIRBuilder,
22602319
SPIRVGlobalRegistry *GR) {
@@ -2847,6 +2906,8 @@ std::optional<bool> lowerBuiltin(const StringRef DemangledCall,
28472906
return generateExtendedBitOpsInst(Call.get(), MIRBuilder, GR);
28482907
case SPIRV::BindlessINTEL:
28492908
return generateBindlessImageINTELInst(Call.get(), MIRBuilder, GR);
2909+
case SPIRV::BlockingPipes:
2910+
return generateBlockingPipesInst(Call.get(), MIRBuilder, GR);
28502911
}
28512912
return false;
28522913
}

llvm/lib/Target/SPIRV/SPIRVBuiltins.td

Lines changed: 5 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 BlockingPipes : BuiltinGroup;
7071

7172
//===----------------------------------------------------------------------===//
7273
// Class defining a demangled builtin record. The information in the record
@@ -1128,6 +1129,10 @@ defm : DemangledNativeBuiltin<"clock_read_hilo_device", OpenCL_std, KernelClock,
11281129
defm : DemangledNativeBuiltin<"clock_read_hilo_work_group", OpenCL_std, KernelClock, 0, 0, OpReadClockKHR>;
11291130
defm : DemangledNativeBuiltin<"clock_read_hilo_sub_group", OpenCL_std, KernelClock, 0, 0, OpReadClockKHR>;
11301131

1132+
//SPV_INTEL_blocking_pipes
1133+
defm : DemangledNativeBuiltin<"__spirv_WritePipeBlockingINTEL", OpenCL_std, BlockingPipes, 0, 0, OpWritePipeBlockingINTEL>;
1134+
defm : DemangledNativeBuiltin<"__spirv_ReadPipeBlockingINTEL", OpenCL_std, BlockingPipes, 0, 0, OpReadPipeBlockingINTEL>;
1135+
11311136
//===----------------------------------------------------------------------===//
11321137
// Class defining an atomic instruction on floating-point numbers.
11331138
//

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_blocking_pipes",
97+
SPIRV::Extension::Extension::SPV_INTEL_blocking_pipes}};
9698

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

llvm/lib/Target/SPIRV/SPIRVInstrInfo.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -956,3 +956,9 @@ def OpAliasScopeDeclINTEL: Op<5912, (outs ID:$res), (ins ID:$AliasDomain, variab
956956
"$res = OpAliasScopeDeclINTEL $AliasDomain">;
957957
def OpAliasScopeListDeclINTEL: Op<5913, (outs ID:$res), (ins variable_ops),
958958
"$res = OpAliasScopeListDeclINTEL">;
959+
960+
//SPV_INTEL_blocking_pipes
961+
def OpReadPipeBlockingINTEL :Op<5946, (outs), (ins ID:$pipe, ID:$pointer, ID:$packetSize, ID:$packetAlignment),
962+
"OpReadPipeBlockingINTEL $pipe $pointer $packetSize $packetAlignment">;
963+
def OpWritePipeBlockingINTEL :Op<5946, (outs), (ins ID:$pipe, ID:$pointer, ID:$packetSize, ID:$packetAlignment),
964+
"OpWritePipeBlockingINTEL $pipe $pointer $packetSize $packetAlignment">;

llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1690,6 +1690,13 @@ void addInstrRequirements(const MachineInstr &MI,
16901690
Reqs.addCapability(
16911691
SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
16921692
break;
1693+
case SPIRV::OpReadPipeBlockingINTEL:
1694+
case SPIRV::OpWritePipeBlockingINTEL:
1695+
if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_blocking_pipes)) {
1696+
Reqs.addExtension(SPIRV::Extension::SPV_INTEL_blocking_pipes);
1697+
Reqs.addCapability(SPIRV::Capability::BlockingPipesINTEL);
1698+
}
1699+
break;
16931700
case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:
16941701
if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
16951702
report_fatal_error("OpCooperativeMatrixGetElementCoordINTEL requires the "

llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,7 @@ defm LongCompositesINTEL : CapabilityOperand<6089, 0, 0, [SPV_INTEL_long_composi
513513
defm BindlessImagesINTEL : CapabilityOperand<6528, 0, 0, [SPV_INTEL_bindless_images], []>;
514514
defm MemoryAccessAliasingINTEL : CapabilityOperand<5910, 0, 0, [SPV_INTEL_memory_access_aliasing], []>;
515515
defm FPMaxErrorINTEL : CapabilityOperand<6169, 0, 0, [SPV_INTEL_fp_max_error], []>;
516+
defm BlockingPipesINTEL : CapabilityOperand<5945, 0, 0, [SPV_INTEL_blocking_pipes], []>;
516517

517518
//===----------------------------------------------------------------------===//
518519
// Multiclass used to define SourceLanguage enum values and at the same time
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_blocking_pipes %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV
2+
; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_blocking_pipes %s -o - -filetype=obj | spirv-val %}
3+
4+
%opencl.pipe_ro_t = type opaque
5+
%opencl.pipe_wo_t = type opaque
6+
7+
; CHECK-SPIRV: OpCapability BlockingPipesINTEL
8+
; CHECK-SPIRV: OpExtension "SPV_INTEL_blocking_pipes"
9+
; CHECK-SPIRV: %[[PipeRTy:[0-9]+]] = OpTypePipe ReadOnly
10+
; CHECK-SPIRV: %[[PipeWTy:[0-9]+]] = OpTypePipe WriteOnly
11+
; CHECK-SPIRV: %[[PipeR1:[0-9]+]] = OpLoad %[[PipeRTy]] %[[#]] Aligned 8
12+
; CHECK-SPIRV: OpReadPipeBlockingINTEL %[[PipeR1]] %[[#]] %[[#]] %[[#]]
13+
; CHECK-SPIRV: %[[PipeR2:[0-9]+]] = OpLoad %[[PipeRTy]] %[[#]] Aligned 8
14+
; CHECK-SPIRV: OpReadPipeBlockingINTEL %[[PipeR2]] %[[#]] %[[#]] %[[#]]
15+
; CHECK-SPIRV: %[[PipeW1:[0-9]+]] = OpLoad %[[PipeWTy]] %[[#]] Aligned 8
16+
; CHECK-SPIRV: OpWritePipeBlockingINTEL %[[PipeW1]] %[[#]] %[[#]] %[[#]]
17+
; CHECK-SPIRV: %[[PipeW2:[0-9]+]] = OpLoad %[[PipeWTy]] %[[#]] Aligned 8
18+
; CHECK-SPIRV: OpWritePipeBlockingINTEL %[[PipeW2]] %[[#]] %[[#]] %[[#]]
19+
20+
21+
; Function Attrs: convergent noinline nounwind optnone
22+
define spir_func void @foo(target("spirv.Pipe", 0) %p, ptr addrspace(1) %ptr) #0 {
23+
entry:
24+
%p.addr = alloca target("spirv.Pipe", 0), align 8
25+
%ptr.addr = alloca ptr addrspace(1), align 8
26+
store target("spirv.Pipe", 0) %p, target("spirv.Pipe", 0)* %p.addr, align 8
27+
store ptr addrspace(1) %ptr, ptr %ptr.addr, align 8
28+
%0 = load target("spirv.Pipe", 0), target("spirv.Pipe", 0)* %p.addr, align 8
29+
%1 = load ptr addrspace(1), ptr %ptr.addr, align 8
30+
%2 = addrspacecast ptr addrspace(1) %1 to ptr addrspace(4)
31+
call spir_func void @_Z29__spirv_ReadPipeBlockingINTELIiEv8ocl_pipePiii(target("spirv.Pipe", 0) %0, ptr addrspace(4) %2, i32 4, i32 4)
32+
ret void
33+
}
34+
35+
declare dso_local spir_func void @_Z29__spirv_ReadPipeBlockingINTELIiEv8ocl_pipePiii(target("spirv.Pipe", 0), ptr addrspace(4), i32, i32)
36+
37+
; Function Attrs: convergent noinline nounwind optnone
38+
define spir_func void @bar(target("spirv.Pipe", 0) %p, ptr addrspace(1) %ptr) #0 {
39+
entry:
40+
%p.addr = alloca target("spirv.Pipe", 0), align 8
41+
%ptr.addr = alloca ptr addrspace(1), align 8
42+
store target("spirv.Pipe", 0) %p, target("spirv.Pipe", 0)* %p.addr, align 8
43+
store ptr addrspace(1) %ptr, ptr %ptr.addr, align 8
44+
%0 = load target("spirv.Pipe", 0), target("spirv.Pipe", 0)* %p.addr, align 8
45+
%1 = load ptr addrspace(1), ptr %ptr.addr, align 8
46+
%2 = addrspacecast ptr addrspace(1) %1 to ptr addrspace(4)
47+
call spir_func void @_Z29__spirv_ReadPipeBlockingINTELIiEv8ocl_pipePvii(target("spirv.Pipe", 0) %0, ptr addrspace(4) %2, i32 4, i32 4)
48+
ret void
49+
}
50+
51+
declare dso_local spir_func void @_Z29__spirv_ReadPipeBlockingINTELIiEv8ocl_pipePvii(target("spirv.Pipe", 0), ptr addrspace(4), i32, i32)
52+
53+
; Function Attrs: convergent noinline nounwind optnone
54+
define spir_func void @boo(target("spirv.Pipe", 1) %p, ptr addrspace(1) %ptr) #0 {
55+
entry:
56+
%p.addr = alloca target("spirv.Pipe", 1), align 8
57+
%ptr.addr = alloca ptr addrspace(1), align 8
58+
store target("spirv.Pipe", 1) %p, target("spirv.Pipe", 1)* %p.addr, align 8
59+
store ptr addrspace(1) %ptr, ptr %ptr.addr, align 8
60+
%0 = load target("spirv.Pipe", 1), target("spirv.Pipe", 1)* %p.addr, align 8
61+
%1 = load ptr addrspace(1), ptr %ptr.addr, align 8
62+
%2 = addrspacecast ptr addrspace(1) %1 to ptr addrspace(4)
63+
call spir_func void @_Z30__spirv_WritePipeBlockingINTELIKiEv8ocl_pipePiii(target("spirv.Pipe", 1) %0, ptr addrspace(4) %2, i32 4, i32 4)
64+
ret void
65+
}
66+
67+
declare dso_local spir_func void @_Z30__spirv_WritePipeBlockingINTELIKiEv8ocl_pipePiii(target("spirv.Pipe", 1), ptr addrspace(4), i32, i32)
68+
69+
; Function Attrs: convergent noinline nounwind optnone
70+
define spir_func void @baz(target("spirv.Pipe", 1) %p, ptr addrspace(1) %ptr) #0 {
71+
entry:
72+
%p.addr = alloca target("spirv.Pipe", 1), align 8
73+
%ptr.addr = alloca ptr addrspace(1), align 8
74+
store target("spirv.Pipe", 1) %p, target("spirv.Pipe", 1)* %p.addr, align 8
75+
store ptr addrspace(1) %ptr, ptr %ptr.addr, align 8
76+
%0 = load target("spirv.Pipe", 1), target("spirv.Pipe", 1)* %p.addr, align 8
77+
%1 = load ptr addrspace(1), ptr %ptr.addr, align 8
78+
%2 = addrspacecast ptr addrspace(1) %1 to ptr addrspace(4)
79+
call spir_func void @_Z30__spirv_WritePipeBlockingINTELIKiEv8ocl_pipePvii(target("spirv.Pipe", 1) %0, ptr addrspace(4) %2, i32 4, i32 4)
80+
ret void
81+
}
82+
83+
declare dso_local spir_func void @_Z30__spirv_WritePipeBlockingINTELIKiEv8ocl_pipePvii(target("spirv.Pipe", 1), ptr addrspace(4), i32, i32)
84+
85+
; CHECK-LLVM: declare spir_func void @__read_pipe_2_bl(ptr addrspace(1), ptr addrspace(4), i32, i32)
86+
; CHECK-LLVM: declare spir_func void @__write_pipe_2_bl(ptr addrspace(1), ptr addrspace(4), i32, i32)
87+
88+
; Function Attrs: convergent mustprogress norecurse nounwind
89+
define linkonce_odr dso_local spir_func void @WritePipeBLockingi9Pointer(ptr addrspace(4) align 2 dereferenceable(2) %_Data) {
90+
entry:
91+
%_Data.addr = alloca ptr addrspace(4), align 8
92+
%_WPipe = alloca target("spirv.Pipe", 1), align 8
93+
%_Data.addr.ascast = addrspacecast ptr %_Data.addr to ptr addrspace(4)
94+
%_WPipe.ascast = addrspacecast target("spirv.Pipe", 1)* %_WPipe to target("spirv.Pipe", 1) addrspace(4)*
95+
store ptr addrspace(4) %_Data, ptr addrspace(4) %_Data.addr.ascast, align 8
96+
%0 = bitcast target("spirv.Pipe", 1)* %_WPipe to ptr
97+
%1 = load target("spirv.Pipe", 1), target("spirv.Pipe", 1) addrspace(4)* %_WPipe.ascast, align 8
98+
%2 = load ptr addrspace(4), ptr addrspace(4) %_Data.addr.ascast, align 8
99+
call spir_func void @_Z30__spirv_WritePipeBlockingINTELIDU9_Ev8ocl_pipePKT_ii(target("spirv.Pipe", 1) %1, ptr addrspace(4) %2, i32 2, i32 2)
100+
ret void
101+
}
102+
103+
declare dso_local spir_func void @_Z30__spirv_WritePipeBlockingINTELIDU9_Ev8ocl_pipePKT_ii(target("spirv.Pipe", 1), ptr addrspace(4), i32, i32)
104+
105+
attributes #0 = { convergent noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "denorms-are-zero"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
106+
107+
!llvm.module.flags = !{!0}
108+
!opencl.ocl.version = !{!1}
109+
!opencl.spir.version = !{!1}
110+
!llvm.ident = !{!2}
111+
112+
!0 = !{i32 1, !"wchar_size", i32 4}
113+
!1 = !{i32 2, i32 0}
114+
!2 = !{!"clang version 9.0.0 (https://github.com/MrSidims/llvm.git c627b787284c5bcc917ea9742908baa1b856e176)"}

0 commit comments

Comments
 (0)