Skip to content

Commit c451ac3

Browse files
mdtoguchibader
authored andcommitted
[SYCL] Expanded Ahead Of Time Compilation support
Adds support for AOT compilation in a single pass. Support is triggered by using a sub architecture value in the triple. The following 2 are supported: spir64_fpga, spir64_gen When one of these are used, the respective backend compiler (aoc, ocloc) is invoked to perform the AOT compilation. That device binary is then wrapped and included in the final binary. Additional options can also be added to the SYCL device compilation, the Backend compile or the device link. These are handled by -Xsycl-target-frontend, -Xsycl-target-backend or -Xsycl-target-linker respectively Example command lines: FPGA: clang++ -fsycl -fsycl-targets=spir64_fpga-unknown-linux-sycldevice testfile.cpp -Xsycl-target-backend "-DFOO" GEN: clang++ -fsycl -fsycl-targets=spir64_gen-unknown-linux-sycldevice testfile.cpp -Xsycl-target-backend "-device skl" Signed-off-by: Michael D Toguchi <[email protected]>
1 parent e5a215e commit c451ac3

File tree

13 files changed

+462
-50
lines changed

13 files changed

+462
-50
lines changed

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,9 @@ def err_drv_Xopenmp_target_missing_triple : Error<
104104
def err_drv_invalid_Xopenmp_target_with_args : Error<
105105
"invalid -Xopenmp-target argument: '%0', options requiring arguments are unsupported">;
106106
def err_drv_Xsycl_target_missing_triple : Error<
107-
"cannot deduce implicit triple value for -Xsycl-target, specify triple using -Xsycl-target=<triple>">;
108-
def err_drv_invalid_Xsycl_target_with_args : Error<
109-
"invalid -Xsycl-target argument: '%0', options requiring arguments are unsupported">;
107+
"cannot deduce implicit triple value for '%0', specify triple using '%0=<triple>'">;
108+
def err_drv_invalid_Xsycl_frontend_with_args : Error<
109+
"invalid -Xsycl-target-frontend argument: '%0', options requiring arguments are unsupported">;
110110
def err_drv_argument_only_allowed_with : Error<
111111
"invalid argument '%0' only allowed with '%1'">;
112112
def err_drv_argument_not_allowed_with : Error<

clang/include/clang/Driver/Action.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,10 @@ class Action {
7373
OffloadUnbundlingJobClass,
7474
OffloadWrappingJobClass,
7575
SPIRVTranslatorJobClass,
76+
BackendCompileJobClass,
7677

7778
JobClassFirst = PreprocessJobClass,
78-
JobClassLast = SPIRVTranslatorJobClass
79+
JobClassLast = BackendCompileJobClass
7980
};
8081

8182
// The offloading kind determines if this action is binded to a particular
@@ -638,6 +639,17 @@ class SPIRVTranslatorJobAction : public JobAction {
638639
}
639640
};
640641

642+
class BackendCompileJobAction : public JobAction {
643+
void anchor() override;
644+
645+
public:
646+
BackendCompileJobAction(Action *Input, types::ID OutputType);
647+
648+
static bool classof(const Action *A) {
649+
return A->getKind() == BackendCompileJobClass;
650+
}
651+
};
652+
641653
} // namespace driver
642654
} // namespace clang
643655

clang/include/clang/Driver/Options.td

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -472,10 +472,20 @@ def Xopenmp_target : Separate<["-"], "Xopenmp-target">,
472472
def Xopenmp_target_EQ : JoinedAndSeparate<["-"], "Xopenmp-target=">,
473473
HelpText<"Pass <arg> to the target offloading toolchain identified by <triple>.">,
474474
MetaVarName<"<triple> <arg>">;
475-
def Xsycl_target : Separate<["-"], "Xsycl-target">,
476-
HelpText<"Pass <arg> to the SYCL based target offloading toolchain.">, MetaVarName<"<arg>">;
477-
def Xsycl_target_EQ : JoinedAndSeparate<["-"], "Xsycl-target=">,
478-
HelpText<"Pass <arg> to the SYCL based target offloading toolchain identified by <triple>.">,
475+
def Xsycl_backend : Separate<["-"], "Xsycl-target-backend">,
476+
HelpText<"Pass <arg> to the SYCL based target backend.">, MetaVarName<"<arg>">;
477+
def Xsycl_backend_EQ : JoinedAndSeparate<["-"], "Xsycl-target-backend=">,
478+
HelpText<"Pass <arg> to the SYCL based backend identified by <triple>.">,
479+
MetaVarName<"<triple> <arg>">;
480+
def Xsycl_frontend : Separate<["-"], "Xsycl-target-frontend">,
481+
HelpText<"Pass <arg> to the SYCL based target frontend.">, MetaVarName<"<arg>">;
482+
def Xsycl_frontend_EQ : JoinedAndSeparate<["-"], "Xsycl-target-frontend=">,
483+
HelpText<"Pass <arg> to the SYCL based target frontend identified by <triple>.">,
484+
MetaVarName<"<triple> <arg>">;
485+
def Xsycl_linker : Separate<["-"], "Xsycl-target-linker">,
486+
HelpText<"Pass <arg> to the SYCL based target linker.">, MetaVarName<"<arg>">;
487+
def Xsycl_linker_EQ : JoinedAndSeparate<["-"], "Xsycl-target-linker=">,
488+
HelpText<"Pass <arg> to the SYCL based target linker identified by <triple>.">,
479489
MetaVarName<"<triple> <arg>">;
480490
def z : Separate<["-"], "z">, Flags<[LinkerInput, RenderAsInput]>,
481491
HelpText<"Pass -z <arg> to the linker">, MetaVarName<"<arg>">,

