Skip to content

[Driver][SYCL] Enable adding of default device triple #4175

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Aug 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions clang/include/clang/Driver/Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,21 @@ class Driver {
FPGAEmulationMode = IsEmulation;
}

/// The inclusion of the default SYCL device triple is dependent on either
/// the discovery of an existing object/archive that contains the device code
/// or if a user explicitly turns this on with -fsycl-add-spirv.
/// We need to keep track of this so any use of any generic target option
/// setting is only applied to the user specified triples.
bool SYCLDefaultTripleImplied = false;
void setSYCLDefaultTriple(bool IsDefaultImplied) {
SYCLDefaultTripleImplied = IsDefaultImplied;
}

/// Returns true if an offload binary is found that contains the default
/// triple for SYCL (spir64)
bool checkForSYCLDefaultDevice(Compilation &C,
llvm::opt::DerivedArgList &Args) const;

/// Returns true if an offload static library is found.
bool checkForOffloadStaticLib(Compilation &C,
llvm::opt::DerivedArgList &Args) const;
Expand Down Expand Up @@ -714,6 +729,10 @@ class Driver {
/// FPGA Emulation. This is only used for SYCL offloading to FPGA device.
bool isFPGAEmulationMode() const { return FPGAEmulationMode; };

/// isSYCLDefaultTripleImplied - The default SYCL triple (spir64) has been
/// added or should be added given proper criteria.
bool isSYCLDefaultTripleImplied() const { return SYCLDefaultTripleImplied; };

/// addIntegrationFiles - Add the integration files that will be populated
/// by the device compilation and used by the host compile.
void addIntegrationFiles(StringRef IntHeaderName, StringRef IntFooterName,
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -2644,6 +2644,9 @@ def fno_sycl_use_footer : Flag<["-"], "fno-sycl-use-footer">, Flags<[CoreOption]
def fsycl_footer_path_EQ : Joined<["-"], "fsycl-footer-path=">,
Flags<[CoreOption]>, HelpText<"Specify the location of the temporary "
"source file with the included integration footer.">;
def fno_sycl_link_spirv : Flag<["-"], "fno-sycl-link-spirv">,
Flags<[CoreOption]>, HelpText<"Disable adding of the default (spir64) triple "
"when discovered in user specified objects and archives.">;
def fsyntax_only : Flag<["-"], "fsyntax-only">,
Flags<[NoXarchOption,CoreOption,CC1Option,FC1Option]>, Group<Action_Group>;
def ftabstop_EQ : Joined<["-"], "ftabstop=">, Group<f_Group>;
Expand Down
85 changes: 79 additions & 6 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,23 @@ static bool isValidSYCLTriple(llvm::Triple T) {
return true;
}

static void addSYCLDefaultTriple(Compilation &C,
SmallVectorImpl<llvm::Triple> &SYCLTriples) {
if (!C.getDriver().isSYCLDefaultTripleImplied())
return;
for (const auto &SYCLTriple : SYCLTriples) {
if (SYCLTriple.getSubArch() == llvm::Triple::NoSubArch &&
SYCLTriple.isSPIR())
return;
// If we encounter a known non-spir* target, do not add the default triple.
if (SYCLTriple.isNVPTX() || SYCLTriple.isAMDGCN())
return;
}
// Add the default triple as it was not found.
llvm::Triple DefaultTriple = C.getDriver().MakeSYCLDeviceTriple("spir64");
SYCLTriples.insert(SYCLTriples.begin(), DefaultTriple);
}

void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
InputList &Inputs) {

Expand Down Expand Up @@ -929,6 +946,7 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
FoundNormalizedTriples[NormalizedName] = Val;
UniqueSYCLTriplesVec.push_back(TT);
}
addSYCLDefaultTriple(C, UniqueSYCLTriplesVec);
} else
Diag(clang::diag::warn_drv_empty_joined_argument)
<< SYCLTargetsValues->getAsString(C.getInputArgs());
Expand Down Expand Up @@ -987,8 +1005,10 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
else if (HasValidSYCLRuntime)
// Triple for -fintelfpga is spir64_fpga-unknown-unknown-sycldevice.
SYCLTargetArch = SYCLfpga ? "spir64_fpga" : "spir64";
if (!SYCLTargetArch.empty())
if (!SYCLTargetArch.empty()) {
UniqueSYCLTriplesVec.push_back(MakeSYCLDeviceTriple(SYCLTargetArch));
addSYCLDefaultTriple(C, UniqueSYCLTriplesVec);
}
}
// We'll need to use the SYCL and host triples as the key into
// getOffloadingDeviceToolChain, because the device toolchains we're
Expand Down Expand Up @@ -1418,6 +1438,11 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
if (checkForOffloadStaticLib(*C, *TranslatedArgs))
setOffloadStaticLibSeen();

