Skip to content

Commit 823985f

Browse files
committed
Implement host pipe unique name generation and mapping calls
1 parent e9c769e commit 823985f

File tree

12 files changed

+239
-7
lines changed

12 files changed

+239
-7
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1554,6 +1554,15 @@ def SYCLDeviceGlobal: InheritableAttr {
15541554
let SimpleHandler = 1;
15551555
}
15561556

1557+
def SYCLHostPipe: InheritableAttr {
1558+
let Spellings = [CXX11<"__sycl_detail__", "host_pipe">];
1559+
let Subjects = SubjectList<[CXXRecord], ErrorDiag>;
1560+
let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost];
1561+
// Only used internally by SYCL implementation
1562+
let Documentation = [SYCLHostPipeAttrDocs];
1563+
let SimpleHandler = 1;
1564+
}
1565+
15571566
def SYCLGlobalVariableAllowed : InheritableAttr {
15581567
let Spellings = [CXX11<"__sycl_detail__", "global_variable_allowed">];
15591568
let Subjects = SubjectList<[CXXRecord], ErrorDiag>;

clang/include/clang/Basic/AttrDocs.td

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3124,6 +3124,26 @@ so we have this attribute in sycl_detail namespace.
31243124
}];
31253125
}
31263126

3127+
def SYCLHostPipeAttrDocs : Documentation {
3128+
let Category = DocCatType;
3129+
let Heading = "__sycl_detail__::host_pipe";
3130+
let Content = [{
3131+
This attribute is part of support for SYCL host_pipe feature.
3132+
Global or static variables of type decorated with this attribute have
3133+
`sycl-unique-id`, an LLVM IR attribute, added to the definition of each such
3134+
variable, which provides a unique string identifier using
3135+
__builtin_sycl_unique_stable_id.
3136+
We do not intend to support this as a general attribute that user code can use,
3137+
so we have this attribute in sycl_detail namespace.
3138+
3139+
.. code-block:: c++
3140+
struct
3141+
[[__sycl_detail__::host_pipe]] __pipeType {}
3142+
3143+
__pipeType __pipe;
3144+
}];
3145+
}
3146+
31273147
def SYCLGlobalVariableAllowedAttrDocs : Documentation {
31283148
let Category = DocCatType;
31293149
let Heading = "__sycl_detail__::global_variable_allowed";

clang/include/clang/Sema/Sema.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,13 @@ class SYCLIntegrationHeader {
371371
NeedToEmitDeviceGlobalRegistration = true;
372372
}
373373

374+
/// Signals that emission of __sycl_host_pipe_registration type and
375+
/// declaration of variable __sycl_host_pipe_registrar of this type in
376+
/// integration header is required.
377+
void addHostPipeRegistration() {
378+
NeedToEmitHostPipeRegistration = true;
379+
}
380+
374381
private:
375382
// Kernel actual parameter descriptor.
376383
struct KernelParamDesc {
@@ -454,6 +461,10 @@ class SYCLIntegrationHeader {
454461
/// Keeps track of whether declaration of __sycl_device_global_registration
455462
/// type and __sycl_device_global_registrar variable are required to emit.
456463
bool NeedToEmitDeviceGlobalRegistration = false;
464+
465+
/// Keeps track of whether declaration of __sycl_host_pipe_registration
466+
/// type and __sycl_host_pipe_registrar variable are required to emit.
467+
bool NeedToEmitHostPipeRegistration = false;
457468
};
458469

459470
class SYCLIntegrationFooter {

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5512,9 +5512,10 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
55125512
// type.
55135513
if (RD && RD->hasAttr<SYCLAddIRAttributesGlobalVariableAttr>())
55145514
AddGlobalSYCLIRAttributes(GV, RD);
5515-
// If VarDecl has a type decorated with SYCL device_global attribute, emit
5516-
// IR attribute 'sycl-unique-id'.
5517-
if (RD && RD->hasAttr<SYCLDeviceGlobalAttr>())
5515+
// If VarDecl has a type decorated with SYCL device_global attribute or
5516+
// SYCL host_pipe attribute, emit IR attribute 'sycl-unique-id'.
5517+
if (RD && (RD->hasAttr<SYCLDeviceGlobalAttr>() ||
5518+
RD->hasAttr<SYCLHostPipeAttr>()))
55185519
addSYCLUniqueID(GV, D, Context);
55195520
}
55205521

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9702,6 +9702,9 @@ void SYCLPostLink::ConstructJob(Compilation &C, const JobAction &JA,
97029702
// Process device-globals.
97039703
addArgs(CmdArgs, TCArgs, {"-device-globals"});
97049704

9705+
// Process host pipes.
9706+
addArgs(CmdArgs, TCArgs, {"-host-pipes"});
9707+
97059708
// Make ESIMD accessors use stateless memory accesses.
97069709
if (TCArgs.hasFlag(options::OPT_fsycl_esimd_force_stateless_mem,
97079710
options::OPT_fno_sycl_esimd_force_stateless_mem, false))

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5169,6 +5169,24 @@ void SYCLIntegrationHeader::emit(raw_ostream &O) {
51695169
O << "\n";
51705170
}
51715171

5172+
// Generate declaration of variable of type __sycl_host_pipe_registration
5173+
// whose sole purpose is to run its constructor before the application's
5174+
// main() function.
5175+
if (NeedToEmitHostPipeRegistration) {
5176+
O << "namespace {\n";
5177+
5178+
O << "class __sycl_host_pipe_registration {\n";
5179+
O << "public:\n";
5180+
O << " __sycl_host_pipe_registration() noexcept;\n";
5181+
O << "};\n";
5182+
O << "__sycl_host_pipe_registration __sycl_host_pipe_registrar;\n";
5183+
5184+
O << "} // namespace\n";
5185+
5186+
O << "\n";
5187+
}
5188+
5189+
51725190
O << "// names of all kernels defined in the corresponding source\n";
51735191
O << "static constexpr\n";
51745192
O << "const char* const kernel_names[] = {\n";
@@ -5359,6 +5377,7 @@ void SYCLIntegrationFooter::addVarDecl(const VarDecl *VD) {
53595377
return;
53605378
// Step 1: ensure that this is of the correct type template specialization.
53615379
if (!isSyclType(VD->getType(), SYCLTypeAttr::specialization_id) &&
5380+
!S.isTypeDecoratedWithDeclAttribute<SYCLHostPipeAttr>(VD->getType()) &&
53625381
!S.isTypeDecoratedWithDeclAttribute<SYCLDeviceGlobalAttr>(
53635382
VD->getType())) {
53645383
// Handle the case where this could be a deduced type, such as a deduction
@@ -5528,20 +5547,25 @@ bool SYCLIntegrationFooter::emit(raw_ostream &OS) {
55285547
llvm::SmallSet<const VarDecl *, 8> Visited;
55295548
bool EmittedFirstSpecConstant = false;
55305549
bool DeviceGlobalsEmitted = false;
5550+
bool HostPipesEmitted = false;
55315551

55325552
// Used to uniquely name the 'shim's as we generate the names in each
55335553
// anonymous namespace.
55345554
unsigned ShimCounter = 0;
55355555

55365556
std::string DeviceGlobalsBuf;
55375557
llvm::raw_string_ostream DeviceGlobOS(DeviceGlobalsBuf);
5558+
std::string HostPipesBuf;
5559+
llvm::raw_string_ostream HostPipesOS(HostPipesBuf);
55385560
for (const VarDecl *VD : GlobalVars) {
55395561
VD = VD->getCanonicalDecl();
55405562

5541-
// Skip if this isn't a SpecIdType or DeviceGlobal. This can happen if it
5542-
// was a deduced type.
5563+
// Skip if this isn't a SpecIdType, DeviceGlobal, or HostPipe. This
5564+
// can happen if it was a deduced type.
55435565
if (!isSyclType(VD->getType(), SYCLTypeAttr::specialization_id) &&
55445566
!S.isTypeDecoratedWithDeclAttribute<SYCLDeviceGlobalAttr>(
5567+
VD->getType()) &&
5568+
!S.isTypeDecoratedWithDeclAttribute<SYCLHostPipeAttr>(
55455569
VD->getType()))
55465570
continue;
55475571

@@ -5551,7 +5575,7 @@ bool SYCLIntegrationFooter::emit(raw_ostream &OS) {
55515575

55525576
// We only want to emit the #includes if we have a variable that needs
55535577
// them, so emit this one on the first time through the loop.
5554-
if (!EmittedFirstSpecConstant && !DeviceGlobalsEmitted)
5578+
if (!EmittedFirstSpecConstant && !DeviceGlobalsEmitted && !HostPipesEmitted)
55555579
OS << "#include <sycl/detail/defines_elementary.hpp>\n";
55565580

55575581
Visited.insert(VD);
@@ -5571,6 +5595,21 @@ bool SYCLIntegrationFooter::emit(raw_ostream &OS) {
55715595
DeviceGlobOS << SYCLUniqueStableIdExpr::ComputeName(S.getASTContext(),
55725596
VD);
55735597
DeviceGlobOS << "\");\n";
5598+
} else if (S.isTypeDecoratedWithDeclAttribute<SYCLHostPipeAttr>(
5599+
VD->getType())) {
5600+
HostPipesEmitted = true;
5601+
HostPipesOS << "host_pipe_map::add(";
5602+
HostPipesOS << "(void *)&";
5603+
if (VD->isInAnonymousNamespace()) {
5604+
HostPipesOS << TopShim;
5605+
} else {
5606+
HostPipesOS << "::";
5607+
VD->getNameForDiagnostic(HostPipesOS, Policy, true);
5608+
}
5609+
HostPipesOS << ", \"";
5610+
HostPipesOS << SYCLUniqueStableIdExpr::ComputeName(S.getASTContext(),
5611+
VD);
5612+
HostPipesOS << "\");\n";
55745613
} else {
55755614
EmittedFirstSpecConstant = true;
55765615
OS << "namespace sycl {\n";
@@ -5614,5 +5653,21 @@ bool SYCLIntegrationFooter::emit(raw_ostream &OS) {
56145653

56155654
S.getSyclIntegrationHeader().addDeviceGlobalRegistration();
56165655
}
5656+
5657+
if (HostPipesEmitted) {
5658+
OS << "#include <sycl/detail/host_pipe_map.hpp>\n";
5659+
HostPipesOS.flush();
5660+
OS << "namespace sycl::detail {\n";
5661+
OS << "namespace {\n";
5662+
OS << "__sycl_host_pipe_registration::__sycl_host_pipe_"
5663+
"registration() noexcept {\n";
5664+
OS << HostPipesBuf;
5665+
OS << "}\n";
5666+
OS << "} // namespace (unnamed)\n";
5667+
OS << "} // namespace sycl::detail\n";
5668+
5669+
S.getSyclIntegrationHeader().addHostPipeRegistration();
5670+
}
5671+
56175672
return true;
56185673
}

llvm/lib/SYCLLowerIR/CompileTimePropertiesPass.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,13 @@ PreservedAnalyses CompileTimePropertiesPass::run(Module &M,
266266
HostAccessDecorValue, VarName));
267267
}
268268

269+
if (isHostPipeVariable(GV)) {
270+
auto VarName = getGlobalVariableUniqueId(GV);
271+
MDOps.push_back(buildSpirvDecorMetadata(Ctx, SPIRV_HOST_ACCESS_DECOR,
272+
SPIRV_HOST_ACCESS_DEFAULT_VALUE,
273+
VarName));
274+
}
275+
269276
// Add the generated metadata to the variable
270277
if (!MDOps.empty()) {
271278
GV.addMetadata(MDKindID, *MDNode::get(Ctx, MDOps));
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
; RUN: sycl-post-link --host-pipes -S %s -o %t.files.table
2+
; RUN: FileCheck %s -input-file=%t.files_0.ll --check-prefix CHECK-IR
3+
; RUN: sycl-post-link --host-pipes --ir-output-only %s -S -o - | FileCheck %s --check-prefix CHECK-IR
4+
5+
; This test is intended to check that CompileTimePropertiesPass adds all the required
6+
; metadata nodes to host pipe vars decorated with the "sycl-host-pipe" attribute
7+
8+
source_filename = "basic.cpp"
9+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"
10+
target triple = "spir64_fpga-unknown-unknown"
11+
12+
%struct.BasicKernel = type { i8 }
13+
14+
$_ZN4sycl3_V13ext5intel12experimental9host_pipeI9D2HPipeIDiNS1_6oneapi12experimental10propertiesISt5tupleIJEEEEE6__pipeE = comdat any
15+
16+
@_ZN4sycl3_V13ext5intel12experimental9host_pipeI9D2HPipeIDiNS1_6oneapi12experimental10propertiesISt5tupleIJEEEEE6__pipeE = linkonce_odr dso_local addrspace(1) constant %struct.BasicKernel zeroinitializer, comdat, align 1 #0
17+
; CHECK-IR: @_ZN4sycl3_V13ext5intel12experimental9host_pipeI9D2HPipeIDiNS1_6oneapi12experimental10propertiesISt5tupleIJEEEEE6__pipeE = linkonce_odr dso_local addrspace(1) constant %struct.BasicKernel zeroinitializer, comdat, align 1, !spirv.Decorations ![[#MN0:]]
18+
19+
attributes #0 = { "sycl-host-pipe" "sycl-unique-id"="_ZN4sycl3_V13ext5intel12experimental9host_pipeI9H2DPipeIDiNS1_6oneapi12experimental10propertiesISt5tupleIJEEEEE6__pipeE" }
20+
21+
; Ensure that the generated metadata nodes are correct
22+
; CHECK-IR-DAG: ![[#MN0]] = !{![[#MN1:]]}
23+
; CHECK-IR-DAG: ![[#MN1]] = !{i32 6147, i32 2, !"_ZN4sycl3_V13ext5intel12experimental9host_pipeI9H2DPipeIDiNS1_6oneapi12experimental10propertiesISt5tupleIJEEEEE6__pipeE"}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//===------------- HostPipes.cpp - SYCL Host Pipes Pass -------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
// See comments in the header.
9+
//===----------------------------------------------------------------------===//
10+
11+
#include "HostPipes.h"
12+
#include "CompileTimePropertiesPass.h"
13+
14+
#include "llvm/ADT/STLExtras.h"
15+
#include "llvm/ADT/StringRef.h"
16+
#include "llvm/IR/Module.h"
17+
18+
#include <cassert>
19+
20+
using namespace llvm;
21+
22+
namespace {
23+
24+
constexpr StringRef SYCL_HOST_PIPE_ATTR = "sycl-host-pipe";
25+
26+
} // anonymous namespace
27+
28+
namespace llvm {
29+
30+
/// Return \c true if the variable @GV is a device global variable.
31+
///
32+
/// The function checks whether the variable has the LLVM IR attribute \c
33+
/// sycl-host-pipe.
34+
/// @param GV [in] A variable to test.
35+
///
36+
/// @return \c true if the variable is a host pipe variable, \c false
37+
/// otherwise.
38+
bool isHostPipeVariable(const GlobalVariable &GV) {
39+
return GV.hasAttribute(SYCL_HOST_PIPE_ATTR);
40+
}
41+
42+
} // namespace llvm

llvm/tools/sycl-post-link/HostPipes.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//===------- HostPipes.h - get required into about SYCL Host Pipes --------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// The file contains a number of functions to extract corresponding attributes
10+
// of host pipe variables and save them as a property set for the runtime.
11+
//===----------------------------------------------------------------------===//
12+
13+
#pragma once
14+
15+
#include "llvm/ADT/MapVector.h"
16+
17+
#include <cstdint>
18+
#include <vector>
19+
20+
namespace llvm {
21+
22+
class GlobalVariable;
23+
class Module;
24+
class StringRef;
25+
26+
/// Return \c true if the variable @GV is a host pipe variable.
27+
///
28+
/// @param GV [in] A variable to test.
29+
///
30+
/// @return \c true if the variable is a host pipe variable, \c false
31+
/// otherwise.
32+
bool isHostPipeVariable(const GlobalVariable &GV);
33+
34+
} // end namespace llvm

llvm/tools/sycl-post-link/sycl-post-link.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,11 @@ cl::opt<bool> DeviceGlobals{
207207
cl::desc("Lower and generate information about device global variables"),
208208
cl::cat(PostLinkCat)};
209209

210+
cl::opt<bool> HostPipes{
211+
"host-pipes",
212+
cl::desc("Lower and generate information about host pipe variables"),
213+
cl::cat(PostLinkCat)};
214+
210215
struct GlobalBinImageProps {
211216
bool EmitKernelParamInfo;
212217
bool EmitProgramMetadata;
@@ -970,10 +975,11 @@ int main(int argc, char **argv) {
970975
bool DoProgMetadata = EmitProgramMetadata.getNumOccurrences() > 0;
971976
bool DoExportedSyms = EmitExportedSymbols.getNumOccurrences() > 0;
972977
bool DoDeviceGlobals = DeviceGlobals.getNumOccurrences() > 0;
978+
bool DoHostPipes = HostPipes.getNumOccurrences() > 0;
973979

974980
if (!DoSplit && !DoSpecConst && !DoSymGen && !DoParamInfo &&
975981
!DoProgMetadata && !DoSplitEsimd && !DoExportedSyms && !DoDeviceGlobals &&
976-
!DoLowerEsimd) {
982+
!DoLowerEsimd && !DoHostPipes) {
977983
errs() << "no actions specified; try --help for usage info\n";
978984
return 1;
979985
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//==-------------------- host_pipe_map.hpp -----------------------------==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#pragma once
10+
11+
namespace sycl {
12+
__SYCL_INLINE_VER_NAMESPACE(_V1) {
13+
namespace detail {
14+
namespace host_pipe_map {
15+
16+
__SYCL_EXPORT void add(const void *HostPipePtr, const char *UniqueId);
17+
18+
} // namespace host_pipe_map
19+
} // namespace detail
20+
} // __SYCL_INLINE_VER_NAMESPACE(_V1)
21+
} // namespace sycl

0 commit comments

Comments
 (0)