clang/include/clang/Driver/ToolChain.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ class ToolChain {
139139
mutable std::unique_ptr<Tool> OffloadBundler;
140140
mutable std::unique_ptr<Tool> OffloadWrapper;
141141
mutable std::unique_ptr<Tool> SPIRVTranslator;
142+
mutable std::unique_ptr<Tool> BackendCompiler;
142143

143144
Tool *getClang() const;
144145
Tool *getAssemble() const;
@@ -147,6 +148,7 @@ class ToolChain {
147148
Tool *getOffloadBundler() const;
148149
Tool *getOffloadWrapper() const;
149150
Tool *getSPIRVTranslator() const;
151+
Tool *getBackendCompiler() const;
150152

151153
mutable std::unique_ptr<SanitizerArgs> SanitizerArguments;
152154
mutable std::unique_ptr<XRayArgs> XRayArguments;
@@ -170,6 +172,7 @@ class ToolChain {
170172

171173
virtual Tool *buildAssembler() const;
172174
virtual Tool *buildLinker() const;
175+
virtual Tool *buildBackendCompiler() const;
173176
virtual Tool *getTool(Action::ActionClass AC) const;
174177

175178
/// \name Utilities for implementing subclasses.

clang/lib/Driver/Action.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ const char *Action::getClassName(ActionClass AC) {
4444
return "clang-offload-wrapper";
4545
case SPIRVTranslatorJobClass:
4646
return "llvm-spirv";
47+
case BackendCompileJobClass:
48+
return "backend-compiler";
4749
}
4850

4951
llvm_unreachable("invalid class");
@@ -423,3 +425,9 @@ void SPIRVTranslatorJobAction::anchor() {}
423425
SPIRVTranslatorJobAction::SPIRVTranslatorJobAction(Action *Input,
424426
types::ID Type)
425427
: JobAction(SPIRVTranslatorJobClass, Input, Type) {}
428+
429+
void BackendCompileJobAction::anchor() {}
430+
431+
BackendCompileJobAction::BackendCompileJobAction(Action *Input,
432+
types::ID Type)
433+
: JobAction(BackendCompileJobClass, Input, Type) {}

clang/lib/Driver/Compilation.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ Compilation::getArgsForToolChain(const ToolChain *TC, StringRef BoundArch,
6969
SmallVector<Arg *, 4> AllocatedArgs;
7070
DerivedArgList *OffloadArgs = nullptr;
7171
// Translate offload toolchain arguments provided via the -Xopenmp-target
72-
// or -Xsycl-target flags.
72+
// or -Xsycl-target-frontend flags.
7373
if (DeviceOffloadKind == Action::OFK_OpenMP ||
7474
DeviceOffloadKind == Action::OFK_SYCL) {
7575
const ToolChain *HostTC = getSingleOffloadToolChain<Action::OFK_Host>();

clang/lib/Driver/Driver.cpp

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3023,6 +3023,10 @@ class OffloadingActionBuilder final {
30233023
/// The compiler inputs obtained for each toolchain
30243024
Action * DeviceCompilerInput = nullptr;
30253025

3026+
/// List of offload device triples needed to track for different toolchain
3027+
/// construction
3028+
SmallVector<llvm::Triple, 4> SYCLTripleList;
3029+
30263030
public:
30273031
SYCLActionBuilder(Compilation &C, DerivedArgList &Args,
30283032
const Driver::InputList &Inputs)
@@ -3087,6 +3091,7 @@ class OffloadingActionBuilder final {
30873091
// We avoid creating host action in device-only mode.
30883092
return ABRT_Ignore_Host;
30893093
}
3094+
30903095
// We passed the device action as a host dependence, so we don't need to
30913096
// do anything else with them.
30923097
SYCLDeviceActions.clear();
@@ -3188,17 +3193,37 @@ class OffloadingActionBuilder final {
31883193
if (SYCLAOTInputs.empty()) {
31893194
// Append a new link action for each device.
31903195
auto TC = ToolChains.begin();
3196+
3197+
unsigned I = 0;
31913198
for (auto &LI : DeviceLinkerInputs) {
31923199
auto *DeviceLinkAction =
3193-
C.MakeAction<LinkJobAction>(LI, types::TY_Image);
3200+
C.MakeAction<LinkJobAction>(LI, types::TY_SPIRV);
3201+
auto TT = SYCLTripleList[I];
3202+
bool SYCLAOTCompile = (TT.getSubArch() != llvm::Triple::NoSubArch &&
3203+
(TT.getSubArch() == llvm::Triple::SPIRSubArch_fpga ||
3204+
TT.getSubArch() == llvm::Triple::SPIRSubArch_gen));
31943205

31953206
// After the Link, wrap the files before the final host link
3196-
auto *DeviceWrappingAction =
3207+
if (SYCLAOTCompile) {
3208+
// Do the additional Ahead of Time compilation when the specific
3209+
// triple calls for it (provided a valid subarch).
3210+
auto *DeviceBECompileAction =
3211+
C.MakeAction<BackendCompileJobAction>(DeviceLinkAction,
3212+
types::TY_Image);
3213+
auto *DeviceWrappingAction =
3214+
C.MakeAction<OffloadWrappingJobAction>(DeviceBECompileAction,
3215+
types::TY_Object);
3216+
DA.add(*DeviceWrappingAction, **TC, /*BoundArch=*/nullptr,
3217+
Action::OFK_SYCL);
3218+
} else {
3219+
auto *DeviceWrappingAction =
31973220
C.MakeAction<OffloadWrappingJobAction>(DeviceLinkAction,
31983221
types::TY_Object);
3199-
DA.add(*DeviceWrappingAction, **TC, /*BoundArch=*/nullptr,
3200-
Action::OFK_SYCL);
3222+
DA.add(*DeviceWrappingAction, **TC, /*BoundArch=*/nullptr,
3223+
Action::OFK_SYCL);
3224+
}
32013225
++TC;
3226+
++I;
32023227
}
32033228
} else {
32043229
// Perform additional wraps against -fsycl-add-targets
@@ -3263,6 +3288,41 @@ class OffloadingActionBuilder final {
32633288
}
32643289
}
32653290
}
3291+
// Gather information about the SYCL Ahead of Time targets. The targets
3292+
// are determined on the SubArch values passed along in the triple.
3293+
// The SubArch information for SYCL offload is not used during the
3294+
// compilation and is only used to determine additional compilation steps
3295+
// needed in the driver toolchain.
3296+
Arg *SYCLTargets =
3297+
C.getInputArgs().getLastArg(options::OPT_fsycl_targets_EQ);
3298+
bool HasValidSYCLRuntime = C.getInputArgs().hasFlag(options::OPT_fsycl,
3299+
options::OPT_fno_sycl, false);
3300+
if (SYCLTargets) {
3301+
llvm::StringMap<const char *> FoundNormalizedTriples;
3302+
for (const char *Val : SYCLTargets->getValues()) {
3303+
llvm::Triple TT(Val);
3304+
std::string NormalizedName = TT.normalize();
3305+
3306+
// Make sure we don't have a duplicate triple.
3307+
auto Duplicate = FoundNormalizedTriples.find(NormalizedName);
3308+
if (Duplicate != FoundNormalizedTriples.end())
3309+
continue;
3310+
3311+
// Store the current triple so that we can check for duplicates in
3312+
// the following iterations.
3313+
FoundNormalizedTriples[NormalizedName] = Val;
3314+
3315+
SYCLTripleList.push_back(TT);
3316+
}
3317+
} else if (HasValidSYCLRuntime) {
3318+
// Only -fsycl is provided without -fsycl-targets.
3319+
llvm::Triple TT;
3320+
TT.setArch(llvm::Triple::spir64);
3321+
TT.setVendor(llvm::Triple::UnknownVendor);
3322+
TT.setOS(llvm::Triple(llvm::sys::getProcessTriple()).getOS());
3323+
TT.setEnvironment(llvm::Triple::SYCLDevice);
3324+
SYCLTripleList.push_back(TT);
3325+
}
32663326

32673327
DeviceLinkerInputs.resize(ToolChains.size());
32683328
return false;

clang/lib/Driver/ToolChain.cpp

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,10 @@ Tool *ToolChain::buildLinker() const {
272272
llvm_unreachable("Linking is not supported by this toolchain");
273273
}
274274

275+
Tool *ToolChain::buildBackendCompiler() const {
276+
llvm_unreachable("Backend Compilation is not supported by this toolchain");
277+
}
278+
275279
Tool *ToolChain::getAssemble() const {
276280
if (!Assemble)
277281
Assemble.reset(buildAssembler());
@@ -308,6 +312,12 @@ Tool *ToolChain::getSPIRVTranslator() const {
308312
return SPIRVTranslator.get();
309313
}
310314

315+
Tool *ToolChain::getBackendCompiler() const {
316+
if (!BackendCompiler)
317+
BackendCompiler.reset(buildBackendCompiler());
318+
return BackendCompiler.get();
319+
}
320+
311321
Tool *ToolChain::getTool(Action::ActionClass AC) const {
312322
switch (AC) {
313323
case Action::AssembleJobClass:
@@ -343,6 +353,9 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const {
343353

344354
case Action::SPIRVTranslatorJobClass:
345355
return getSPIRVTranslator();
356+
357+
case Action::BackendCompileJobClass:
358+
return getBackendCompiler();
346359
}
347360

348361
llvm_unreachable("Invalid tool kind.");
@@ -979,7 +992,7 @@ llvm::opt::DerivedArgList *ToolChain::TranslateOffloadTargetArgs(
979992
const OptTable &Opts = getDriver().getOpts();
980993
bool Modified = false;
981994

982-
// Handle -Xopenmp-target and -Xsycl-target flags
995+
// Handle -Xopenmp-target and -Xsycl-target-frontend flags
983996
for (auto *A : Args) {
984997
// Exclude flags which may only apply to the host toolchain.
985998
// Do not exclude flags when the host triple (AuxTriple)
@@ -1023,15 +1036,15 @@ llvm::opt::DerivedArgList *ToolChain::TranslateOffloadTargetArgs(
10231036
}
10241037
} else if (DeviceOffloadKind == Action::OFK_SYCL) {
10251038
XOffloadTargetNoTriple =
1026-
A->getOption().matches(options::OPT_Xsycl_target);
1027-
if (A->getOption().matches(options::OPT_Xsycl_target_EQ)) {
1028-
// Passing device args: -Xsycl-target=<triple> -opt=val.
1039+
A->getOption().matches(options::OPT_Xsycl_frontend);
1040+
if (A->getOption().matches(options::OPT_Xsycl_frontend_EQ)) {
1041+
// Passing device args: -Xsycl-target-frontend=<triple> -opt=val.
10291042
if (A->getValue(0) == getTripleString())
10301043
Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
10311044
else
10321045
continue;
10331046
} else if (XOffloadTargetNoTriple) {
1034-
// Passing device args: -Xsycl-target -opt=val.
1047+
// Passing device args: -Xsycl-target-frontend -opt=val.
10351048
Index = Args.getBaseArgs().MakeIndex(A->getValue(0));
10361049
} else {
10371050
DAL->append(A);
@@ -1047,7 +1060,7 @@ llvm::opt::DerivedArgList *ToolChain::TranslateOffloadTargetArgs(
10471060
getDriver().Diag(diag::err_drv_invalid_Xopenmp_target_with_args)
10481061
<< A->getAsString(Args);
10491062
} else {
1050-
getDriver().Diag(diag::err_drv_invalid_Xsycl_target_with_args)
1063+
getDriver().Diag(diag::err_drv_invalid_Xsycl_frontend_with_args)
10511064
<< A->getAsString(Args);
10521065
}
10531066
continue;
@@ -1060,8 +1073,9 @@ llvm::opt::DerivedArgList *ToolChain::TranslateOffloadTargetArgs(
10601073
getDriver().Diag(diag::err_drv_Xopenmp_target_missing_triple);
10611074
continue;
10621075
} else if (DeviceOffloadKind == Action::OFK_SYCL &&
1063-
Args.getAllArgValues(options::OPT_fsycl_targets_EQ).size() != 1) {
1064-
getDriver().Diag(diag::err_drv_Xsycl_target_missing_triple);
1076+
Args.getAllArgValues(options::OPT_fsycl_targets_EQ).size() > 1) {
1077+
getDriver().Diag(diag::err_drv_Xsycl_target_missing_triple)
1078+
<< A->getSpelling();
10651079
continue;
10661080
}
10671081
}

0 commit comments

Comments
 (0)