// Check for any objects/archives that need to be compiled with the default
// triple.
if (checkForSYCLDefaultDevice(*C, *TranslatedArgs))
setSYCLDefaultTriple(true);

// Populate the tool chains for the offloading devices, if any.
CreateOffloadingDeviceToolChains(*C, Inputs);

Expand All @@ -1428,7 +1453,8 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
const ToolChain *TC = SYCLTCRange.first->second;
const toolchains::SYCLToolChain *SYCLTC =
static_cast<const toolchains::SYCLToolChain *>(TC);
SYCLTC->TranslateBackendTargetArgs(*TranslatedArgs, TargetArgs);
SYCLTC->TranslateBackendTargetArgs(SYCLTC->getTriple(), *TranslatedArgs,
TargetArgs);
for (StringRef ArgString : TargetArgs) {
if (ArgString.equals("-hardware") || ArgString.equals("-simulation")) {
setFPGAEmulationMode(false);
Expand Down Expand Up @@ -2762,6 +2788,30 @@ bool hasFPGABinary(Compilation &C, std::string Object, types::ID Type) {
return runBundler(BundlerArgs, C);
}

static bool hasSYCLDefaultSection(Compilation &C, const StringRef &File) {
// Do not do the check if the file doesn't exist
if (!llvm::sys::fs::exists(File))
return false;

bool IsArchive = isStaticArchiveFile(File);
if (!(IsArchive || isObjectFile(File.str())))
return false;

llvm::Triple TT(C.getDriver().MakeSYCLDeviceTriple("spir64"));
// Checking uses -check-section option with the input file, no output
// file and the target triple being looked for.
const char *Targets =
C.getArgs().MakeArgString(Twine("-targets=sycl-") + TT.str());
const char *Inputs =
C.getArgs().MakeArgString(Twine("-inputs=") + File.str());
// Always use -type=ao for bundle checking. The 'bundles' are
// actually archives.
SmallVector<StringRef, 6> BundlerArgs = {"clang-offload-bundler",
IsArchive ? "-type=ao" : "-type=o",
Targets, Inputs, "-check-section"};
return runBundler(BundlerArgs, C);
}

static bool hasOffloadSections(Compilation &C, const StringRef &Archive,
DerivedArgList &Args) {
// Do not do the check if the file doesn't exist
Expand Down Expand Up @@ -2792,14 +2842,15 @@ static bool optionMatches(const std::string &Option,
// Process linker inputs for use with offload static libraries. We are only
// handling options and explicitly named static archives as these need to be
// partially linked.
static SmallVector<const char *, 16> getLinkerArgs(Compilation &C,
DerivedArgList &Args) {
static SmallVector<const char *, 16>
getLinkerArgs(Compilation &C, DerivedArgList &Args, bool IncludeObj = false) {
SmallVector<const char *, 16> LibArgs;
for (const auto *A : Args) {
std::string FileName = A->getAsString(Args);
if (A->getOption().getKind() == Option::InputClass) {
StringRef Value(A->getValue());
if (isStaticArchiveFile(Value)) {
if (isStaticArchiveFile(Value) ||
(IncludeObj && isObjectFile(Value.str()))) {
LibArgs.push_back(Args.MakeArgString(FileName));
continue;
}
Expand All @@ -2818,7 +2869,7 @@ static SmallVector<const char *, 16> getLinkerArgs(Compilation &C,
// Only add named static libs objects and --whole-archive options.
if (optionMatches("-whole-archive", V.str()) ||
optionMatches("-no-whole-archive", V.str()) ||
isStaticArchiveFile(V)) {
isStaticArchiveFile(V) || (IncludeObj && isObjectFile(V.str()))) {
LibArgs.push_back(Args.MakeArgString(V));
return;
}
Expand Down Expand Up @@ -2884,6 +2935,26 @@ static bool IsSYCLDeviceLibObj(std::string ObjFilePath, bool isMSVCEnv) {
return Ret;
}

// Goes through all of the arguments, including inputs expected for the
// linker directly, to determine if we need to potentially add the SYCL
// default triple.
bool Driver::checkForSYCLDefaultDevice(Compilation &C,
DerivedArgList &Args) const {
// Check only if enabled with -fsycl
if (!Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false))
return false;

if (Args.hasArg(options::OPT_fno_sycl_link_spirv))
return false;

SmallVector<const char *, 16> AllArgs(getLinkerArgs(C, Args, true));
for (StringRef Arg : AllArgs) {
if (hasSYCLDefaultSection(C, Arg))
return true;
}
return false;
}

// Goes through all of the arguments, including inputs expected for the
// linker directly, to determine if we need to perform additional work for
// static offload libraries.
Expand Down Expand Up @@ -4665,6 +4736,7 @@ class OffloadingActionBuilder final {
if (TT.getSubArch() == llvm::Triple::SPIRSubArch_fpga)
SYCLfpgaTriple = true;
}
addSYCLDefaultTriple(C, SYCLTripleList);
}
if (SYCLAddTargets) {
for (StringRef Val : SYCLAddTargets->getValues()) {
Expand All @@ -4687,6 +4759,7 @@ class OffloadingActionBuilder final {
const char *SYCLTargetArch = SYCLfpga ? "spir64_fpga" : "spir64";
SYCLTripleList.push_back(
C.getDriver().MakeSYCLDeviceTriple(SYCLTargetArch));
addSYCLDefaultTriple(C, SYCLTripleList);
if (SYCLfpga)
SYCLfpgaTriple = true;
}
Expand Down
8 changes: 6 additions & 2 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8274,6 +8274,8 @@ void OffloadBundler::ConstructJobMultipleOutputs(
if (getToolChain().getTriple().getSubArch() ==
llvm::Triple::SPIRSubArch_fpga &&
Dep.DependentOffloadKind == Action::OFK_SYCL) {
if (J++)
Triples += ',';
llvm::Triple TT;
TT.setArchName(types::getTypeName(InputType));
TT.setVendorName("intel");
Expand All @@ -8284,6 +8286,8 @@ void OffloadBundler::ConstructJobMultipleOutputs(
} else if (getToolChain().getTriple().getSubArch() !=
llvm::Triple::SPIRSubArch_fpga &&
Dep.DependentOffloadKind == Action::OFK_Host) {
if (J++)
Triples += ',';
Triples += Action::GetOffloadKindName(Dep.DependentOffloadKind);
Triples += '-';
Triples += Dep.DependentToolChain->getTriple().normalize();
Expand Down Expand Up @@ -8443,10 +8447,10 @@ void OffloadWrapper::ConstructJob(Compilation &C, const JobAction &JA,
// Only store compile/link opts in the image descriptor for the SPIR-V
// target; AOT compilation has already been performed otherwise.
TC.AddImpliedTargetArgs(TT, TCArgs, BuildArgs);
TC.TranslateBackendTargetArgs(TCArgs, BuildArgs);
TC.TranslateBackendTargetArgs(TT, TCArgs, BuildArgs);
createArgString("-compile-opts=");
BuildArgs.clear();
TC.TranslateLinkerTargetArgs(TCArgs, BuildArgs);
TC.TranslateLinkerTargetArgs(TT, TCArgs, BuildArgs);
createArgString("-link-opts=");
}

Expand Down
41 changes: 30 additions & 11 deletions clang/lib/Driver/ToolChains/SYCL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,8 @@ void SYCL::fpga::BackendCompiler::constructOpenCLAOTCommand(
llvm::Triple CPUTriple("spir64_x86_64");
TC.AddImpliedTargetArgs(CPUTriple, Args, CmdArgs);
// Add the target args passed in
TC.TranslateBackendTargetArgs(Args, CmdArgs);
TC.TranslateLinkerTargetArgs(Args, CmdArgs);
TC.TranslateBackendTargetArgs(CPUTriple, Args, CmdArgs);
TC.TranslateLinkerTargetArgs(CPUTriple, Args, CmdArgs);

SmallString<128> ExecPath(
getToolChain().GetProgramPath(makeExeName(C, "opencl-aot")));
Expand All @@ -414,7 +414,7 @@ void SYCL::fpga::BackendCompiler::ConstructJob(
const toolchains::SYCLToolChain &TC =
static_cast<const toolchains::SYCLToolChain &>(getToolChain());
ArgStringList TargetArgs;
TC.TranslateBackendTargetArgs(Args, TargetArgs);
TC.TranslateBackendTargetArgs(TC.getTriple(), Args, TargetArgs);

// When performing emulation compilations for FPGA AOT, we want to use
// opencl-aot instead of aoc.
Expand Down Expand Up @@ -534,8 +534,8 @@ void SYCL::fpga::BackendCompiler::ConstructJob(
TC.AddImpliedTargetArgs(getToolChain().getTriple(), Args, CmdArgs);

// Add -Xsycl-target* options.
TC.TranslateBackendTargetArgs(Args, CmdArgs);
TC.TranslateLinkerTargetArgs(Args, CmdArgs);
TC.TranslateBackendTargetArgs(getToolChain().getTriple(), Args, CmdArgs);
TC.TranslateLinkerTargetArgs(getToolChain().getTriple(), Args, CmdArgs);

// Look for -reuse-exe=XX option
if (Arg *A = Args.getLastArg(options::OPT_reuse_exe_EQ)) {
Expand Down Expand Up @@ -581,8 +581,8 @@ void SYCL::gen::BackendCompiler::ConstructJob(Compilation &C,
const toolchains::SYCLToolChain &TC =
static_cast<const toolchains::SYCLToolChain &>(getToolChain());
TC.AddImpliedTargetArgs(getToolChain().getTriple(), Args, CmdArgs);
TC.TranslateBackendTargetArgs(Args, CmdArgs);
TC.TranslateLinkerTargetArgs(Args, CmdArgs);
TC.TranslateBackendTargetArgs(getToolChain().getTriple(), Args, CmdArgs);
TC.TranslateLinkerTargetArgs(getToolChain().getTriple(), Args, CmdArgs);
SmallString<128> ExecPath(
getToolChain().GetProgramPath(makeExeName(C, "ocloc")));
const char *Exec = C.getArgs().MakeArgString(ExecPath);
Expand Down Expand Up @@ -614,8 +614,8 @@ void SYCL::x86_64::BackendCompiler::ConstructJob(
static_cast<const toolchains::SYCLToolChain &>(getToolChain());

TC.AddImpliedTargetArgs(getToolChain().getTriple(), Args, CmdArgs);
TC.TranslateBackendTargetArgs(Args, CmdArgs);
TC.TranslateLinkerTargetArgs(Args, CmdArgs);
TC.TranslateBackendTargetArgs(getToolChain().getTriple(), Args, CmdArgs);
TC.TranslateLinkerTargetArgs(getToolChain().getTriple(), Args, CmdArgs);
SmallString<128> ExecPath(
getToolChain().GetProgramPath(makeExeName(C, "opencl-aot")));
const char *Exec = C.getArgs().MakeArgString(ExecPath);
Expand Down Expand Up @@ -765,7 +765,8 @@ void SYCLToolChain::AddImpliedTargetArgs(
}

void SYCLToolChain::TranslateBackendTargetArgs(
const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const {
const llvm::Triple &Triple, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const {
// Handle -Xs flags.
for (auto *A : Args) {
// When parsing the target args, the -Xs<opt> type option applies to all
Expand All @@ -775,6 +776,15 @@ void SYCLToolChain::TranslateBackendTargetArgs(
// -Xs "-DFOO -DBAR"
// -XsDFOO -XsDBAR
// All of the above examples will pass -DFOO -DBAR to the backend compiler.

// Do not add the -Xs to the default SYCL triple (spir64) when we know we
// have implied the setting.
if ((A->getOption().matches(options::OPT_Xs) ||
A->getOption().matches(options::OPT_Xs_separate)) &&
Triple.getSubArch() == llvm::Triple::NoSubArch && Triple.isSPIR() &&
getDriver().isSYCLDefaultTripleImplied())
continue;

if (A->getOption().matches(options::OPT_Xs)) {
// Take the arg and create an option out of it.
CmdArgs.push_back(Args.MakeArgString(Twine("-") + A->getValue()));
Expand All @@ -788,13 +798,22 @@ void SYCLToolChain::TranslateBackendTargetArgs(
continue;
}
}
// Do not process -Xsycl-target-backend for implied spir64
if (Triple.getSubArch() == llvm::Triple::NoSubArch && Triple.isSPIR() &&
getDriver().isSYCLDefaultTripleImplied())
return;
// Handle -Xsycl-target-backend.
TranslateTargetOpt(Args, CmdArgs, options::OPT_Xsycl_backend,
options::OPT_Xsycl_backend_EQ);
}

void SYCLToolChain::TranslateLinkerTargetArgs(
const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const {
const llvm::Triple &Triple, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const {
// Do not process -Xsycl-target-linker for implied spir64
if (Triple.getSubArch() == llvm::Triple::NoSubArch && Triple.isSPIR() &&
getDriver().isSYCLDefaultTripleImplied())
return;
// Handle -Xsycl-target-linker.
TranslateTargetOpt(Args, CmdArgs, options::OPT_Xsycl_linker,
options::OPT_Xsycl_linker_EQ);
Expand Down
10 changes: 6 additions & 4 deletions clang/lib/Driver/ToolChains/SYCL.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,12 @@ class LLVM_LIBRARY_VISIBILITY SYCLToolChain : public ToolChain {
void AddImpliedTargetArgs(const llvm::Triple &Triple,
const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
void TranslateBackendTargetArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
void TranslateLinkerTargetArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
void TranslateBackendTargetArgs(const llvm::Triple &Triple,
const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
void TranslateLinkerTargetArgs(const llvm::Triple &Triple,
const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;

bool useIntegratedAs() const override { return true; }
bool isPICDefault() const override { return false; }
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Driver/sycl-intelfpga-aoco-win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// RUN: echo "void foo() {}" > %t.c
// RUN: echo "void foo2() {}" > %t2.c
// RUN: %clang -target x86_64-pc-windows-msvc -c -o %t.o %t.c
// RUN: %clang_cl --target=x86_64-pc-windows-msvc -fsycl -c -o %t2.o %t2.c
// RUN: %clang_cl --target=x86_64-pc-windows-msvc -fsycl -fintelfpga -c -o %t2.o %t2.c
// RUN: clang-offload-wrapper -o %t-aoco.bc -host=x86_64-pc-windows-msvc -kind=sycl -target=fpga_aoco-intel-unknown-sycldevice %t.aoco
// RUN: llc -filetype=obj -o %t-aoco.o %t-aoco.bc
// RUN: llvm-ar crv %t_aoco.a %t.o %t2.o %t-aoco.o
Expand Down
4 changes: 2 additions & 2 deletions clang/test/Driver/sycl-intelfpga-aoco.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
// RUN: echo "void foo() {}" > %t.c
// RUN: echo "void foo2() {}" > %t2.c
// RUN: %clang -c -o %t.o %t.c
// RUN: %clang -fsycl -c -o %t2.o %t2.c
// RUN: %clang_cl -fsycl -c -o %t2_cl.o %t2.c
// RUN: %clang -fsycl -fintelfpga -c -o %t2.o %t2.c
// RUN: %clang_cl -fsycl -fintelfpga -c -o %t2_cl.o %t2.c
// RUN: clang-offload-wrapper -o %t-aoco.bc -host=x86_64-unknown-linux-gnu -kind=sycl -target=fpga_aoco-intel-unknown-sycldevice %t.aoco
// RUN: llc -filetype=obj -o %t-aoco.o %t-aoco.bc
// RUN: clang-offload-wrapper -o %t-aoco_cl.bc -host=x86_64-unknown-linux-gnu -kind=sycl -target=fpga_aoco-intel-unknown-sycldevice %t.aoco
Expand Down
1 change: 0 additions & 1 deletion clang/test/Driver/sycl-offload-intelfpga.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
// RUN: | FileCheck -check-prefixes=CHK-FPGA-LINK,CHK-FPGA-IMAGE %s
// RUN: %clangxx -### -target x86_64-unknown-linux-gnu -fsycl -fno-sycl-device-lib=all -fsycl-targets=spir64_fpga-unknown-unknown-sycldevice -fsycl-link=image -Xshardware %t.o -o libfoo.a 2>&1 \
// RUN: | FileCheck -check-prefixes=CHK-FPGA-LINK,CHK-FPGA-IMAGE %s
// CHK-FPGA-LINK-NOT: clang-offload-bundler{{.*}} "-check-section"
// CHK-FPGA-LINK: clang-offload-bundler{{.*}} "-type=o" "-targets=sycl-spir64_fpga-unknown-unknown-sycldevice" "-inputs=[[INPUT:.+\.o]]" "-outputs=[[OUTPUT1:.+\.o]]" "-unbundle"
// CHK-FPGA-LINK-NOT: clang-offload-bundler{{.*}}
// CHK-FPGA-LINK: llvm-link{{.*}} "[[OUTPUT1]]" "-o" "[[OUTPUT2_1:.+\.bc]]"
Expand Down
Loading