Skip to content

Commit d37cadc

Browse files
committed
[SYCL] break out offload-wrapper step to allow usage for all sycl devices.
Address some review issues from the previous commit, and fix problem seen after latest pulldown with -fsycl Signed-off-by: Vladimir Lazarev <[email protected]>
1 parent 5e3005c commit d37cadc

File tree

14 files changed

+270
-85
lines changed

14 files changed

+270
-85
lines changed

clang/include/clang/Driver/Action.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,10 @@ class Action {
7272
VerifyPCHJobClass,
7373
OffloadBundlingJobClass,
7474
OffloadUnbundlingJobClass,
75+
OffloadWrappingJobClass,
7576

7677
JobClassFirst = PreprocessJobClass,
77-
JobClassLast = OffloadUnbundlingJobClass
78+
JobClassLast = OffloadWrappingJobClass
7879
};
7980

8081
// The offloading kind determines if this action is binded to a particular
@@ -615,6 +616,17 @@ class OffloadUnbundlingJobAction final : public JobAction {
615616
}
616617
};
617618

619+
class OffloadWrappingJobAction : public JobAction {
620+
void anchor() override;
621+
622+
public:
623+
OffloadWrappingJobAction(Action *Input, types::ID OutputType);
624+
625+
static bool classof(const Action *A) {
626+
return A->getKind() == OffloadWrappingJobClass;
627+
}
628+
};
629+
618630
} // namespace driver
619631
} // namespace clang
620632

