Skip to content

Commit

Permalink
[Driver][SYCL] Improve support for -fsycl-link with AOT (#12828)
Browse files Browse the repository at this point in the history
Support for -fsycl-link was restricted to only providing device linking
and providing the final device binary for JIT. These changes expand on
that functionality to pull in the ability to also perform offline
compilation steps to support AOT targets.

Example:

  clang++ -fsycl -fsycl-targets=spir64_gen -c file.cpp
  clang++ -fsycl -fsycl-link -fsycl-targets=spir64_gen
          -Xsycl-target-backend "-device skl" file.o -o newfile.o
  clang++ file.o newfile.o -o finalexe

'newfile.o' here is a final device binary for GPU that is wrapped and
allowed to be linked in as a regular host object.

The changes here are significant, performing adjustments on when the
device linking occurs within the compilation toolchain within the
driver. This improves the general dependency flow, allowing for the
device linking to occur in a common location for -fsycl-link and normal
link steps. Due to this, a number of tests relying on phase checking
required to be tweaked.
  • Loading branch information
mdtoguchi committed Mar 8, 2024
1 parent ce70f0d commit 22fab5a
Show file tree
Hide file tree
Showing 38 changed files with 1,017 additions and 1,441 deletions.
262 changes: 150 additions & 112 deletions clang/lib/Driver/Driver.cpp

Large diffs are not rendered by default.

98 changes: 62 additions & 36 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9747,6 +9747,53 @@ void OffloadBundler::ConstructJobMultipleOutputs(

// Begin OffloadWrapper

static void addRunTimeWrapperOpts(Compilation &C,
Action::OffloadKind DeviceOffloadKind,
const llvm::opt::ArgList &TCArgs,
ArgStringList &CmdArgs,
const ToolChain &TC,
const JobAction &JA) {
// Grab any Target specific options that need to be added to the wrapper
// information.
ArgStringList BuildArgs;
auto createArgString = [&](const char *Opt) {
if (BuildArgs.empty())
return;
SmallString<128> AL;
for (const char *A : BuildArgs) {
if (AL.empty()) {
AL = A;
continue;
}
AL += " ";
AL += A;
}
CmdArgs.push_back(C.getArgs().MakeArgString(Twine(Opt) + AL));
};
const toolchains::SYCLToolChain &SYCLTC =
static_cast<const toolchains::SYCLToolChain &>(TC);
llvm::Triple TT = SYCLTC.getTriple();
// TODO: Consider separating the mechanisms for:
// - passing standard-defined options to AOT/JIT compilation steps;
// - passing AOT-compiler specific options.
// This would allow retaining standard language options in the
// image descriptor, while excluding tool-specific options that
// have been known to confuse RT implementations.
if (TT.getSubArch() == llvm::Triple::NoSubArch) {
// Only store compile/link opts in the image descriptor for the SPIR-V
// target; AOT compilation has already been performed otherwise.
const ArgList &Args = C.getArgsForToolChain(nullptr, StringRef(),
DeviceOffloadKind);
const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
SYCLTC.AddImpliedTargetArgs(TT, Args, BuildArgs, JA, *HostTC);
SYCLTC.TranslateBackendTargetArgs(TT, Args, BuildArgs);
createArgString("-compile-opts=");
BuildArgs.clear();
SYCLTC.TranslateLinkerTargetArgs(TT, Args, BuildArgs);
createArgString("-link-opts=");
}
}

void OffloadWrapper::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
Expand Down Expand Up @@ -9792,6 +9839,9 @@ void OffloadWrapper::ConstructJob(Compilation &C, const JobAction &JA,
if (A->getValue() == StringRef("image"))
WrapperArgs.push_back(C.getArgs().MakeArgString("--emit-reg-funcs=0"));
}
addRunTimeWrapperOpts(C, OffloadingKind, TCArgs, WrapperArgs,
getToolChain(), JA);

// When wrapping an FPGA device binary, we need to be sure to apply the
// appropriate triple that corresponds (fpga_aocr-intel-<os>)
// to the target triple setting.
Expand All @@ -9807,42 +9857,8 @@ void OffloadWrapper::ConstructJob(Compilation &C, const JobAction &JA,
TT.setVendorName("intel");
TargetTripleOpt = TT.str();
}
// Grab any Target specific options that need to be added to the wrapper
// information.
ArgStringList BuildArgs;
auto createArgString = [&](const char *Opt) {
if (BuildArgs.empty())
return;
SmallString<128> AL;
for (const char *A : BuildArgs) {
if (AL.empty()) {
AL = A;
continue;
}
AL += " ";
AL += A;
}
WrapperArgs.push_back(C.getArgs().MakeArgString(Twine(Opt) + AL));
};
const toolchains::SYCLToolChain &TC =
static_cast<const toolchains::SYCLToolChain &>(getToolChain());
// TODO: Consider separating the mechanisms for:
// - passing standard-defined options to AOT/JIT compilation steps;
// - passing AOT-compiler specific options.
// This would allow retaining standard language options in the
// image descriptor, while excluding tool-specific options that
// have been known to confuse RT implementations.
if (TC.getTriple().getSubArch() == llvm::Triple::NoSubArch) {
// Only store compile/link opts in the image descriptor for the SPIR-V
// target; AOT compilation has already been performed otherwise.
const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
TC.AddImpliedTargetArgs(TT, TCArgs, BuildArgs, JA, *HostTC);
TC.TranslateBackendTargetArgs(TT, TCArgs, BuildArgs);
createArgString("-compile-opts=");
BuildArgs.clear();
TC.TranslateLinkerTargetArgs(TT, TCArgs, BuildArgs);
createArgString("-link-opts=");
}
bool IsEmbeddedIR = cast<OffloadWrapperJobAction>(JA).isEmbeddedIR();
if (IsEmbeddedIR) {
// When the offload-wrapper is called to embed LLVM IR, add a prefix to
Expand Down Expand Up @@ -9984,8 +10000,18 @@ void OffloadWrapper::ConstructJob(Compilation &C, const JobAction &JA,
// And add it to the offload targets.
CmdArgs.push_back(C.getArgs().MakeArgString(
Twine("-kind=") + Action::GetOffloadKindName(DeviceKind)));
CmdArgs.push_back(TCArgs.MakeArgString(Twine("-target=") +
DeviceTC->getTriple().normalize()));
std::string TargetTripleOpt = DeviceTC->getTriple().normalize();
// SYCL toolchain target only uses the arch name.
if (DeviceKind == Action::OFK_SYCL)
TargetTripleOpt = DeviceTC->getTriple().getArchName();
CmdArgs.push_back(
TCArgs.MakeArgString(Twine("-target=") + TargetTripleOpt));
addRunTimeWrapperOpts(C, DeviceKind, TCArgs, CmdArgs, *DeviceTC, JA);

if (Inputs[I].getType() == types::TY_Tempfiletable ||
Inputs[I].getType() == types::TY_Tempfilelist)
// wrapper actual input files are passed via the batch job file table:
CmdArgs.push_back(C.getArgs().MakeArgString("-batch"));

// Add input.
assert(Inputs[I].isFilename() && "Invalid input.");
Expand Down
Loading

0 comments on commit 22fab5a

Please sign in to comment.