Skip to content

[SYCL] Add SYCL registered kernel metadata into property sets #16821

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Feb 24, 2025
1 change: 1 addition & 0 deletions llvm/include/llvm/Support/PropertySetIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ class PropertySetRegistry {
static constexpr char SYCL_HOST_PIPES[] = "SYCL/host pipes";
static constexpr char SYCL_VIRTUAL_FUNCTIONS[] = "SYCL/virtual functions";
static constexpr char SYCL_IMPLICIT_LOCAL_ARG[] = "SYCL/implicit local arg";
static constexpr char SYCL_REGISTERED_KERNELS[] = "SYCL/registered kernels";

static constexpr char PROPERTY_REQD_WORK_GROUP_SIZE[] =
"reqd_work_group_size_uint64_t";
Expand Down
15 changes: 15 additions & 0 deletions llvm/lib/SYCLLowerIR/ComputeModuleRuntimeInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,21 @@ PropSetRegTy computeModuleProperties(const Module &M,
}
}

if (const NamedMDNode *MD = M.getNamedMetadata("sycl_registered_kernels")) {
if (MD->getNumOperands() == 1) {
const MDNode *RegisteredKernels = MD->getOperand(0);
for (const MDOperand &Op : RegisteredKernels->operands()) {
const auto *RegisteredKernel = cast<MDNode>(Op);
if (RegisteredKernel->getNumOperands() != 2)
continue;
PropSet.add(
PropSetRegTy::SYCL_REGISTERED_KERNELS,
cast<MDString>(RegisteredKernel->getOperand(0))->getString(),
cast<MDString>(RegisteredKernel->getOperand(1))->getString());
}
}
}

