Skip to content

Commit 441bffe

Browse files
authored
[SYCL][Fusion] API for kernel fusion library (#7465)
This is the second patch in a series of patches to add an implementation of thekernel fusion extension. We have split the implementation into multiple patches to make them more easy to review. This patch can be reviewed and merged independently of #7416. This patch adds the first components for the JIT compiler used for implementation of kernel fusion at runtime , concretely: API definitions Input translation from SPIR-V to LLVM IR Insertion of fused kernel function stub and metadata Supporting infrastructure such as compiler options. CMake logic to link and code to invoke this JIT from the SYCL runtime will follow in a later patch. Co-authored-by: Lukas Sommer [email protected] Co-authored-by: Victor Perez [email protected] Signed-off-by: Lukas Sommer [email protected]
1 parent 63ee151 commit 441bffe

21 files changed

+1501
-0
lines changed

.github/CODEOWNERS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,6 @@ llvm/include/llvm/SYCLLowerIR/LowerInvokeSimd.h @kbobrovs @v-klochkov @rolandsch
7070
.github/workflows/ @intel/dpcpp-devops-reviewers
7171
buildbot/ @intel/dpcpp-devops-reviewers
7272
devops/ @intel/dpcpp-devops-reviewers
73+
74+
# Kernel fusion JIT compiler
75+
sycl-fusion/ @victor-eds @Naghasan @sommerlukas

sycl-fusion/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
2+
3+
# Define a variable holding the root directory of the JIT compiler project
4+
# for use in includes etc.
5+
set(SYCL_JIT_BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
6+
7+
# For some reason, the LLVMSPIRVLib does not define any public includes.
8+
# To link against the library, define the following link to its include
9+
# directories, similar to how clang/CMakeLists.txt does it.
10+
set(LLVM_SPIRV_INCLUDE_DIRS "${LLVM_MAIN_SRC_DIR}/../llvm-spirv/include")
11+
12+
add_subdirectory(jit-compiler)

sycl-fusion/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# SYCL Kernel Fusion Compiler
2+
3+
Basic JIT compiler infrastructure to perform online kernel fusion of SYCL kernels at runtime.
4+
5+
The experimental SYCL extension for kernel fusion is described in
6+
[this proposal](../sycl/doc/extensions/experimental/sycl_ext_codeplay_kernel_fusion.asciidoc).
7+
8+
The design of the JIT compiler is described in this
9+
[design document](../sycl/doc/design/KernelFusionJIT.md).

sycl-fusion/common/include/Kernel.h

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
//==------- Kernel.h - Representation of a SYCL kernel for JIT compiler ----==//
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+
#ifndef SYCL_FUSION_COMMON_KERNEL_H
10+
#define SYCL_FUSION_COMMON_KERNEL_H
11+
12+
#include <algorithm>
13+
#include <string>
14+
#include <vector>
15+
16+
namespace jit_compiler {
17+
18+
using BinaryAddress = const unsigned char *;
19+
20+
///
21+
/// Enumerate possible kinds of parameters.
22+
/// 1:1 correspondence with the definition in kernel_desc.hpp in the DPC++ SYCL
23+
/// runtime.
24+
enum class ParameterKind : unsigned {
25+
Accessor = 0,
26+
StdLayout = 1,
27+
Sampler = 2,
28+
Pointer = 3,
29+
SpecConstBuffer = 4,
30+
Stream = 5,
31+
Invalid = 0xF,
32+
};
33+
34+
/// Different binary formats supported as input to the JIT compiler.
35+
enum class BinaryFormat { INVALID, LLVM, SPIRV };
36+
37+
/// Information about a device intermediate representation module (e.g., SPIR-V,
38+
/// LLVM IR) from DPC++.
39+
struct SYCLKernelBinaryInfo {
40+
41+
BinaryFormat Format = BinaryFormat::INVALID;
42+
43+
size_t AddressBits = 0;
44+
45+
BinaryAddress BinaryStart = nullptr;
46+
47+
size_t BinarySize = 0;
48+
};
49+
50+
///
51+
/// Describe a SYCL/OpenCL kernel attribute by its name and values.
52+
struct SYCLKernelAttribute {
53+
using AttributeValueList = std::vector<std::string>;
54+
55+
// Explicit constructor for compatibility with LLVM YAML I/O.
56+
SYCLKernelAttribute() : Values{} {};
57+
SYCLKernelAttribute(std::string Name)
58+
: AttributeName{std::move(Name)}, Values{} {}
59+
60+
std::string AttributeName;
61+
AttributeValueList Values;
62+
};
63+
64+
enum ArgUsage : unsigned char {
65+
// Used to indicate that an argument is not used by the kernel
66+
Unused = 0,
67+
// Used to indicate that an argument is used by the kernel
68+
Used = 1u,
69+
// Used to indicate that the accessor/pointer argument has been promoted to
70+
// private memory
71+
PromotedPrivate = 1u << 4,
72+
// Used to indicate that the accessor/pointer argument has been promoted to
73+
// local memory
74+
PromotedLocal = 1u << 5,
75+
};
76+
77+
///
78+
/// Encode usage of parameters for the actual kernel function.
79+
// This is a vector of unsigned char, because std::vector<bool> is a weird
80+
// construct and unlike all other std::vectors, and LLVM YAML I/O is having a
81+
// hard time coping with it.
82+
using ArgUsageMask = std::vector<std::underlying_type_t<ArgUsage>>;
83+
84+
///
85+
/// Describe the list of arguments by their kind.
86+
struct SYCLArgumentDescriptor {
87+
88+
// Explicit constructor for compatibility with LLVM YAML I/O.
89+
SYCLArgumentDescriptor() : Kinds{}, UsageMask{} {}
90+
91+
std::vector<ParameterKind> Kinds;
92+
93+
ArgUsageMask UsageMask;
94+
};
95+
96+
///
97+
/// List of SYCL/OpenCL kernel attributes.
98+
using AttributeList = std::vector<SYCLKernelAttribute>;
99+
100+
/// Information about a kernel from DPC++.
101+
struct SYCLKernelInfo {
102+
103+
std::string Name;
104+
105+
SYCLArgumentDescriptor Args;
106+
107+
AttributeList Attributes;
108+
109+
SYCLKernelBinaryInfo BinaryInfo;
110+
111+
//// Explicit constructor for compatibility with LLVM YAML I/O.
112+
SYCLKernelInfo() : Name{}, Args{}, Attributes{}, BinaryInfo{} {}
113+
114+
SYCLKernelInfo(const std::string &KernelName,
115+
const SYCLArgumentDescriptor &ArgDesc,
116+
const SYCLKernelBinaryInfo &BinInfo)
117+
: Name{KernelName}, Args{ArgDesc}, Attributes{}, BinaryInfo{BinInfo} {}
118+
119+
explicit SYCLKernelInfo(const std::string &KernelName)
120+
: Name{KernelName}, Args{}, Attributes{}, BinaryInfo{} {}
121+
};
122+
123+
///
124+
/// Represents a SPIR-V translation unit containing SYCL kernels by the
125+
/// KernelInfo for each of the contained kernels.
126+
class SYCLModuleInfo {
127+
public:
128+
using KernelInfoList = std::vector<SYCLKernelInfo>;
129+
130+
void addKernel(SYCLKernelInfo &Kernel) { Kernels.push_back(Kernel); }
131+
132+
KernelInfoList &kernels() { return Kernels; }
133+
134+
bool hasKernelFor(const std::string &KernelName) {
135+
return getKernelFor(KernelName) != nullptr;
136+
}
137+
138+
SYCLKernelInfo *getKernelFor(const std::string &KernelName) {
139+
auto It =
140+
std::find_if(Kernels.begin(), Kernels.end(),
141+
[&](SYCLKernelInfo &K) { return K.Name == KernelName; });
142+
return (It != Kernels.end()) ? &*It : nullptr;
143+
}
144+
145+
private:
146+
KernelInfoList Kernels;
147+
};
148+
149+
} // namespace jit_compiler
150+
151+
#endif // SYCL_FUSION_COMMON_KERNEL_H

sycl-fusion/common/include/KernelIO.h

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
//==----- KernelIO.h - YAML output of internal SYCL kernel representation --==//
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+
#ifndef SYCL_FUSION_COMMON_KERNELIO_H
10+
#define SYCL_FUSION_COMMON_KERNELIO_H
11+
12+
#include "Kernel.h"
13+
#include "llvm/Support/YAMLParser.h"
14+
#include "llvm/Support/YAMLTraits.h"
15+
16+
using llvm::yaml::IO;
17+
using llvm::yaml::MappingTraits;
18+
using llvm::yaml::ScalarEnumerationTraits;
19+
20+
// Specify how to map std::vectors of different user-defined types to YAML
21+
// sequences.
22+
LLVM_YAML_IS_SEQUENCE_VECTOR(jit_compiler::ArgUsageMask)
23+
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(jit_compiler::ParameterKind)
24+
LLVM_YAML_IS_SEQUENCE_VECTOR(jit_compiler::SYCLArgumentDescriptor)
25+
LLVM_YAML_IS_SEQUENCE_VECTOR(jit_compiler::SYCLKernelAttribute)
26+
LLVM_YAML_IS_SEQUENCE_VECTOR(jit_compiler::SYCLKernelInfo)
27+
28+
//
29+
// Mapping traits for the different elements of KernelInfo.
30+
namespace llvm {
31+
namespace yaml {
32+
33+
template <> struct ScalarEnumerationTraits<jit_compiler::ParameterKind> {
34+
static void enumeration(IO &IO, jit_compiler::ParameterKind &PK) {
35+
IO.enumCase(PK, "Accessor", jit_compiler::ParameterKind::Accessor);
36+
IO.enumCase(PK, "StdLayout", jit_compiler::ParameterKind::StdLayout);
37+
IO.enumCase(PK, "Sampler", jit_compiler::ParameterKind::Sampler);
38+
IO.enumCase(PK, "Pointer", jit_compiler::ParameterKind::Pointer);
39+
IO.enumCase(PK, "SpecConstantBuffer",
40+
jit_compiler::ParameterKind::SpecConstBuffer);
41+
IO.enumCase(PK, "Stream", jit_compiler::ParameterKind::Stream);
42+
IO.enumCase(PK, "Invalid", jit_compiler::ParameterKind::Invalid);
43+
}
44+
};
45+
46+
template <> struct ScalarEnumerationTraits<jit_compiler::BinaryFormat> {
47+
static void enumeration(IO &IO, jit_compiler::BinaryFormat &BF) {
48+
IO.enumCase(BF, "LLVM", jit_compiler::BinaryFormat::LLVM);
49+
IO.enumCase(BF, "SPIRV", jit_compiler::BinaryFormat::SPIRV);
50+
IO.enumCase(BF, "INVALID", jit_compiler::BinaryFormat::INVALID);
51+
}
52+
};
53+
54+
template <> struct MappingTraits<jit_compiler::SYCLKernelBinaryInfo> {
55+
static void mapping(IO &IO, jit_compiler::SYCLKernelBinaryInfo &BI) {
56+
IO.mapRequired("Format", BI.Format);
57+
IO.mapRequired("AddressBits", BI.AddressBits);
58+
// We do not serialize the pointer here on purpose.
59+
IO.mapRequired("BinarySize", BI.BinarySize);
60+
}
61+
};
62+
63+
template <> struct MappingTraits<jit_compiler::SYCLArgumentDescriptor> {
64+
static void mapping(IO &IO, jit_compiler::SYCLArgumentDescriptor &AD) {
65+
IO.mapRequired("Kinds", AD.Kinds);
66+
IO.mapRequired("Mask", AD.UsageMask);
67+
}
68+
};
69+
70+
template <> struct MappingTraits<jit_compiler::SYCLKernelAttribute> {
71+
static void mapping(IO &IO, jit_compiler::SYCLKernelAttribute &KA) {
72+
IO.mapRequired("AttrName", KA.AttributeName);
73+
IO.mapRequired("Values", KA.Values);
74+
}
75+
};
76+
77+
template <> struct MappingTraits<jit_compiler::SYCLKernelInfo> {
78+
static void mapping(IO &IO, jit_compiler::SYCLKernelInfo &KI) {
79+
IO.mapRequired("KernelName", KI.Name);
80+
IO.mapRequired("Args", KI.Args);
81+
IO.mapOptional("Attributes", KI.Attributes);
82+
IO.mapRequired("BinInfo", KI.BinaryInfo);
83+
}
84+
};
85+
86+
template <> struct MappingTraits<jit_compiler::SYCLModuleInfo> {
87+
static void mapping(IO &IO, jit_compiler::SYCLModuleInfo &SMI) {
88+
IO.mapRequired("Kernels", SMI.kernels());
89+
}
90+
};
91+
92+
} // namespace yaml
93+
} // namespace llvm
94+
95+
#endif // SYCL_FUSION_COMMON_KERNELIO_H
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
2+
add_llvm_library(sycl-fusion
3+
SHARED
4+
lib/KernelFusion.cpp
5+
lib/JITContext.cpp
6+
lib/translation/SPIRVLLVMTranslation.cpp
7+
lib/fusion/FusionHelper.cpp
8+
lib/fusion/ModuleHelper.cpp
9+
lib/helper/ConfigHelper.cpp
10+
11+
LINK_COMPONENTS
12+
Core
13+
Support
14+
Analysis
15+
TransformUtils
16+
Passes
17+
Linker
18+
ScalarOpts
19+
InstCombine
20+
)
21+
22+
target_include_directories(sycl-fusion
23+
PUBLIC
24+
$<INSTALL_INTERFACE:include>
25+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
26+
$<BUILD_INTERFACE:${SYCL_JIT_BASE_DIR}/common/include>
27+
PRIVATE
28+
${CMAKE_CURRENT_SOURCE_DIR}/lib
29+
${LLVM_SPIRV_INCLUDE_DIRS}
30+
)
31+
32+
find_package(Threads REQUIRED)
33+
34+
target_link_libraries(sycl-fusion
35+
PRIVATE
36+
LLVMSPIRVLib
37+
${CMAKE_THREAD_LIBS_INIT}
38+
)
39+
40+
install(TARGETS sycl-fusion
41+
LIBRARY DESTINATION "lib${LLVM_LIBDIR_SUFFIX}" COMPONENT sycl-fusion
42+
RUNTIME DESTINATION "bin" COMPONENT sycl-fusion)
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//==------- JITContext.h - Context holding data for the JIT compiler -------==//
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+
#ifndef SYCL_FUSION_JIT_COMPILER_JITCONTEXT_H
10+
#define SYCL_FUSION_JIT_COMPILER_JITCONTEXT_H
11+
12+
#include "llvm/IR/LLVMContext.h"
13+
#include <shared_mutex>
14+
#include <unordered_map>
15+
16+
#include "Kernel.h"
17+
#include "Parameter.h"
18+
19+
namespace jit_compiler {
20+
21+
///
22+
/// Wrapper around a SPIR-V binary.
23+
class SPIRVBinary {
24+
public:
25+
explicit SPIRVBinary(std::string Binary);
26+
27+
jit_compiler::BinaryAddress address() const;
28+
29+
size_t size() const;
30+
31+
private:
32+
std::string Blob;
33+
};
34+
35+
///
36+
/// Context to persistenly store information across invocations of the JIT
37+
/// compiler and manage lifetimes of binaries.
38+
class JITContext {
39+
40+
public:
41+
JITContext();
42+
43+
~JITContext();
44+
45+
llvm::LLVMContext *getLLVMContext();
46+
47+
SPIRVBinary &emplaceSPIRVBinary(std::string Binary);
48+
49+
private:
50+
// FIXME: Change this to std::shared_mutex after switching to C++17.
51+
using MutexT = std::shared_timed_mutex;
52+
53+
using ReadLockT = std::shared_lock<MutexT>;
54+
55+
using WriteLockT = std::unique_lock<MutexT>;
56+
57+
std::unique_ptr<llvm::LLVMContext> LLVMCtx;
58+
59+
MutexT BinariesMutex;
60+
61+
std::vector<SPIRVBinary> Binaries;
62+
};
63+
} // namespace jit_compiler
64+
65+
#endif // SYCL_FUSION_JIT_COMPILER_JITCONTEXT_H

0 commit comments

Comments
 (0)