Skip to content

Commit 4d58f01

Browse files
committed
Add kernel property to propagate compile options to backend
Signed-off-by: Arvind Sudarsanam <[email protected]>
1 parent 6dbeb2e commit 4d58f01

File tree

10 files changed

+177
-15
lines changed

10 files changed

+177
-15
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,12 +1309,12 @@ def SYCLType: InheritableAttr {
13091309
"specialization_id", "kernel_handler", "buffer_location",
13101310
"no_alias", "accessor_property_list", "group",
13111311
"private_memory", "aspect", "annotated_ptr", "annotated_arg",
1312-
"stream", "sampler"],
1312+
"compile_options", "stream", "sampler"],
13131313
["accessor", "local_accessor", "spec_constant",
13141314
"specialization_id", "kernel_handler", "buffer_location",
13151315
"no_alias", "accessor_property_list", "group",
13161316
"private_memory", "aspect", "annotated_ptr", "annotated_arg",
1317-
"stream", "sampler"]>];
1317+
"compile_options", "stream", "sampler"]>];
13181318
// Only used internally by SYCL implementation
13191319
let Documentation = [InternalOnly];
13201320
}
@@ -1328,6 +1328,15 @@ def SYCLDeviceHas : InheritableAttr {
13281328
let SupportsNonconformingLambdaSyntax = 1;
13291329
}
13301330

1331+
def SYCLDeviceCompileOptions : InheritableAttr {
1332+
let Spellings = [CXX11<"sycl", "device_compile_options">];
1333+
let Subjects = SubjectList<[Function], ErrorDiag>;
1334+
let Args = [VariadicExprArgument<"DeviceCompileOptions">];
1335+
let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost];
1336+
// Only used internally by SYCL implementation
1337+
let Documentation = [InternalOnly];
1338+
}
1339+
13311340
def SYCLUsesAspects : InheritableAttr {
13321341
let Spellings = [CXX11<"__sycl_detail__", "__uses_aspects__">];
13331342
let Subjects = SubjectList<[CXXRecord, Function], ErrorDiag>;

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -582,11 +582,23 @@ void CodeGenFunction::EmitKernelMetadata(const FunctionDecl *FD,
582582
&& !FD->hasAttr<SYCLDeviceAttr>())
583583
return;
584584

585-
// TODO Module identifier is not reliable for this purpose since two modules
586-
// can have the same ID, needs improvement
587-
if (getLangOpts().SYCLIsDevice)
585+
586+
if (getLangOpts().SYCLIsDevice) {
587+
// TODO Module identifier is not reliable for this purpose since two modules
588+
// can have the same ID, needs improvement
588589
Fn->addFnAttr("sycl-module-id", Fn->getParent()->getModuleIdentifier());
589-
590+
int SYCLDeviceCompileOptLevel;
591+
switch (CGM.getCodeGenOpts().OptimizationLevel) {
592+
default:
593+
llvm_unreachable("Invalid optimization level!");
594+
case 0:
595+
case 1:
596+
case 2:
597+
case 3:
598+
SYCLDeviceCompileOptLevel = CGM.getCodeGenOpts().OptimizationLevel;
599+
}
600+
Fn->addFnAttr("sycl-device-compile-optlevel", std::to_string(SYCLDeviceCompileOptLevel));
601+
}
590602
llvm::LLVMContext &Context = getLLVMContext();
591603

592604
if (FD->hasAttr<OpenCLKernelAttr>() || FD->hasAttr<CUDAGlobalAttr>())

llvm/tools/sycl-post-link/CompileTimePropertiesPass.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,10 @@ attributeToExecModeMetadata(Module &M, const Attribute &Attr) {
208208
MDNode::get(Ctx, MD));
209209
}
210210

211+
if (AttrKindStr == "sycl-device-compile-options") {
212+
auto Opt = Attr.getValueAsString();
213+
llvm::errs() << "ARV: Opt is -O" << Opt << "\n";
214+
}
211215
return None;
212216
}
213217

llvm/tools/sycl-post-link/sycl-post-link.cpp

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ cl::OptionCategory PostLinkCat{"sycl-post-link options"};
8989
// clang/lib/Driver/Driver.cpp, sycl-post-link.cpp, ClangOffloadWrapper.cpp
9090
constexpr char COL_CODE[] = "Code";
9191
constexpr char COL_SYM[] = "Symbols";
92+
constexpr char COL_OPTS[] = "Options";
9293
constexpr char COL_PROPS[] = "Properties";
9394

9495
// InputFilename - The filename to read from.
@@ -215,10 +216,11 @@ struct GlobalBinImageProps {
215216
bool EmitDeviceGlobalPropSet;
216217
};
217218

