Skip to content

Commit e68ebeb

Browse files
[SYCL] SYCL_JIT support on Windows for kernel_compiler (#16018)
Presently the kernel_compiler extension uses the sycl-jit compiler on Linux, but on Windows it simply reports back that the support is unavailable. In this PR sycl-jit is made available for Windows as well for its use by the kernel_compiler. In a follow-on PR I will remove `sycl_jit` as a source language enumeration and make the SYCL_JIT mechanism the default when the kernel_compiler is compiling SYCL code, as well as remove the invoking one, rather than trying to do everything at once.
1 parent 21018ab commit e68ebeb

File tree

14 files changed

+193
-108
lines changed

14 files changed

+193
-108
lines changed

sycl-jit/CMakeLists.txt

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,23 @@ set(SYCL_JIT_BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
99
# directories, similar to how clang/CMakeLists.txt does it.
1010
set(LLVM_SPIRV_INCLUDE_DIRS "${LLVM_MAIN_SRC_DIR}/../llvm-spirv/include")
1111

12-
# Set library-wide warning options.
13-
set(SYCL_JIT_WARNING_FLAGS -Wall -Wextra)
12+
if (NOT WIN32 AND NOT CYGWIN)
13+
# Set library-wide warning options.
14+
set(SYCL_JIT_WARNING_FLAGS -Wall -Wextra)
1415

15-
option(SYCL_JIT_ENABLE_WERROR "Treat all warnings as errors in SYCL kernel JIT library" ON)
16-
if(SYCL_JIT_ENABLE_WERROR)
17-
list(APPEND SYCL_JIT_WARNING_FLAGS -Werror)
18-
endif(SYCL_JIT_ENABLE_WERROR)
16+
option(SYCL_JIT_ENABLE_WERROR "Treat all warnings as errors in SYCL kernel JIT library" ON)
17+
if(SYCL_JIT_ENABLE_WERROR)
18+
list(APPEND SYCL_JIT_WARNING_FLAGS -Werror)
19+
endif(SYCL_JIT_ENABLE_WERROR)
20+
endif()
1921

20-
if(WIN32)
21-
message(WARNING "Kernel JIT not yet supported on Windows")
22-
else(WIN32)
23-
add_subdirectory(common)
24-
add_subdirectory(jit-compiler)
25-
add_subdirectory(passes)
22+
23+
add_subdirectory(common)
24+
add_subdirectory(jit-compiler)
25+
add_subdirectory(passes)
26+
27+
# Loadable plugins for opt aren't supported on Windows,
28+
# so we can't execute the tests.
29+
if (NOT WIN32 AND NOT CYGWIN)
2630
add_subdirectory(test)
27-
endif(WIN32)
31+
endif()

sycl-jit/jit-compiler/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ add_llvm_library(sycl-jit
4040
clangSerialization
4141
)
4242

43+
if(WIN32)
44+
target_link_libraries(sycl-jit PRIVATE Shlwapi)
45+
endif()
46+
4347
target_compile_options(sycl-jit PRIVATE ${SYCL_JIT_WARNING_FLAGS})
4448

4549
# Mark LLVM and SPIR-V headers as system headers to ignore warnigns in them.

sycl-jit/jit-compiler/include/KernelFusion.h

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99
#ifndef SYCL_FUSION_JIT_COMPILER_KERNELFUSION_H
1010
#define SYCL_FUSION_JIT_COMPILER_KERNELFUSION_H
1111

12+
#ifdef _WIN32
13+
#define KF_EXPORT_SYMBOL __declspec(dllexport)
14+
#else
15+
#define KF_EXPORT_SYMBOL
16+
#endif
17+
1218
#include "Kernel.h"
1319
#include "Options.h"
1420
#include "Parameter.h"
@@ -55,25 +61,31 @@ extern "C" {
5561
#ifdef __clang__
5662
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
5763
#endif // __clang__
58-
JITResult fuseKernels(View<SYCLKernelInfo> KernelInformation,
59-
const char *FusedKernelName,
60-
View<ParameterIdentity> Identities,
61-
BarrierFlags BarriersFlags,
62-
View<ParameterInternalization> Internalization,
63-
View<jit_compiler::JITConstant> JITConstants);
6464

65-
JITResult materializeSpecConstants(const char *KernelName,
66-
jit_compiler::SYCLKernelBinaryInfo &BinInfo,
67-
View<unsigned char> SpecConstBlob);
65+
#ifdef _MSC_VER
66+
#pragma warning(push)
67+
#pragma warning(disable : 4190)
68+
#endif // _MSC_VER
69+
70+
KF_EXPORT_SYMBOL JITResult
71+
fuseKernels(View<SYCLKernelInfo> KernelInformation, const char *FusedKernelName,
72+
View<ParameterIdentity> Identities, BarrierFlags BarriersFlags,
73+
View<ParameterInternalization> Internalization,
74+
View<jit_compiler::JITConstant> JITConstants);
75+
76+
KF_EXPORT_SYMBOL JITResult materializeSpecConstants(
77+
const char *KernelName, jit_compiler::SYCLKernelBinaryInfo &BinInfo,
78+
View<unsigned char> SpecConstBlob);
6879

69-
JITResult compileSYCL(InMemoryFile SourceFile, View<InMemoryFile> IncludeFiles,
70-
View<const char *> UserArgs);
80+
KF_EXPORT_SYMBOL JITResult compileSYCL(InMemoryFile SourceFile,
81+
View<InMemoryFile> IncludeFiles,
82+
View<const char *> UserArgs);
7183

7284
/// Clear all previously set options.
73-
void resetJITConfiguration();
85+
KF_EXPORT_SYMBOL void resetJITConfiguration();
7486

7587
/// Add an option to the configuration.
76-
void addToJITConfiguration(OptionStorage &&Opt);
88+
KF_EXPORT_SYMBOL void addToJITConfiguration(OptionStorage &&Opt);
7789

7890
} // end of extern "C"
7991

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

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,9 @@ static bool isTargetFormatSupported(BinaryFormat TargetFormat) {
7171
}
7272
}
7373

74-
extern "C" JITResult
75-
materializeSpecConstants(const char *KernelName,
76-
jit_compiler::SYCLKernelBinaryInfo &BinInfo,
77-
View<unsigned char> SpecConstBlob) {
74+
extern "C" KF_EXPORT_SYMBOL JITResult materializeSpecConstants(
75+
const char *KernelName, jit_compiler::SYCLKernelBinaryInfo &BinInfo,
76+
View<unsigned char> SpecConstBlob) {
7877
auto &JITCtx = JITContext::getInstance();
7978

8079
TargetInfo TargetInfo = ConfigHelper::get<option::JITTargetInfo>();
@@ -115,12 +114,11 @@ materializeSpecConstants(const char *KernelName,
115114
return JITResult{MaterializerKernelInfo};
116115
}
117116

118-
extern "C" JITResult fuseKernels(View<SYCLKernelInfo> KernelInformation,
119-
const char *FusedKernelName,
120-
View<ParameterIdentity> Identities,
121-
BarrierFlags BarriersFlags,
122-
View<ParameterInternalization> Internalization,
123-
View<jit_compiler::JITConstant> Constants) {
117+
extern "C" KF_EXPORT_SYMBOL JITResult
118+
fuseKernels(View<SYCLKernelInfo> KernelInformation, const char *FusedKernelName,
119+
View<ParameterIdentity> Identities, BarrierFlags BarriersFlags,
120+
View<ParameterInternalization> Internalization,
121+
View<jit_compiler::JITConstant> Constants) {
124122

125123
std::vector<std::string> KernelsToFuse;
126124
llvm::transform(KernelInformation, std::back_inserter(KernelsToFuse),
@@ -236,9 +234,9 @@ extern "C" JITResult fuseKernels(View<SYCLKernelInfo> KernelInformation,
236234
return JITResult{FusedKernelInfo};
237235
}
238236

239-
extern "C" JITResult compileSYCL(InMemoryFile SourceFile,
240-
View<InMemoryFile> IncludeFiles,
241-
View<const char *> UserArgs) {
237+
extern "C" KF_EXPORT_SYMBOL JITResult
238+
compileSYCL(InMemoryFile SourceFile, View<InMemoryFile> IncludeFiles,
239+
View<const char *> UserArgs) {
242240
auto ModuleOrErr = compileDeviceCode(SourceFile, IncludeFiles, UserArgs);
243241
if (!ModuleOrErr) {
244242
return errorToFusionResult(ModuleOrErr.takeError(),
@@ -261,8 +259,10 @@ extern "C" JITResult compileSYCL(InMemoryFile SourceFile,
261259
return JITResult{Kernel};
262260
}
263261

264-
extern "C" void resetJITConfiguration() { ConfigHelper::reset(); }
262+
extern "C" KF_EXPORT_SYMBOL void resetJITConfiguration() {
263+
ConfigHelper::reset();
264+
}
265265

266-
extern "C" void addToJITConfiguration(OptionStorage &&Opt) {
266+
extern "C" KF_EXPORT_SYMBOL void addToJITConfiguration(OptionStorage &&Opt) {
267267
ConfigHelper::getConfig().set(std::move(Opt));
268268
}

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

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,49 @@
2020
static char X; // Dummy symbol, used as an anchor for `dlinfo` below.
2121
#endif
2222

23+
#ifdef _WIN32
24+
#include <filesystem> // For std::filesystem::path ( C++17 only )
25+
#include <shlwapi.h> // For PathRemoveFileSpec
26+
#include <windows.h> // For GetModuleFileName, HMODULE, DWORD, MAX_PATH
27+
28+
// cribbed from sycl/source/detail/os_util.cpp
29+
using OSModuleHandle = intptr_t;
30+
static constexpr OSModuleHandle ExeModuleHandle = -1;
31+
static OSModuleHandle getOSModuleHandle(const void *VirtAddr) {
32+
HMODULE PhModule;
33+
DWORD Flag = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
34+
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT;
35+
auto LpModuleAddr = reinterpret_cast<LPCSTR>(VirtAddr);
36+
if (!GetModuleHandleExA(Flag, LpModuleAddr, &PhModule)) {
37+
// Expect the caller to check for zero and take
38+
// necessary action
39+
return 0;
40+
}
41+
if (PhModule == GetModuleHandleA(nullptr))
42+
return ExeModuleHandle;
43+
return reinterpret_cast<OSModuleHandle>(PhModule);
44+
}
45+
46+
// cribbed from sycl/source/detail/os_util.cpp
47+
/// Returns an absolute path where the object was found.
48+
std::wstring getCurrentDSODir() {
49+
wchar_t Path[MAX_PATH];
50+
auto Handle = getOSModuleHandle(reinterpret_cast<void *>(&getCurrentDSODir));
51+
DWORD Ret = GetModuleFileName(
52+
reinterpret_cast<HMODULE>(ExeModuleHandle == Handle ? 0 : Handle), Path,
53+
MAX_PATH);
54+
assert(Ret < MAX_PATH && "Path is longer than MAX_PATH?");
55+
assert(Ret > 0 && "GetModuleFileName failed");
56+
(void)Ret;
57+
58+
BOOL RetCode = PathRemoveFileSpec(Path);
59+
assert(RetCode && "PathRemoveFileSpec failed");
60+
(void)RetCode;
61+
62+
return Path;
63+
}
64+
#endif // _WIN32
65+
2366
static constexpr auto InvalidDPCPPRoot = "<invalid>";
2467

2568
static const std::string &getDPCPPRoot() {
@@ -42,6 +85,10 @@ static const std::string &getDPCPPRoot() {
4285
}
4386
#endif // _GNU_SOURCE
4487

88+
#ifdef _WIN32
89+
DPCPPRoot = std::filesystem::path(getCurrentDSODir()).parent_path().string();
90+
#endif // _WIN32
91+
4592
// TODO: Implemenent other means of determining the DPCPP root, e.g.
4693
// evaluating the `CMPLR_ROOT` env.
4794

sycl-jit/passes/CMakeLists.txt

Lines changed: 50 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,54 @@
1-
# Module library for usage as library/pass-plugin with LLVM opt.
2-
add_llvm_library(SYCLKernelJIT MODULE
3-
SYCLFusionPasses.cpp
4-
kernel-fusion/Builtins.cpp
5-
kernel-fusion/SYCLKernelFusion.cpp
6-
kernel-fusion/SYCLSpecConstMaterializer.cpp
7-
kernel-info/SYCLKernelInfo.cpp
8-
internalization/Internalization.cpp
9-
syclcp/SYCLCP.cpp
10-
cleanup/Cleanup.cpp
11-
debug/PassDebug.cpp
12-
target/TargetFusionInfo.cpp
13-
14-
DEPENDS
15-
intrinsics_gen
16-
)
1+
# See llvm/examples/Bye/CmakeLists.txt as to why this kind of loadable plugin libraries
2+
# isn't supported on Windows.
3+
if (NOT WIN32 AND NOT CYGWIN)
4+
# Module library for usage as library/pass-plugin with LLVM opt.
5+
add_llvm_library(SYCLKernelJIT MODULE
6+
SYCLFusionPasses.cpp
7+
kernel-fusion/Builtins.cpp
8+
kernel-fusion/SYCLKernelFusion.cpp
9+
kernel-fusion/SYCLSpecConstMaterializer.cpp
10+
kernel-info/SYCLKernelInfo.cpp
11+
internalization/Internalization.cpp
12+
syclcp/SYCLCP.cpp
13+
cleanup/Cleanup.cpp
14+
debug/PassDebug.cpp
15+
target/TargetFusionInfo.cpp
16+
17+
DEPENDS
18+
intrinsics_gen
19+
)
20+
21+
target_compile_options(SYCLKernelJIT PRIVATE ${SYCL_JIT_WARNING_FLAGS})
22+
23+
# Mark LLVM headers as system headers to ignore warnigns in them. This
24+
# classification remains intact even if the same path is added as a normal
25+
# include path in GCC and Clang.
26+
target_include_directories(SYCLKernelJIT
27+
SYSTEM PRIVATE
28+
${LLVM_MAIN_INCLUDE_DIR}
29+
)
30+
target_include_directories(SYCLKernelJIT
31+
PUBLIC
32+
${CMAKE_CURRENT_SOURCE_DIR}
33+
PRIVATE
34+
${SYCL_JIT_BASE_DIR}/common/include
35+
)
36+
37+
target_link_libraries(SYCLKernelJIT
38+
PRIVATE
39+
sycl-jit-common
40+
)
41+
42+
add_dependencies(SYCLKernelJIT sycl-headers)
43+
44+
if("NVPTX" IN_LIST LLVM_TARGETS_TO_BUILD)
45+
target_compile_definitions(SYCLKernelJIT PRIVATE JIT_SUPPORT_PTX)
46+
endif()
47+
48+
if("AMDGPU" IN_LIST LLVM_TARGETS_TO_BUILD)
49+
target_compile_definitions(SYCLKernelJIT PRIVATE JIT_SUPPORT_AMDGCN)
50+
endif()
1751

18-
target_compile_options(SYCLKernelJIT PRIVATE ${SYCL_JIT_WARNING_FLAGS})
19-
20-
# Mark LLVM headers as system headers to ignore warnigns in them. This
21-
# classification remains intact even if the same path is added as a normal
22-
# include path in GCC and Clang.
23-
target_include_directories(SYCLKernelJIT
24-
SYSTEM PRIVATE
25-
${LLVM_MAIN_INCLUDE_DIR}
26-
)
27-
target_include_directories(SYCLKernelJIT
28-
PUBLIC
29-
${CMAKE_CURRENT_SOURCE_DIR}
30-
PRIVATE
31-
${SYCL_JIT_BASE_DIR}/common/include
32-
)
33-
34-
target_link_libraries(SYCLKernelJIT
35-
PRIVATE
36-
sycl-jit-common
37-
)
38-
39-
add_dependencies(SYCLKernelJIT sycl-headers)
40-
41-
if("NVPTX" IN_LIST LLVM_TARGETS_TO_BUILD)
42-
target_compile_definitions(SYCLKernelJIT PRIVATE JIT_SUPPORT_PTX)
43-
endif()
44-
45-
if("AMDGPU" IN_LIST LLVM_TARGETS_TO_BUILD)
46-
target_compile_definitions(SYCLKernelJIT PRIVATE JIT_SUPPORT_AMDGCN)
4752
endif()
4853

4954
# Static library for linking with the jit_compiler

sycl-jit/passes/target/TargetFusionInfo.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,9 +356,12 @@ class SPIRVTargetFusionInfo : public TargetFusionInfoImpl {
356356
Name = Name.drop_front(Name.find(SPIRVBuiltinPrefix) +
357357
SPIRVBuiltinPrefix.size());
358358
// Check that Name does not start with any name in UnsafeBuiltIns
359-
const auto *Iter =
360-
std::upper_bound(UnsafeBuiltIns.begin(), UnsafeBuiltIns.end(), Name);
361-
return Iter == UnsafeBuiltIns.begin() || !Name.starts_with(*(Iter - 1));
359+
for (const StringRef &Unsafe : UnsafeBuiltIns) {
360+
if (Name.starts_with(Unsafe)) {
361+
return false;
362+
}
363+
}
364+
return true;
362365
}
363366

364367
unsigned getIndexSpaceBuiltinBitwidth() const override { return 64; }

sycl/CMakeLists.txt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,6 @@ endif()
3030
# Option to enable JIT, this in turn makes kernel fusion and spec constant
3131
# materialization possible.
3232
option(SYCL_ENABLE_EXTENSION_JIT "Enable extension to JIT kernels" ON)
33-
if(SYCL_ENABLE_EXTENSION_JIT AND WIN32)
34-
message(WARNING "Extension to JIT kernels not yet supported on Windows")
35-
set(SYCL_ENABLE_EXTENSION_JIT OFF CACHE
36-
BOOL "Extension to JIT kernels not yet supported on Windows" FORCE)
37-
endif()
3833

3934
if (NOT XPTI_INCLUDES)
4035
set(XPTI_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/../xpti/include)

sycl/source/detail/jit_compiler.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <detail/kernel_impl.hpp>
1616
#include <detail/queue_impl.hpp>
1717
#include <detail/sycl_mem_obj_t.hpp>
18+
#include <sycl/detail/os_util.hpp>
1819
#include <sycl/detail/ur.hpp>
1920
#include <sycl/kernel_bundle.hpp>
2021

@@ -30,7 +31,12 @@ static inline void printPerformanceWarning(const std::string &Message) {
3031

3132
jit_compiler::jit_compiler() {
3233
auto checkJITLibrary = [this]() -> bool {
34+
#ifdef _WIN32
35+
static const std::string dir = sycl::detail::OSUtil::getCurrentDSODir();
36+
static const std::string JITLibraryName = dir + "\\" + "sycl-jit.dll";
37+
#else
3338
static const std::string JITLibraryName = "libsycl-jit.so";
39+
#endif
3440

3541
void *LibraryPtr = sycl::detail::ur::loadOsLibrary(JITLibraryName);
3642
if (LibraryPtr == nullptr) {
@@ -625,6 +631,7 @@ ur_kernel_handle_t jit_compiler::materializeSpecConstants(
625631
QueueImplPtr Queue, const RTDeviceBinaryImage *BinImage,
626632
const std::string &KernelName,
627633
const std::vector<unsigned char> &SpecConstBlob) {
634+
#ifndef _WIN32
628635
if (!BinImage) {
629636
throw sycl::exception(sycl::make_error_code(sycl::errc::invalid),
630637
"No suitable IR available for materializing");
@@ -716,6 +723,13 @@ ur_kernel_handle_t jit_compiler::materializeSpecConstants(
716723
}
717724

718725
return NewKernel;
726+
#else // _WIN32
727+
(void)Queue;
728+
(void)BinImage;
729+
(void)KernelName;
730+
(void)SpecConstBlob;
731+
return nullptr;
732+
#endif // _WIN32
719733
}
720734

721735
std::unique_ptr<detail::CG>

0 commit comments

Comments
 (0)