return PropSet;
}
std::string computeModuleSymbolTable(const Module &M,
Expand Down
26 changes: 26 additions & 0 deletions llvm/lib/SYCLLowerIR/ModuleSplitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,31 @@ static bool mustPreserveGV(const GlobalValue &GV) {
return true;
}

void cleanupSYCLRegisteredKernels(Module *M) {
NamedMDNode *MD = M->getNamedMetadata("sycl_registered_kernels");
if (!MD)
return;

if (MD->getNumOperands() == 0)
return;

SmallVector<Metadata *, 8> OperandsToKeep;
MDNode *RegisterdKernels = MD->getOperand(0);
for (const MDOperand &Op : RegisterdKernels->operands()) {
auto RegisteredKernel = cast<MDNode>(Op);
// Ignore metadata nodes with wrong number of operands.
if (RegisteredKernel->getNumOperands() != 2)
continue;

StringRef MangledName =
cast<MDString>(RegisteredKernel->getOperand(1))->getString();
if (M->getFunction(MangledName))
OperandsToKeep.push_back(RegisteredKernel);
}
MD->clearOperands();
MD->addOperand(MDNode::get(M->getContext(), OperandsToKeep));
}

// TODO: try to move all passes (cleanup, spec consts, compile time properties)
// in one place and execute MPM.run() only once.
void ModuleDesc::cleanup() {
Expand Down Expand Up @@ -740,6 +765,7 @@ void ModuleDesc::cleanup() {
// process all nodes in the named metadata and remove nodes which are
// referencing kernels which are not included into submodule.
processSubModuleNamedMetadata(M.get());
cleanupSYCLRegisteredKernels(M.get());
}

bool ModuleDesc::isSpecConstantDefault() const {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
; RUN: sycl-post-link -properties %s -o %t.table
; RUN: FileCheck %s -input-file=%t_0.prop --implicit-check-not="[SYCL/registered kernels]"
!sycl_registered_kernels = !{}
93 changes: 93 additions & 0 deletions llvm/test/tools/sycl-post-link/sycl-registered-kernels.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
; This test checks that the sycl-post-link ouputs registered kernel data
; from !sycl_registered_kernels metadata into the SYCL/registerd_kernels section.

; RUN: sycl-post-link %s -properties -split=auto -o %t.table
; RUN: FileCheck %s -input-file=%t_0.prop --check-prefixes=CHECK-WITH-ASPECT,CHECK \
; RUN: --implicit-check-not=kernel_with_aspects
; RUN: FileCheck %s -input-file=%t_1.prop --check-prefixes=CHECK-NO-ASPECT,CHECK

!sycl_registered_kernels = !{!4}
!4 = !{!5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !16, !17, !18, !19}

; Both splits should contain the registered kernel data.
; CHECK: [SYCL/registered kernels]

; For each entry in !sycl_registered_kernels, an entry
; mapping the registered name to the mangled name is added in the
; [SYCL/registered kernels] if it references a kernel that appears
; in the split. (Although in the prop files, the
; mapped values are base64 encoded, so just using simplifed check
; with a regex.)
; CHECK-NO-ASPECT-NEXT: foo=2|{{[A-Za-z0-9+/]+}}
!5 = !{!"foo", !"_Z17__sycl_kernel_foov"}
define spir_kernel void @_Z17__sycl_kernel_foov() {
ret void
}

; CHECK-NO-ASPECT-NEXT: foo3=2|{{[A-Za-z0-9+/]+}}
!6 = !{!"foo3", !"_Z18__sycl_kernel_ff_4v"}
define spir_kernel void @_Z18__sycl_kernel_ff_4v() {
ret void
}

; CHECK-NO-ASPECT-NEXT: iota=2|{{[A-Za-z0-9+/]+}}
!7 = !{!"iota", !"_Z18__sycl_kernel_iotaiPi"}
define spir_kernel void @_Z18__sycl_kernel_iotaiPi() {
ret void
}

; CHECK-NO-ASPECT-NEXT: inst temp=2|{{[A-Za-z0-9+/]+}}
!8 = !{!"inst temp", !"_Z22__sycl_kernel_tempfoo2IiEvT_"}
define spir_kernel void @_Z22__sycl_kernel_tempfoo2IiEvT_() {
ret void
}

; CHECK-NO-ASPECT-NEXT: def spec=2|{{[A-Za-z0-9+/]+}}
!9 = !{!"def spec", !"_Z22__sycl_kernel_tempfoo2IsEvT_"}
define spir_kernel void @_Z22__sycl_kernel_tempfoo2IsEvT_() {
ret void
}

; CHECK-NO-ASPECT-NEXT: decl temp=2|{{[A-Za-z0-9+/]+}}
!10 = !{!"decl temp", !"_Z21__sycl_kernel_tempfooIiEvT_"}
define spir_kernel void @_Z21__sycl_kernel_tempfooIiEvT_() {
ret void
}

; CHECK-NO-ASPECT-NEXT: decl spec=2|{{[A-Za-z0-9+/]+}}
!11 = !{!"decl spec", !"_Z22__sycl_kernel_tempfoo2IfEvT_"}
define spir_kernel void @_Z22__sycl_kernel_tempfoo2IfEvT_() {
ret void
}

; CHECK-NO-ASPECT-NEXT: nontype=2|{{[A-Za-z0-9+/]+}}
!12 = !{!"nontype", !"_Z22__sycl_kernel_tempfoo3ILi5EEvv"}
define spir_kernel void @_Z22__sycl_kernel_tempfoo3ILi5EEvv() {
ret void
}

; CHECK-NO-ASPECT-NEXT: non-temp=2|{{[A-Za-z0-9+/]+}}
!13 = !{!"decl non-temp", !"_Z17__sycl_kernel_barv"}
define spir_kernel void @_Z17__sycl_kernel_barv() {
ret void
}

!14 = !{!"kernel_with_aspects", !"kernel_with_aspects"}
!15 = !{i32 1}
; CHECK-WITH-ASPECT-NEXT: kernel_with_aspects=2|{{[A-Za-z0-9+/]+}}
define spir_kernel void @kernel_with_aspects() !sycl_used_aspects !15 {
ret void
}

; Data with incorrect format should be ignored.
; CHECK-NOT: incorrect_data_format
!16 = !{!"incorrect_data_format"}

!17 = !{!"bar", !"_Z3barv"}
!18 = !{!"bar", !"_Z3barv"}
!19 = !{!"(void(*)())bar", !"_Z3barv"}
; CHECK-NO-ASPECT-NEXT: bar=2|[[BAR:[A-Za-z0-9+/]+]]
; CHECK-NO-ASPECT-NEXT: (void(*)())bar=2|[[BAR]]
define spir_kernel void @_Z3barv() {
ret void
}
Loading