218-
struct IrPropSymFilenameTriple {
219+
struct IrPropSymFilenameQuad {
219220
std::string Ir;
220221
std::string Prop;
221222
std::string Sym;
223+
std::string Opt;
222224
};
223225

224226
void writeToFile(const std::string &Filename, const std::string &Content) {
@@ -466,6 +468,44 @@ std::string saveModuleProperties(module_split::ModuleDesc &MD,
466468
return SCFile;
467469
}
468470

471+
std::string getOptString(module_split::ModuleDesc &MD) {
472+
auto &M = MD.getModule();
473+
// Process all properties on kernels.
474+
for (Function &F : M) {
475+
// Only consider kernels.
476+
if (F.getCallingConv() != CallingConv::SPIR_KERNEL)
477+
continue;
478+
479+
SmallVector<Metadata *, 8> MDOps;
480+
SmallVector<std::pair<std::string, MDNode *>, 8> NamedMDOps;
481+
for (const Attribute &Attr : F.getAttributes().getFnAttrs()) {
482+
// Currently, only string attributes are supported
483+
if (!Attr.isStringAttribute())
484+
continue;
485+
StringRef AttrKindStr = Attr.getKindAsString();
486+
if (AttrKindStr == "sycl-device-compile-optlevel") {
487+
auto Opt = "-O" + Attr.getValueAsString();
488+
llvm::errs() << "ARV: Opt is " << Opt << "\n";
489+
return Opt.str();
490+
}
491+
}
492+
}
493+
return "";
494+
}
495+
496+
std::string saveModuleOptions(module_split::ModuleDesc &MD,
497+
const std::string &Opts, int I,
498+
StringRef Suff) {
499+
std::error_code EC;
500+
std::string SCFile = makeResultFileName(".opt", I, Suff);
501+
raw_fd_ostream SCOut(SCFile, EC);
502+
checkError(EC, "error opening file '" + SCFile + "'");
503+
SCOut << Opts;
504+
505+
return SCFile;
506+
}
507+
508+
469509
// Saves specified collection of symbols to a file.
470510
std::string saveModuleSymbolTable(const module_split::EntryPointSet &Es, int I,
471511
StringRef Suffix) {
@@ -570,11 +610,11 @@ StringRef getModuleSuffix(const module_split::ModuleDesc &MD) {
570610
// @param IRFilename filename of already available IR component. If not empty,
571611
// IR component saving is skipped, and this file name is recorded as such in
572612
// the result.
573-
// @return a triple of files where IR, Property and Symbols components of the
574-
// Module descriptor are written respectively.
575-
IrPropSymFilenameTriple saveModule(module_split::ModuleDesc &MD, int I,
613+
// @return a quadruple of files where IR, Property, Symbols and Opts components
614+
// of the Module descriptor are written respectively.
615+
IrPropSymFilenameQuad saveModule(module_split::ModuleDesc &MD, int I,
576616
StringRef IRFilename = "") {
577-
IrPropSymFilenameTriple Res;
617+
IrPropSymFilenameQuad Res;
578618
StringRef Suffix = getModuleSuffix(MD);
579619

580620
if (!IRFilename.empty()) {
@@ -587,6 +627,9 @@ IrPropSymFilenameTriple saveModule(module_split::ModuleDesc &MD, int I,
587627
EmitExportedSymbols, DeviceGlobals};
588628
Res.Prop = saveModuleProperties(MD, Props, I, Suffix);
589629

630+
std::string Opts = getOptString(MD);
631+
Res.Opt = saveModuleOptions(MD, Opts, I, Suffix);
632+
590633
if (DoSymGen) {
591634
// save the names of the entry points - the symbol table
592635
Res.Sym = saveModuleSymbolTable(MD.entries(), I, Suffix);
@@ -631,20 +674,37 @@ bool processSpecConstants(module_split::ModuleDesc &MD) {
631674
return MD.Props.SpecConstsMet;
632675
}
633676

634-
constexpr int MAX_COLUMNS_IN_FILE_TABLE = 3;
677+
constexpr int MAX_COLUMNS_IN_FILE_TABLE = 4;
635678

679+
#if 0
636680
void addTableRow(util::SimpleTable &Table,
637-
const IrPropSymFilenameTriple &RowData) {
681+
const IrPropSymFilenameQuad &RowData) {
638682
SmallVector<StringRef, MAX_COLUMNS_IN_FILE_TABLE> Row;
639683

684+
for (const std::string *S : {&RowData.Ir, &RowData.Prop, &RowData.Opt, &RowData.Sym}) {
685+
if (!S->empty()) {
686+
Row.push_back(StringRef(*S));
687+
}
688+
}
689+
llvm::errs() << "ARV: " << static_cast<size_t>(Table.getNumColumns()) << "," << Row.size() <<"\n";
690+
assert(static_cast<size_t>(Table.getNumColumns()) == Row.size());
691+
Table.addRow(Row);
692+
}
693+
#else
694+
void addTableRow(util::SimpleTable &Table,
695+
const IrPropSymFilenameQuad &RowData) {
696+
SmallVector<StringRef, 3> Row;
697+
640698
for (const std::string *S : {&RowData.Ir, &RowData.Prop, &RowData.Sym}) {
641699
if (!S->empty()) {
642700
Row.push_back(StringRef(*S));
643701
}
644702
}
703+
//llvm::errs() << "ARV: " << static_cast<size_t>(Table.getNumColumns()) << "," << Row.size() <<"\n";
645704
assert(static_cast<size_t>(Table.getNumColumns()) == Row.size());
646705
Table.addRow(Row);
647706
}
707+
#endif
648708

649709
// Removes the global variable "llvm.used" and returns true on success.
650710
// "llvm.used" is a global constant array containing references to kernels
@@ -693,8 +753,13 @@ static bool removeSYCLKernelsConstRefArray(Module &M) {
693753
std::unique_ptr<util::SimpleTable>
694754
processInputModule(std::unique_ptr<Module> M) {
695755
// Construct the resulting table which will accumulate all the outputs.
756+
#if 0
757+
SmallVector<StringRef, MAX_COLUMNS_IN_FILE_TABLE> ColumnTitles{
758+
StringRef(COL_CODE), StringRef(COL_PROPS), StringRef(COL_OPTS)};
759+
#else
696760
SmallVector<StringRef, MAX_COLUMNS_IN_FILE_TABLE> ColumnTitles{
697761
StringRef(COL_CODE), StringRef(COL_PROPS)};
762+
#endif
698763

699764
if (DoSymGen) {
700765
ColumnTitles.push_back(COL_SYM);
@@ -869,7 +934,7 @@ processInputModule(std::unique_ptr<Module> M) {
869934
"have been made\n";
870935
}
871936
for (module_split::ModuleDesc &IrMD : MMs) {
872-
IrPropSymFilenameTriple T = saveModule(IrMD, ID, OutIRFileName);
937+
IrPropSymFilenameQuad T = saveModule(IrMD, ID, OutIRFileName);
873938
addTableRow(*Table, T);
874939
}
875940
}

sycl/include/sycl/compile_options.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//==---- compile_options.hpp - SYCL compile options Enums -----*- C++ -*---==//
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+
#pragma once
9+
10+
#include <sycl/detail/defines.hpp>
11+
12+
namespace sycl {
13+
__SYCL_INLINE_VER_NAMESPACE(_V1) {
14+
15+
#define __SYCL_COMPILE_OPTION(OPTION, ID) OPTION = ID,
16+
enum class __SYCL_TYPE(compile_options) compile_options {
17+
#include <sycl/info/compile_options.def>
18+
};
19+
#undef __SYCL_COMPILE_OPTION
20+
21+
} // __SYCL_INLINE_VER_NAMESPACE(_V1)
22+
} // namespace sycl

sycl/include/sycl/ext/oneapi/kernel_properties/properties.hpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#pragma once
1010

1111
#include <sycl/aspects.hpp>
12+
#include <sycl/compile_options.hpp>
1213
#include <sycl/ext/oneapi/properties/property.hpp>
1314
#include <sycl/ext/oneapi/properties/property_utils.hpp>
1415
#include <sycl/ext/oneapi/properties/property_value.hpp>
@@ -56,6 +57,12 @@ struct device_has_key {
5657
std::integral_constant<aspect, Aspects>...>;
5758
};
5859

60+
struct device_compile_options_key {
61+
template <compile_options... CompileOptions>
62+
using value_t = property_value<device_compile_options_key,
63+
std::integral_constant<compile_options, CompileOptions>...>;
64+
};
65+
5966
template <size_t Dim0, size_t... Dims>
6067
struct property_value<work_group_size_key, std::integral_constant<size_t, Dim0>,
6168
std::integral_constant<size_t, Dims>...> {
@@ -108,6 +115,14 @@ struct property_value<device_has_key,
108115
static constexpr std::array<aspect, sizeof...(Aspects)> value{Aspects...};
109116
};
110117

118+
template <compile_options... CompileOptions>
119+
struct property_value<device_compile_options_key,
120+
std::integral_constant<compile_options, CompileOptions>...> {
121+
using key_t = device_compile_options_key;
122+
static constexpr std::array<compile_options,
123+
sizeof...(CompileOptions)> value{CompileOptions...};
124+
};
125+
111126
template <size_t Dim0, size_t... Dims>
112127
inline constexpr work_group_size_key::value_t<Dim0, Dims...> work_group_size;
113128

@@ -121,11 +136,15 @@ inline constexpr sub_group_size_key::value_t<Size> sub_group_size;
121136
template <aspect... Aspects>
122137
inline constexpr device_has_key::value_t<Aspects...> device_has;
123138

139+
template <compile_options... CompileOptions>
140+
inline constexpr device_compile_options_key::value_t<CompileOptions...> device_compile_options;
141+
124142
template <> struct is_property_key<work_group_size_key> : std::true_type {};
125143
template <>
126144
struct is_property_key<work_group_size_hint_key> : std::true_type {};
127145
template <> struct is_property_key<sub_group_size_key> : std::true_type {};
128146
template <> struct is_property_key<device_has_key> : std::true_type {};
147+
template <> struct is_property_key<device_compile_options_key> : std::true_type {};
129148

130149
namespace detail {
131150
template <> struct PropertyToKind<work_group_size_key> {
@@ -140,6 +159,9 @@ template <> struct PropertyToKind<sub_group_size_key> {
140159
template <> struct PropertyToKind<device_has_key> {
141160
static constexpr PropKind Kind = PropKind::DeviceHas;
142161
};
162+
template <> struct PropertyToKind<device_compile_options_key> {
163+
static constexpr PropKind Kind = PropKind::DeviceCompileOptions;
164+
};
143165

144166
template <>
145167
struct IsCompileTimeProperty<work_group_size_key> : std::true_type {};
@@ -148,6 +170,7 @@ struct IsCompileTimeProperty<work_group_size_hint_key> : std::true_type {};
148170
template <>
149171
struct IsCompileTimeProperty<sub_group_size_key> : std::true_type {};
150172
template <> struct IsCompileTimeProperty<device_has_key> : std::true_type {};
173+
template <> struct IsCompileTimeProperty<device_compile_options_key> : std::true_type {};
151174

152175
template <size_t Dim0, size_t... Dims>
153176
struct PropertyMetaInfo<work_group_size_key::value_t<Dim0, Dims...>> {
@@ -170,6 +193,12 @@ struct PropertyMetaInfo<device_has_key::value_t<Aspects...>> {
170193
static constexpr const char *value =
171194
SizeListToStr<static_cast<size_t>(Aspects)...>::value;
172195
};
196+
template <compile_options... CompileOptions>
197+
struct PropertyMetaInfo<device_compile_options_key::value_t<CompileOptions...>> {
198+
static constexpr const char *name = "sycl-device-compile-options";
199+
static constexpr const char *value =
200+
SizeListToStr<static_cast<size_t>(CompileOptions)...>::value;
201+
};
173202

174203
template <typename T, typename = void>
175204
struct HasKernelPropertiesGetMethod : std::false_type {};

sycl/include/sycl/ext/oneapi/properties/property.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,9 @@ enum PropKind : uint32_t {
173173
WorkGroupSizeHint = 7,
174174
SubGroupSize = 8,
175175
DeviceHas = 9,
176+
DeviceCompileOptions = 10,
176177
// PropKindSize must always be the last value.
177-
PropKindSize = 10,
178+
PropKindSize = 11,
178179
};
179180

180181
// This trait must be specialized for all properties and must have a unique
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
__SYCL_COMPILE_OPTION(O0, 0)
2+
__SYCL_COMPILE_OPTION(O1, 1)
3+
__SYCL_COMPILE_OPTION(O2, 2)
4+
__SYCL_COMPILE_OPTION(O3, 3)

sycl/include/sycl/sycl.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#endif
2020
#include <sycl/buffer.hpp>
2121
#include <sycl/builtins.hpp>
22+
#include <sycl/compile_options.hpp>
2223
#include <sycl/context.hpp>
2324
#include <sycl/define_vendors.hpp>
2425
#include <sycl/device.hpp>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %clangxx -O0 -fsycl-device-only -S -Xclang -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK-IR
2+
// RUN: %clangxx -O0 -fsycl-device-only -Xclang -verify %s
3+
// expected-no-diagnostics
4+
// Tests for propagation of compile options
5+
6+
#include <sycl/sycl.hpp>
7+
8+
using namespace sycl;
9+
using namespace sycl::ext::oneapi::experimental;
10+
11+
int main() {
12+
queue Q;
13+
// CHECK-IR: spir_kernel void @{{.*}}Kernel0(){{.*}} #[[COAttr1:[0-9]+]]
14+
Q.single_task<class Kernel0>([]() {});
15+
}

0 commit comments

Comments
 (0)