Skip to content

Commit 84adf59

Browse files
committed
Implement linking of default device libraries.
Signed-off-by: Julian Oppermann <[email protected]>
1 parent e938da1 commit 84adf59

File tree

4 files changed

+105
-11
lines changed

4 files changed

+105
-11
lines changed

sycl-jit/jit-compiler/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ add_llvm_library(sycl-jit
2323
IPO
2424
TransformUtils
2525
Passes
26+
IRReader
2627
Linker
2728
ScalarOpts
2829
InstCombine

sycl-jit/jit-compiler/lib/KernelFusion.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -246,18 +246,25 @@ extern "C" JITResult compileSYCL(InMemoryFile SourceFile,
246246
}
247247
std::unique_ptr<llvm::Module> Module = std::move(*ModuleOrErr);
248248

249-
SYCLKernelInfo Kernel;
250-
auto Error = translation::KernelTranslator::translateKernel(
251-
Kernel, *Module, JITContext::getInstance(), BinaryFormat::SPIRV);
252-
253-
auto *LLVMCtx = &Module->getContext();
254-
Module.reset();
255-
delete LLVMCtx;
249+
auto FreeModuleAndContext = [&Module]() {
250+
auto *LLVMCtx = &Module->getContext();
251+
Module.reset();
252+
delete LLVMCtx;
253+
};
254+
255+
if (auto Error = linkDefaultDeviceLibraries(Module.get(), UserArgs)) {
256+
FreeModuleAndContext();
257+
return errorToFusionResult(std::move(Error), "Device linking failed");
258+
}
256259

257-
if (Error) {
260+
SYCLKernelInfo Kernel;
261+
if (auto Error = translation::KernelTranslator::translateKernel(
262+
Kernel, *Module, JITContext::getInstance(), BinaryFormat::SPIRV)) {
263+
FreeModuleAndContext();
258264
return errorToFusionResult(std::move(Error), "SPIR-V translation failed");
259265
}
260266

267+
FreeModuleAndContext();
261268
return JITResult{Kernel};
262269
}
263270

sycl-jit/jit-compiler/lib/rtc/DeviceCompilation.cpp

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@
1515
#include <clang/Tooling/CompilationDatabase.h>
1616
#include <clang/Tooling/Tooling.h>
1717

18+
#include <llvm/IRReader/IRReader.h>
19+
#include <llvm/Linker/Linker.h>
20+
21+
#include <array>
22+
1823
using namespace clang;
1924
using namespace clang::tooling;
2025
using namespace clang::driver;
@@ -108,9 +113,6 @@ jit_compiler::compileDeviceCode(InMemoryFile SourceFile,
108113
}
109114

110115
SmallVector<std::string> CommandLine = {"-fsycl-device-only"};
111-
// TODO: Allow instrumentation again when device library linking is
112-
// implemented.
113-
CommandLine.push_back("-fno-sycl-instrument-device-code");
114116
CommandLine.append(UserArgs.begin(), UserArgs.end());
115117
FixedCompilationDatabase DB{".", CommandLine};
116118

@@ -147,3 +149,84 @@ jit_compiler::compileDeviceCode(InMemoryFile SourceFile,
147149
// TODO: Capture compiler errors from the ClangTool.
148150
return createStringError("Unable to obtain LLVM module");
149151
}
152+
153+
Error jit_compiler::linkDefaultDeviceLibraries(llvm::Module *Module,
154+
View<const char *> UserArgs) {
155+
// This function mimics the device library selection process
156+
// `clang::driver::tools::SYCL::getDeviceLibraries`, assuming a SPIR-V target
157+
// (no AoT, no third-party GPUs, no native CPU).
158+
159+
bool DeviceInstrumentationEnabled = true;
160+
for (StringRef UA : UserArgs) {
161+
if (UA == "-fno-sycl-instrument-device-code") {
162+
DeviceInstrumentationEnabled = false;
163+
continue;
164+
}
165+
166+
// Issue warning for `-fsycl-device-lib` or `-fno-sycl-device-lib`.
167+
// TODO: Is it worth supporting these flags? We're using `LinkOnlyNeeded`
168+
// mode anyways!
169+
// TODO: If we keep the warning, it must go into the build log, not onto the
170+
// console.
171+
// TODO: The FrontendAction emits a warning that these flags are unused. We
172+
// should probably silence that by removing the argument occurence for
173+
// the compilation step.
174+
if (UA.contains("sycl-device-lib")) {
175+
errs() << "warning: device library selection with '" << UA
176+
<< "' is ignored\n";
177+
}
178+
179+
// TODO: Presence of `-fsanitize=address` would require linking
180+
// `libsycl-sanitizer`, but currently compilation fails earlier.
181+
assert(!UA.contains("-fsanitize=address") && "Device ASAN unsupported");
182+
}
183+
184+
const std::string &DPCPPRoot = getDPCPPRoot();
185+
if (DPCPPRoot == InvalidDPCPPRoot) {
186+
return createStringError("Could not locate DPCPP root directory");
187+
}
188+
189+
constexpr std::array<llvm::StringLiteral, 8> SYCLDeviceWrapperLibs = {
190+
"libsycl-crt", "libsycl-complex", "libsycl-complex-fp64",
191+
"libsycl-cmath", "libsycl-cmath-fp64", "libsycl-imf",
192+
"libsycl-imf-fp64", "libsycl-imf-bf16"};
193+
194+
constexpr std::array<llvm::StringLiteral, 3> SYCLDeviceAnnotationLibs = {
195+
"libsycl-itt-user-wrappers", "libsycl-itt-compiler-wrappers",
196+
"libsycl-itt-stubs"};
197+
198+
LLVMContext &Ctx = Module->getContext();
199+
auto Link = [&](ArrayRef<llvm::StringLiteral> LibNames) -> Error {
200+
for (const auto &LibName : LibNames) {
201+
std::string LibPath = (DPCPPRoot + "/lib/" + LibName + ".bc").str();
202+
203+
SMDiagnostic Diag;
204+
std::unique_ptr<llvm::Module> Lib = parseIRFile(LibPath, Diag, Ctx);
205+
if (!Lib) {
206+
std::string DiagMsg;
207+
raw_string_ostream SOS(DiagMsg);
208+
Diag.print(/*ProgName=*/nullptr, SOS);
209+
return createStringError(DiagMsg);
210+
}
211+
212+
if (Linker::linkModules(*Module, std::move(Lib),
213+
Linker::LinkOnlyNeeded)) {
214+
// TODO: `linkModules` always prints errors to the console.
215+
return createStringError("Unable to link device library: %s",
216+
LibPath.c_str());
217+
}
218+
}
219+
220+
return Error::success();
221+
};
222+
223+
if (auto Error = Link(SYCLDeviceWrapperLibs)) {
224+
return Error;
225+
}
226+
if (DeviceInstrumentationEnabled) {
227+
if (auto Error = Link(SYCLDeviceAnnotationLibs)) {
228+
return Error;
229+
}
230+
}
231+
return Error::success();
232+
}

sycl-jit/jit-compiler/lib/rtc/DeviceCompilation.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ llvm::Expected<std::unique_ptr<llvm::Module>>
2323
compileDeviceCode(InMemoryFile SourceFile, View<InMemoryFile> IncludeFiles,
2424
View<const char *> UserArgs);
2525

26+
llvm::Error linkDefaultDeviceLibraries(llvm::Module *Module,
27+
View<const char *> UserArgs);
28+
2629
} // namespace jit_compiler
2730

2831
#endif // SYCL_JIT_COMPILER_RTC_DEVICE_COMPILATION_H

0 commit comments

Comments
 (0)