Skip to content

[SYCL] Fix sycl-post-link when no split and symbols are requested. #1454

New issue

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

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

Already on GitHub? # to your account

Merged
merged 3 commits into from
Apr 3, 2020
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
25 changes: 25 additions & 0 deletions llvm/test/tools/sycl-post-link/sym_but_no_split.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
; This test checks that the post-link tool produces a correct resulting file
; table and a symbol file for an input module with two kernels when no code
; splitting is requested.
;
; RUN: sycl-post-link -symbols -spec-const=rt -S %s -o %t.files.table
; RUN: FileCheck %s -input-file=%t.files.table --check-prefixes CHECK-TABLE
; RUN: FileCheck %s -input-file=%t.files_0.sym --match-full-lines --check-prefixes CHECK-SYM

define dso_local spir_kernel void @KERNEL_AAA() {
; CHECK-SYM-NOT: {{[a-zA-Z0-9._@]+}}
; CHECK-SYM: KERNEL_AAA
entry:
ret void
}

define dso_local spir_kernel void @KERNEL_BBB() {
; CHECK-SYM-NEXT: KERNEL_BBB
; CHECK-SYM-EMPTY:
entry:
ret void
}

; CHECK-TABLE: [Code|Properties|Symbols]
; CHECK-TABLE-NEXT: {{.*}}files_0.sym
; CHECK-TABLE-EMPTY:
52 changes: 42 additions & 10 deletions llvm/tools/sycl-post-link/sycl-post-link.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,23 +121,51 @@ static void writeToFile(std::string Filename, std::string Content) {
OS.close();
}

// Output parameter ResKernelModuleMap is a map containing groups of kernels
// with same values of the sycl-module-id attribute.
// The function fills ResKernelModuleMap using input module M.
// Describes scope covered by each entry in the module-kernel map populated by
// the collectKernelModuleMap function.
enum KernelMapEntryScope {
Scope_PerKernel, // one entry per kernel
Scope_PerModule, // one entry per module
Scope_Global // single entry in the map for all kernels
};

// This function decides how kernels of the input module M will be distributed
// ("split") into multiple modules based on the command options and IR
// attributes. The decision is recorded in the output map parameter
// ResKernelModuleMap which maps some key to a group of kernels. Each such group
// along with IR it depends on (globals, functions from its call graph,...) will
// constitute a separate module.
static void collectKernelModuleMap(
Module &M, std::map<StringRef, std::vector<Function *>> &ResKernelModuleMap,
bool OneKernelPerModule) {

constexpr char ATTR_SYCL_MODULE_ID[] = "sycl-module-id";
KernelMapEntryScope EntryScope) {

for (auto &F : M.functions()) {
if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
if (OneKernelPerModule) {
switch (EntryScope) {
case Scope_PerKernel:
ResKernelModuleMap[F.getName()].push_back(&F);
} else if (F.hasFnAttribute(ATTR_SYCL_MODULE_ID)) {
break;
case Scope_PerModule: {
constexpr char ATTR_SYCL_MODULE_ID[] = "sycl-module-id";

// TODO It may make sense to group all kernels w/o the attribute into
// a separate module rather than issuing an error. Should probably be
// controlled by an option.
if (!F.hasFnAttribute(ATTR_SYCL_MODULE_ID))
error("no '" + Twine(ATTR_SYCL_MODULE_ID) +
"' attribute in kernel '" + F.getName() +
"', per-module split not possible");
Comment on lines +155 to +157
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we group kernels without this attribute into a separate module?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't know, maybe. The answer would be 'yes' if there are practical scenarios where per-module splitting is requested on modules with functions w/o module-id attribute. This would be a topic for a separate PR, anyway.

Here I just protect from the existing problem that I noticed - silent dropping of kernels w/o module-id attribute in -split=source mode. What I can do now is add a TODO.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sure. I thought about this case while implementing split, but I didn't come up with the viable case when it is possible to get such module containing kernels with and without module-id attribute.

Attribute Id = F.getFnAttribute(ATTR_SYCL_MODULE_ID);
StringRef Val = Id.getValueAsString();
ResKernelModuleMap[Val].push_back(&F);
break;
}
case Scope_Global:
// the map key is not significant here
ResKernelModuleMap["<GLOBAL>"].push_back(&F);
break;
default:
llvm_unreachable("unknown scope");
}
}
}
Expand Down Expand Up @@ -375,8 +403,12 @@ int main(int argc, char **argv) {

std::map<StringRef, std::vector<Function *>> GlobalsSet;

if (DoSplit || DoSymGen)
collectKernelModuleMap(*MPtr, GlobalsSet, SplitMode == SPLIT_PER_KERNEL);
if (DoSplit || DoSymGen) {
KernelMapEntryScope Scope = Scope_Global;
if (DoSplit)
Scope = SplitMode == SPLIT_PER_KERNEL ? Scope_PerKernel : Scope_PerModule;
collectKernelModuleMap(*MPtr, GlobalsSet, Scope);
}

std::vector<std::unique_ptr<Module>> ResultModules;
std::vector<SpecIDMapTy> ResultSpecIDMaps;
Expand Down