clang/include/clang/Driver/ToolChain.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,14 @@ class ToolChain {
130130
mutable std::unique_ptr<Tool> Assemble;
131131
mutable std::unique_ptr<Tool> Link;
132132
mutable std::unique_ptr<Tool> OffloadBundler;
133+
mutable std::unique_ptr<Tool> OffloadWrapper;
133134

134135
Tool *getClang() const;
135136
Tool *getAssemble() const;
136137
Tool *getLink() const;
137138
Tool *getClangAs() const;
138139
Tool *getOffloadBundler() const;
140+
Tool *getOffloadWrapper() const;
139141

140142
mutable std::unique_ptr<SanitizerArgs> SanitizerArguments;
141143
mutable std::unique_ptr<XRayArgs> XRayArguments;

clang/lib/Driver/Action.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ const char *Action::getClassName(ActionClass AC) {
4141
return "clang-offload-bundler";
4242
case OffloadUnbundlingJobClass:
4343
return "clang-offload-unbundler";
44+
case OffloadWrappingJobClass:
45+
return "clang-offload-wrapper";
4446
}
4547

4648
llvm_unreachable("invalid class");
@@ -408,3 +410,9 @@ void OffloadUnbundlingJobAction::anchor() {}
408410

409411
OffloadUnbundlingJobAction::OffloadUnbundlingJobAction(Action *Input)
410412
: JobAction(OffloadUnbundlingJobClass, Input, Input->getType()) {}
413+
414+
void OffloadWrappingJobAction::anchor() {}
415+
416+
OffloadWrappingJobAction::OffloadWrappingJobAction(Action *Input,
417+
types::ID Type)
418+
: JobAction(OffloadWrappingJobClass, Input, Type) {}

clang/lib/Driver/Compilation.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,27 +68,27 @@ Compilation::getArgsForToolChain(const ToolChain *TC, StringRef BoundArch,
6868
DerivedArgList *&Entry = TCArgs[{TC, BoundArch, DeviceOffloadKind}];
6969
if (!Entry) {
7070
SmallVector<Arg *, 4> AllocatedArgs;
71-
DerivedArgList *OpenMPArgs = nullptr;
72-
// Translate OpenMP toolchain arguments provided via the -Xopenmp-target
71+
DerivedArgList *OffloadArgs = nullptr;
72+
// Translate offload toolchain arguments provided via the -Xopenmp-target
7373
// or -Xsycl-target flags.
7474
if (DeviceOffloadKind == Action::OFK_OpenMP ||
7575
DeviceOffloadKind == Action::OFK_SYCL) {
7676
const ToolChain *HostTC = getSingleOffloadToolChain<Action::OFK_Host>();
7777
bool SameTripleAsHost = (TC->getTriple() == HostTC->getTriple());
78-
OpenMPArgs = TC->TranslateOffloadTargetArgs(
78+
OffloadArgs = TC->TranslateOffloadTargetArgs(
7979
*TranslatedArgs, SameTripleAsHost, AllocatedArgs, DeviceOffloadKind);
8080
}
8181

82-
if (!OpenMPArgs) {
82+
if (!OffloadArgs) {
8383
Entry = TC->TranslateArgs(*TranslatedArgs, BoundArch, DeviceOffloadKind);
8484
if (!Entry)
8585
Entry = TranslatedArgs;
8686
} else {
87-
Entry = TC->TranslateArgs(*OpenMPArgs, BoundArch, DeviceOffloadKind);
87+
Entry = TC->TranslateArgs(*OffloadArgs, BoundArch, DeviceOffloadKind);
8888
if (!Entry)
89-
Entry = OpenMPArgs;
89+
Entry = OffloadArgs;
9090
else
91-
delete OpenMPArgs;
91+
delete OffloadArgs;
9292
}
9393

9494
// Add allocated arguments to the final DAL.

clang/lib/Driver/Driver.cpp

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -698,15 +698,15 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
698698
// SYCL
699699
//
700700
// We need to generate a SYCL toolchain if the user specified targets with
701-
// the -fsycl-targets option.
701+
// the -fsycl-targets option. If -fsycl is supplied without -fsycl-targets
702+
// we will assume SPIR-V
703+
bool HasValidSYCLRuntime = C.getInputArgs().hasFlag(options::OPT_fsycl,
704+
options::OPT_fno_sycl, false);
702705
if (Arg *SYCLTargets =
703706
C.getInputArgs().getLastArg(options::OPT_fsycl_targets_EQ)) {
704707
if (SYCLTargets->getNumValues()) {
705708
// We expect that -fsycl-targets is always used in conjunction with the
706709
// -fsycl option
707-
bool HasValidSYCLRuntime = C.getInputArgs().hasFlag(
708-
options::OPT_fsycl, options::OPT_fno_sycl, false);
709-
710710
if (HasValidSYCLRuntime) {
711711
llvm::StringMap<const char *> FoundNormalizedTriples;
712712
for (const char *Val : SYCLTargets->getValues()) {
@@ -747,6 +747,27 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
747747
} else
748748
Diag(clang::diag::warn_drv_empty_joined_argument)
749749
<< SYCLTargets->getAsString(C.getInputArgs());
750+
} else {
751+
// If -fsycl is supplied without -fsycl-targets we will assume SPIR-V
752+
if (HasValidSYCLRuntime) {
753+
const ToolChain *HostTC =
754+
C.getSingleOffloadToolChain<Action::OFK_Host>();
755+
const llvm::Triple &HostTriple = HostTC->getTriple();
756+
llvm::Triple TT(TargetTriple);
757+
TT.setArch(llvm::Triple::spir64);
758+
TT.setVendor(llvm::Triple::UnknownVendor);
759+
TT.setOS(llvm::Triple(llvm::sys::getProcessTriple()).getOS());
760+
TT.setEnvironment(llvm::Triple::SYCLDevice);
761+
// Use the SYCL and host triples as the key into the ToolChains map,
762+
// because the device toolchain we create depends on both.
763+
auto &SYCLTC = ToolChains[(TT.normalize() + Twine("/") +
764+
HostTriple.normalize()).str()];
765+
if (!SYCLTC) {
766+
SYCLTC = llvm::make_unique<toolchains::SYCLToolChain>(
767+
*this, TT, *HostTC, C.getInputArgs());
768+
}
769+
C.addOffloadDeviceToolChain(SYCLTC.get(), Action::OFK_SYCL);
770+
}
750771
}
751772

752773
//
@@ -2942,7 +2963,7 @@ class OffloadingActionBuilder final {
29422963
// The host depends on the generated integrated header from the device
29432964
// compilation.
29442965
if (CurPhase == phases::Compile) {
2945-
for (Action *&A : SYCLDeviceActions) {
2966+
for (Action *&A : SYCLDeviceActions) {
29462967
DeviceCompilerInput =
29472968
C.MakeAction<CompileJobAction>(A, types::TY_SYCL_Header);
29482969
}
@@ -3032,7 +3053,12 @@ class OffloadingActionBuilder final {
30323053
for (auto &LI : DeviceLinkerInputs) {
30333054
auto *DeviceLinkAction =
30343055
C.MakeAction<LinkJobAction>(LI, types::TY_Image);
3035-
DA.add(*DeviceLinkAction, **TC, /*BoundArch=*/nullptr,
3056+
3057+
// After the Link, wrap the files before the final host link
3058+
auto *DeviceWrappingAction =
3059+
C.MakeAction<OffloadWrappingJobAction>(DeviceLinkAction,
3060+
types::TY_Object);
3061+
DA.add(*DeviceWrappingAction, **TC, /*BoundArch=*/nullptr,
30363062
Action::OFK_SYCL);
30373063
++TC;
30383064
}

clang/lib/Driver/ToolChain.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,12 @@ Tool *ToolChain::getOffloadBundler() const {
286286
return OffloadBundler.get();
287287
}
288288

289+
Tool *ToolChain::getOffloadWrapper() const {
290+
if (!OffloadWrapper)
291+
OffloadWrapper.reset(new tools::OffloadWrapper(*this));
292+
return OffloadWrapper.get();
293+
}
294+
289295
Tool *ToolChain::getTool(Action::ActionClass AC) const {
290296
switch (AC) {
291297
case Action::AssembleJobClass:
@@ -315,6 +321,9 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const {
315321
case Action::OffloadBundlingJobClass:
316322
case Action::OffloadUnbundlingJobClass:
317323
return getOffloadBundler();
324+
325+
case Action::OffloadWrappingJobClass:
326+
return getOffloadWrapper();
318327
}
319328

320329
llvm_unreachable("Invalid tool kind.");
@@ -931,7 +940,9 @@ llvm::opt::DerivedArgList *ToolChain::TranslateOffloadTargetArgs(
931940
unsigned Index;
932941
unsigned Prev;
933942
bool XOffloadTargetNoTriple;
934-
943+
944+
// TODO: functionality between OpenMP offloading and SYCL offloading
945+
// is similar, can be improved
935946
if (DeviceOffloadKind == Action::OFK_OpenMP) {
936947
XOffloadTargetNoTriple =
937948
A->getOption().matches(options::OPT_Xopenmp_target);
@@ -966,7 +977,6 @@ llvm::opt::DerivedArgList *ToolChain::TranslateOffloadTargetArgs(
966977
}
967978
}
968979

969-
970980
// Parse the argument to -Xopenmp-target.
971981
Prev = Index;
972982
std::unique_ptr<Arg> XOffloadTargetArg(Opts.ParseOneArg(Args, Index));
@@ -981,6 +991,8 @@ llvm::opt::DerivedArgList *ToolChain::TranslateOffloadTargetArgs(
981991
continue;
982992
}
983993
if (XOffloadTargetNoTriple && XOffloadTargetArg) {
994+
// TODO: similar behaviors with OpenMP and SYCL offloading, can be
995+
// improved upon
984996
if (DeviceOffloadKind == Action::OFK_OpenMP &&
985997
Args.getAllArgValues(options::OPT_fopenmp_targets_EQ).size() != 1) {
986998
getDriver().Diag(diag::err_drv_Xopenmp_target_missing_triple);

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3412,6 +3412,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
34123412
InputInfoList ModuleHeaderInputs;
34133413
const InputInfo *CudaDeviceInput = nullptr;
34143414
const InputInfo *OpenMPDeviceInput = nullptr;
3415+
const InputInfo *SYCLDeviceInput = nullptr;
34153416
for (const InputInfo &I : Inputs) {
34163417
if (&I == &Input) {
34173418
// This is the primary input.
@@ -3428,6 +3429,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
34283429
CudaDeviceInput = &I;
34293430
} else if (IsOpenMPDevice && !OpenMPDeviceInput) {
34303431
OpenMPDeviceInput = &I;
3432+
} else if (IsSYCL && !SYCLDeviceInput) {
3433+
SYCLDeviceInput = &I;
34313434
} else {
34323435
llvm_unreachable("unexpectedly given multiple inputs");
34333436
}
@@ -3544,8 +3547,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
35443547
} else if (isa<AssembleJobAction>(JA)) {
35453548
if (IsSYCLOffloadDevice && IsSYCLDevice) {
35463549
CmdArgs.push_back("-emit-spirv");
3547-
}
3548-
else {
3550+
} else {
35493551
CmdArgs.push_back("-emit-obj");
35503552
CollectArgsForIntegratedAssembler(C, Args, CmdArgs, D);
35513553
}
@@ -5221,11 +5223,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
52215223
}
52225224

52235225
if (IsSYCL) {
5224-
// Host-side SYCL compilation receives the integrated header file as
5226+
// Host-side SYCL compilation receives the integration header file as
52255227
// Inputs[1]. Include the header with -include
5226-
if (!IsSYCLOffloadDevice && Inputs.size() > 1) {
5228+
if (!IsSYCLOffloadDevice && SYCLDeviceInput) {
52275229
CmdArgs.push_back("-include");
5228-
CmdArgs.push_back(Inputs[1].getFilename());
5230+
CmdArgs.push_back(SYCLDeviceInput->getFilename());
52295231
}
52305232
if (IsSYCLOffloadDevice && JA.getType() == types::TY_SYCL_Header) {
52315233
// Generating a SYCL Header
@@ -6254,3 +6256,66 @@ void OffloadBundler::ConstructJobMultipleOutputs(
62546256
TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())),
62556257
CmdArgs, None));
62566258
}
6259+
6260+
// Begin OffloadWrapper
6261+
6262+
void OffloadWrapper::ConstructJob(Compilation &C, const JobAction &JA,
6263+
const InputInfo &Output,
6264+
const InputInfoList &Inputs,
6265+
const llvm::opt::ArgList &TCArgs,
6266+
const char *LinkingOutput) const {
6267+
// Construct offload-wrapper command. Also calls llc to generate the
6268+
// object that is fed to the linker from the wrapper generated bc file
6269+
assert(isa<OffloadWrappingJobAction>(JA) && "Expecting wrapping job!");
6270+
6271+
// The wrapper command looks like this:
6272+
// clang-offload-wrapper
6273+
// -o=<outputfile>.bc
6274+
// -target=sycl-x86_64-pc-linux-gnu <inputfile(s)>.spv
6275+
ArgStringList WrapperArgs;
6276+
6277+
std::string OutTmpName = C.getDriver().GetTemporaryPath("wrapper", "bc");
6278+
const char * WrapperFileName =
6279+
C.addTempFile(C.getArgs().MakeArgString(OutTmpName));
6280+
SmallString<128> OutOpt("-o=");
6281+
OutOpt += WrapperFileName;
6282+
WrapperArgs.push_back(C.getArgs().MakeArgString(OutOpt));
6283+
for (auto I : Inputs) {
6284+
WrapperArgs.push_back(I.getFilename());
6285+
}
6286+
6287+
SmallString<128> TargetOpt("-target=");
6288+
TargetOpt += Action::GetOffloadKindName(JA.getOffloadingDeviceKind());
6289+
TargetOpt += '-';
6290+
TargetOpt += getToolChain().getAuxTriple()->str();
6291+
WrapperArgs.push_back(C.getArgs().MakeArgString(TargetOpt));
6292+
6293+
// For SYCL, do not emit entry tables
6294+
if (JA.isOffloading(Action::OFK_SYCL))
6295+
WrapperArgs.push_back("-emit-entry-table=0");
6296+
6297+
C.addCommand(llvm::make_unique<Command>(JA, *this,
6298+
TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())),
6299+
WrapperArgs, None));
6300+
6301+
// Construct llc command.
6302+
// The output is an object file
6303+
ArgStringList LlcArgs{"-filetype=obj", "-o", Output.getFilename(),
6304+
WrapperFileName};
6305+
llvm::Reloc::Model RelocationModel;
6306+
unsigned PICLevel;
6307+
bool IsPIE;
6308+
std::tie(RelocationModel, PICLevel, IsPIE) =
6309+
ParsePICArgs(getToolChain(), TCArgs);
6310+
if (PICLevel > 0) {
6311+
LlcArgs.push_back("-relocation-model=pic");
6312+
}
6313+
if (IsPIE) {
6314+
LlcArgs.push_back("-enable-pie");
6315+
}
6316+
SmallString<128> LlcPath(C.getDriver().Dir);
6317+
llvm::sys::path::append(LlcPath, "llc");
6318+
const char *Llc = C.getArgs().MakeArgString(LlcPath);
6319+
C.addCommand(llvm::make_unique<Command>(JA, *this, Llc, LlcArgs, None));
6320+
}
6321+

clang/lib/Driver/ToolChains/Clang.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,19 @@ class LLVM_LIBRARY_VISIBILITY OffloadBundler final : public Tool {
147147
const llvm::opt::ArgList &TCArgs,
148148
const char *LinkingOutput) const override;
149149
};
150+
151+
/// Offload wrapper tool.
152+
class LLVM_LIBRARY_VISIBILITY OffloadWrapper final : public Tool {
153+
public:
154+
OffloadWrapper(const ToolChain &TC)
155+
: Tool("offload wrapper", "clang-offload-wrapper", TC) {}
156+
157+
bool hasIntegratedCPP() const override { return false; }
158+
void ConstructJob(Compilation &C, const JobAction &JA,
159+
const InputInfo &Output, const InputInfoList &Inputs,
160+
const llvm::opt::ArgList &TCArgs,
161+
const char *LinkingOutput) const override;
162+
};
150163
} // end namespace tools
151164

152165
} // end namespace driver

0 commit comments

Comments
 (0)