Skip to content

Commit b59a8c3

Browse files
authored
[SYCL][Fusion][NoSTL] Replace YAML I/O for SYCLModuleInfo by metadata-backed approach (#12262)
For testing purposes, the `SYCLModuleInfo` data structure (and its dependents) implemented LLVM's YAML traits for easy (de-)serialization. However, as the YAML infrastructure requires the participating structs to support dynamic construction of their instances (e.g. growing a vector of argument types during parsing), this is detrimental to our goal of dropping STL classes from the fusion interface. This PR rewrites the affected lit tests by encoding the information to be injected as a named metadata in the IR module. Only tests for the kernel fusion pass actually require the module info; it could be dropped without replacement from the internalization and CP tests. We also no longer encode the binary format information as the tests were not sensitive to it. The named metadata is not intended to persist across the pipeline, and is currently erased right after parsing. The YAML export was replaced by a simpler (but still YAML-inspired) textual dump of the module info. *This PR is part of a series of changes to remove uses of STL classes in the kernel fusion interface to prevent ABI issues in the future.* --------- Signed-off-by: Julian Oppermann <[email protected]>
1 parent 2a09118 commit b59a8c3

35 files changed

+320
-365
lines changed

sycl-fusion/common/include/Kernel.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,6 @@ struct SYCLKernelBinaryInfo {
111111
struct SYCLKernelAttribute {
112112
using AttributeValueList = std::vector<std::string>;
113113

114-
// Explicit constructor for compatibility with LLVM YAML I/O.
115-
SYCLKernelAttribute() : Values{} {};
116114
SYCLKernelAttribute(std::string Name)
117115
: AttributeName{std::move(Name)}, Values{} {}
118116

@@ -135,18 +133,11 @@ enum ArgUsage : uint8_t {
135133

136134
///
137135
/// Encode usage of parameters for the actual kernel function.
138-
// This is a vector of unsigned char, because std::vector<bool> is a weird
139-
// construct and unlike all other std::vectors, and LLVM YAML I/O is having a
140-
// hard time coping with it.
141136
using ArgUsageMask = std::vector<std::underlying_type_t<ArgUsage>>;
142137

143138
///
144139
/// Describe the list of arguments by their kind.
145140
struct SYCLArgumentDescriptor {
146-
147-
// Explicit constructor for compatibility with LLVM YAML I/O.
148-
SYCLArgumentDescriptor() : Kinds{}, UsageMask{} {}
149-
150141
std::vector<ParameterKind> Kinds;
151142

152143
ArgUsageMask UsageMask;
@@ -277,9 +268,6 @@ struct SYCLKernelInfo {
277268

278269
SYCLKernelBinaryInfo BinaryInfo;
279270

280-
//// Explicit constructor for compatibility with LLVM YAML I/O.
281-
SYCLKernelInfo() : Name{}, Args{}, Attributes{}, NDR{}, BinaryInfo{} {}
282-
283271
SYCLKernelInfo(const std::string &KernelName,
284272
const SYCLArgumentDescriptor &ArgDesc, const NDRange &NDR,
285273
const SYCLKernelBinaryInfo &BinInfo)

sycl-fusion/common/lib/KernelIO.h

Lines changed: 0 additions & 97 deletions
This file was deleted.

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
#include "KernelFusion.h"
1010
#include "Kernel.h"
11-
#include "KernelIO.h"
1211
#include "NDRangesHelper.h"
1312
#include "Options.h"
1413
#include "fusion/FusionHelper.h"

sycl-fusion/passes/kernel-info/SYCLKernelInfo.cpp

Lines changed: 124 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,44 +8,109 @@
88

99
#include "SYCLKernelInfo.h"
1010

11-
#include "KernelIO.h"
11+
#include "metadata/MDParsing.h"
1212

13+
#include "llvm/ADT/STLExtras.h"
1314
#include "llvm/IR/DiagnosticPrinter.h"
1415
#include "llvm/Support/CommandLine.h"
16+
#include "llvm/Support/FormattedStream.h"
1517

1618
using namespace llvm;
1719
using namespace jit_compiler;
1820

19-
static llvm::cl::opt<std::string>
20-
ModuleInfoFilePath("sycl-info-path",
21-
llvm::cl::desc("Path to the SYCL module info YAML file"),
22-
llvm::cl::value_desc("filename"), llvm::cl::init(""));
23-
2421
llvm::AnalysisKey SYCLModuleInfoAnalysis::Key;
2522

26-
void SYCLModuleInfoAnalysis::loadModuleInfoFromFile() {
23+
// Keep this in sync with the enum definition in
24+
// `sycl-fusion/common/include/Kernel.h`.
25+
static constexpr unsigned NumParameterKinds = 6;
26+
static constexpr std::array<llvm::StringLiteral, NumParameterKinds>
27+
ParameterKindStrings = {
28+
StringLiteral{"Accessor"},
29+
StringLiteral{"StdLayout"},
30+
StringLiteral{"Sampler"},
31+
StringLiteral{"Pointer"},
32+
StringLiteral{"SpecConstantBuffer"},
33+
StringLiteral{"Stream"},
34+
};
35+
static constexpr llvm::StringLiteral InvalidParameterKindString{"Invalid"};
36+
37+
void SYCLModuleInfoAnalysis::loadModuleInfoFromMetadata(Module &M) {
2738
DiagnosticPrinterRawOStream Printer{llvm::errs()};
28-
ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrError =
29-
MemoryBuffer::getFile(ModuleInfoFilePath);
30-
if (std::error_code EC = FileOrError.getError()) {
31-
Printer << "Could not open file " << ModuleInfoFilePath << " due to error "
32-
<< EC.message() << "\n";
33-
return;
34-
}
35-
llvm::yaml::Input In{FileOrError->get()->getMemBufferRef()};
3639
ModuleInfo = std::make_unique<SYCLModuleInfo>();
37-
In >> *ModuleInfo;
38-
if (In.error()) {
39-
Printer << "Error parsing YAML from " << ModuleInfoFilePath << ": "
40-
<< In.error().message() << "\n";
40+
auto *MIMD = M.getNamedMetadata(ModuleInfoMDKey);
41+
if (!MIMD) {
42+
Printer << "No !" << ModuleInfoMDKey << " metadata found in module\n";
4143
return;
4244
}
45+
46+
for (auto *KIMD : MIMD->operands()) {
47+
assert(KIMD->getNumOperands() >= 3 && "Incomplete kernel info entry");
48+
const auto *It = KIMD->op_begin(), *End = KIMD->op_end();
49+
50+
// Operand 0: Kernel name
51+
auto Name = cast<MDString>(*It)->getString().str();
52+
SYCLKernelInfo KernelInfo{std::move(Name)};
53+
++It;
54+
55+
// Operand 1: Argument kinds
56+
auto *ArgsKindsMD = cast<MDNode>(*It);
57+
llvm::transform(
58+
ArgsKindsMD->operands(), std::back_inserter(KernelInfo.Args.Kinds),
59+
[](const auto &Op) {
60+
auto KindStr = cast<MDString>(Op)->getString();
61+
auto It = std::find_if(
62+
ParameterKindStrings.begin(), ParameterKindStrings.end(),
63+
[&KindStr](auto &SL) { return KindStr == SL; });
64+
if (It == ParameterKindStrings.end()) {
65+
return ParameterKind::Invalid;
66+
}
67+
auto Idx = std::distance(ParameterKindStrings.begin(), It);
68+
return static_cast<ParameterKind>(Idx);
69+
});
70+
++It;
71+
72+
// Operand 2: Argument usage mask
73+
auto *ArgsUsageMaskMD = cast<MDNode>(*It);
74+
llvm::transform(
75+
ArgsUsageMaskMD->operands(),
76+
std::back_inserter(KernelInfo.Args.UsageMask), [](const auto &Op) {
77+
auto UIntOrErr = metadataToUInt<std::underlying_type_t<ArgUsage>>(Op);
78+
if (UIntOrErr.takeError()) {
79+
llvm_unreachable("Invalid kernel info metadata");
80+
}
81+
return *UIntOrErr;
82+
});
83+
++It;
84+
85+
// Operands 3..n: Attributes
86+
for (; It != End; ++It) {
87+
auto *AIMD = cast<MDNode>(*It);
88+
assert(AIMD->getNumOperands() > 1);
89+
const auto *AttrIt = AIMD->op_begin(), *AttrEnd = AIMD->op_end();
90+
91+
// Operand 0: Attribute name
92+
auto Name = cast<MDString>(*AttrIt)->getString().str();
93+
++AttrIt;
94+
95+
// Operands 1..m: String values
96+
auto &KernelAttr = KernelInfo.Attributes.emplace_back(std::move(Name));
97+
for (; AttrIt != AttrEnd; ++AttrIt) {
98+
auto Value = cast<MDString>(*AttrIt)->getString().str();
99+
KernelAttr.Values.emplace_back(std::move(Value));
100+
}
101+
}
102+
103+
ModuleInfo->addKernel(KernelInfo);
104+
}
105+
106+
// Metadata is no longer needed.
107+
MIMD->eraseFromParent();
43108
}
44109

45110
SYCLModuleInfoAnalysis::Result
46-
SYCLModuleInfoAnalysis::run(Module &, ModuleAnalysisManager &) {
111+
SYCLModuleInfoAnalysis::run(Module &M, ModuleAnalysisManager &) {
47112
if (!ModuleInfo) {
48-
loadModuleInfoFromFile();
113+
loadModuleInfoFromMetadata(M);
49114
}
50115
return {ModuleInfo.get()};
51116
}
@@ -59,7 +124,43 @@ PreservedAnalyses SYCLModuleInfoPrinter::run(Module &Mod,
59124
Printer << "Error: No module info available\n";
60125
return PreservedAnalyses::all();
61126
}
62-
llvm::yaml::Output Out{llvm::outs()};
63-
Out << *ModuleInfo;
127+
128+
formatted_raw_ostream Out{llvm::outs()};
129+
constexpr auto Indent = 2, Pad = 26;
130+
for (const auto &KernelInfo : ModuleInfo->kernels()) {
131+
Out << "KernelName:";
132+
Out.PadToColumn(Pad);
133+
Out << KernelInfo.Name << '\n';
134+
135+
Out.indent(Indent) << "Args:\n";
136+
Out.indent(Indent * 2) << "Kinds:";
137+
Out.PadToColumn(Pad);
138+
llvm::interleaveComma(KernelInfo.Args.Kinds, Out, [&Out](auto Kind) {
139+
auto KindInt = static_cast<unsigned>(Kind);
140+
Out << (KindInt < NumParameterKinds ? ParameterKindStrings[KindInt]
141+
: InvalidParameterKindString);
142+
});
143+
Out << '\n';
144+
145+
Out.indent(Indent * 2) << "Mask:";
146+
Out.PadToColumn(Pad);
147+
llvm::interleaveComma(KernelInfo.Args.UsageMask, Out, [&Out](auto Mask) {
148+
Out << static_cast<unsigned>(Mask);
149+
});
150+
Out << '\n';
151+
152+
if (KernelInfo.Attributes.empty()) {
153+
continue;
154+
}
155+
156+
Out.indent(Indent) << "Attributes:\n";
157+
for (const auto &AttrInfo : KernelInfo.Attributes) {
158+
Out.indent(Indent * 2) << AttrInfo.AttributeName << ':';
159+
Out.PadToColumn(Pad);
160+
llvm::interleaveComma(AttrInfo.Values, Out);
161+
Out << '\n';
162+
}
163+
}
164+
64165
return PreservedAnalyses::all();
65166
}

sycl-fusion/passes/kernel-info/SYCLKernelInfo.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,20 @@ class SYCLModuleInfoAnalysis
2222
public:
2323
static llvm::AnalysisKey Key;
2424

25+
constexpr static llvm::StringLiteral ModuleInfoMDKey{"sycl.moduleinfo"};
26+
2527
SYCLModuleInfoAnalysis(
2628
std::unique_ptr<jit_compiler::SYCLModuleInfo> Info = nullptr)
2729
: ModuleInfo{std::move(Info)} {}
2830

2931
struct Result {
3032
jit_compiler::SYCLModuleInfo *ModuleInfo;
3133
};
32-
Result run(llvm::Module &, llvm::ModuleAnalysisManager &);
34+
Result run(llvm::Module &M, llvm::ModuleAnalysisManager &);
3335

3436
private:
3537
void loadModuleInfoFromFile();
38+
void loadModuleInfoFromMetadata(llvm::Module &M);
3639

3740
std::unique_ptr<jit_compiler::SYCLModuleInfo> ModuleInfo;
3841
};

sycl-fusion/passes/metadata/MDParsing.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
namespace llvm {
1313
template <typename T> inline Expected<T> metadataToUInt(const Metadata *MD) {
1414
if (auto *C = dyn_cast<ConstantAsMetadata>(MD)) {
15-
return C->getValue()->getUniqueInteger().getZExtValue();
15+
return static_cast<T>(C->getValue()->getUniqueInteger().getZExtValue());
1616
}
1717
{
1818
std::string Msg{"Invalid metadata format: "};

sycl-fusion/test/internalization/abort-kernel-info.yaml

Lines changed: 0 additions & 11 deletions
This file was deleted.

sycl-fusion/test/internalization/abort-promote-call.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; RUN: opt -load-pass-plugin %shlibdir/SYCLKernelFusion%shlibext \
2-
; RUN: -passes=sycl-internalization --sycl-info-path %S/abort-kernel-info.yaml -S %s | FileCheck %s
2+
; RUN: -passes=sycl-internalization -S %s | FileCheck %s
33

44
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024"
55
target triple = "spir64-unknown-unknown"

sycl-fusion/test/internalization/abort-promote-stored-ptr.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; RUN: opt -load-pass-plugin %shlibdir/SYCLKernelFusion%shlibext\
2-
; RUN: -passes=sycl-internalization --sycl-info-path %S/abort-kernel-info.yaml -S %s | FileCheck %s
2+
; RUN: -passes=sycl-internalization -S %s | FileCheck %s
33

44
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024"
55
target triple = "spir64-unknown-unknown"

sycl-fusion/test/internalization/promote-local-nested.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; RUN: opt -load-pass-plugin %shlibdir/SYCLKernelFusion%shlibext \
2-
; RUN: -passes=sycl-internalization --sycl-info-path %S/../kernel-fusion/kernel-info.yaml -S %s | FileCheck %s
2+
; RUN: -passes=sycl-internalization -S %s | FileCheck %s
33

44
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024"
55
target triple = "spir64-unknown-unknown"

sycl-fusion/test/internalization/promote-local-scalar.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; RUN: opt -load-pass-plugin %shlibdir/SYCLKernelFusion%shlibext\
2-
; RUN: -passes=sycl-internalization --sycl-info-path %S/../kernel-fusion/kernel-info.yaml -S %s | FileCheck %s
2+
; RUN: -passes=sycl-internalization -S %s | FileCheck %s
33

44
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024"
55
target triple = "spir64-unknown-unknown"

sycl-fusion/test/internalization/promote-local-vec.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; RUN: opt -load-pass-plugin %shlibdir/SYCLKernelFusion%shlibext\
2-
; RUN: -passes=sycl-internalization --sycl-info-path %S/../kernel-fusion/kernel-info.yaml -S %s | FileCheck %s
2+
; RUN: -passes=sycl-internalization -S %s | FileCheck %s
33

44
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024"
55
target triple = "spir64-unknown-unknown"

0 commit comments

Comments
 (0)