Skip to content

Commit 933e3eb

Browse files
authored
[Driver][SYCL] Pass along target options to clang-offload-wrapper (#1061)
The use of -Xsycl-target-linker and -Xsycl-target-backend options should pass along the -compile-opts and -link-opts options to the offload wrapper call for the specified target. Use of the -Xsycl* options when performing AOT will pass the options to the AOT tool call. Signed-off-by: Michael D Toguchi <[email protected]>
1 parent e613fb3 commit 933e3eb

File tree

4 files changed

+164
-120
lines changed

4 files changed

+164
-120
lines changed

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "MSP430.h"
2222
#include "InputInfo.h"
2323
#include "PS4CPU.h"
24+
#include "SYCL.h"
2425
#include "clang/Basic/CharInfo.h"
2526
#include "clang/Basic/CodeGenOptions.h"
2627
#include "clang/Basic/LangOptions.h"
@@ -7250,6 +7251,31 @@ void OffloadWrapper::ConstructJob(Compilation &C, const JobAction &JA,
72507251
if (A->getValue() == StringRef("image"))
72517252
WrapperArgs.push_back(C.getArgs().MakeArgString("--emit-reg-funcs=0"));
72527253
}
7254+
// Grab any Target specific options that need to be added to the wrapper
7255+
// information.
7256+
ArgStringList BuildArgs;
7257+
auto createArgString = [&](const char *Opt) {
7258+
if (BuildArgs.empty())
7259+
return;
7260+
SmallString<128> AL;
7261+
for (const char *A : BuildArgs) {
7262+
if (AL.empty()) {
7263+
AL = A;
7264+
continue;
7265+
}
7266+
AL += " ";
7267+
AL += A;
7268+
}
7269+
WrapperArgs.push_back(C.getArgs().MakeArgString(
7270+
Twine(Opt) + Twine("\"") + AL + Twine("\"")));
7271+
};
7272+
const toolchains::SYCLToolChain &TC =
7273+
static_cast<const toolchains::SYCLToolChain &>(getToolChain());
7274+
TC.TranslateBackendTargetArgs(TCArgs, BuildArgs);
7275+
createArgString("-compile-opts=");
7276+
BuildArgs.clear();
7277+
TC.TranslateLinkerTargetArgs(TCArgs, BuildArgs);
7278+
createArgString("-link-opts=");
72537279
WrapperArgs.push_back(
72547280
C.getArgs().MakeArgString(Twine("-target=") + TargetTripleOpt));
72557281

clang/lib/Driver/ToolChains/SYCL.cpp

Lines changed: 102 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,6 @@ const char *SYCL::Linker::constructLLVMLinkCommand(Compilation &C,
114114
for (const auto &II : InputFiles)
115115
CmdArgs.push_back(II.getFilename());
116116

117-
// Add additional options from -Xsycl-target-linker
118-
TranslateSYCLLinkerArgs(C, Args, getToolChain(), CmdArgs);
119117
// Add an intermediate output file.
120118
CmdArgs.push_back("-o");
121119
const char *OutputFileName = Output.getFilename();
@@ -185,113 +183,6 @@ void SYCL::Linker::ConstructJob(Compilation &C, const JobAction &JA,
185183
SpirvInputs);
186184
}
187185

188-
void SYCL::TranslateSYCLTargetArgs(Compilation &C,
189-
const llvm::opt::ArgList &Args, const ToolChain &TC,
190-
llvm::opt::ArgStringList &CmdArgs) {
191-
192-
// Handle -Xsycl-target and -Xs flags.
193-
for (auto *A : Args) {
194-
// When parsing the target args, the -Xs<opt> type option applies to all
195-
// target compilations is not associated with a specific triple. The
196-
// option can be used in 3 different ways:
197-
// -Xs -DFOO -Xs -DBAR
198-
// -Xs "-DFOO -DBAR"
199-
// -XsDFOO -XsDBAR
200-
// All of the above examples will pass -DFOO -DBAR to the backend compiler.
201-
if (A->getOption().matches(options::OPT_Xs)) {
202-
// Take the arg and create an option out of it.
203-
CmdArgs.push_back(Args.MakeArgString(Twine("-") + A->getValue()));
204-
A->claim();
205-
continue;
206-
}
207-
if (A->getOption().matches(options::OPT_Xs_separate)) {
208-
StringRef ArgString(A->getValue());
209-
// Do a simple parse of the args to pass back
210-
SmallVector<StringRef, 16> TargetArgs;
211-
ArgString.split(TargetArgs, ' ', -1, false);
212-
for (const auto &TA : TargetArgs)
213-
CmdArgs.push_back(Args.MakeArgString(TA));
214-
A->claim();
215-
continue;
216-
}
217-
bool XSYCLTargetNoTriple;
218-
XSYCLTargetNoTriple = A->getOption().matches(options::OPT_Xsycl_backend);
219-
if (A->getOption().matches(options::OPT_Xsycl_backend_EQ)) {
220-
// Passing device args: -Xsycl-target-backend=<triple> -opt=val.
221-
if (A->getValue() != TC.getTripleString())
222-
// Provided triple does not match current tool chain.
223-
continue;
224-
} else if (!XSYCLTargetNoTriple)
225-
// Don't worry about any of the other args, we only want to pass what is
226-
// passed in -Xsycl-target-backend.
227-
continue;
228-
229-
// Add the argument from -Xsycl-target-backend.
230-
StringRef ArgString;
231-
if (XSYCLTargetNoTriple) {
232-
// With multiple -fsycl-targets, a triple is required so we know where
233-
// the options should go.
234-
if (Args.getAllArgValues(options::OPT_fsycl_targets_EQ).size() != 1) {
235-
C.getDriver().Diag(diag::err_drv_Xsycl_target_missing_triple)
236-
<< A->getSpelling();
237-
continue;
238-
}
239-
// No triple, so just add the argument.
240-
ArgString = A->getValue();
241-
} else
242-
// Triple found, add the next argument in line.
243-
ArgString = A->getValue(1);
244-
// Do a simple parse of the args to pass back
245-
SmallVector<StringRef, 16> TargetArgs;
246-
ArgString.split(TargetArgs, ' ', -1, false);
247-
for (const auto &TA : TargetArgs)
248-
CmdArgs.push_back(Args.MakeArgString(TA));
249-
A->claim();
250-
}
251-
}
252-
253-
void SYCL::TranslateSYCLLinkerArgs(Compilation &C,
254-
const llvm::opt::ArgList &Args, const ToolChain &TC,
255-
llvm::opt::ArgStringList &CmdArgs) {
256-
257-
// Handle -Xsycl-target-linker flag.
258-
for (auto *A : Args) {
259-
bool XSYCLLinkerNoTriple;
260-
XSYCLLinkerNoTriple = A->getOption().matches(options::OPT_Xsycl_linker);
261-
if (A->getOption().matches(options::OPT_Xsycl_linker_EQ)) {
262-
// Passing llvm-link args: -Xsycl-target-linker=<triple> -opt=val.
263-
if (A->getValue() != TC.getTripleString())
264-
// Provided triple does not match current tool chain.
265-
continue;
266-
} else if (!XSYCLLinkerNoTriple)
267-
// Don't worry about any of the other args, we only want to pass what is
268-
// passed in -Xsycl-target-linker.
269-
continue;
270-
271-
// Add the argument from -Xsycl-target-linker.
272-
StringRef ArgString;
273-
if (XSYCLLinkerNoTriple) {
274-
// With multiple -fsycl-targets, a triple is required so we know where
275-
// the options should go.
276-
if (Args.getAllArgValues(options::OPT_fsycl_targets_EQ).size() != 1) {
277-
C.getDriver().Diag(diag::err_drv_Xsycl_target_missing_triple)
278-
<< A->getSpelling();
279-
continue;
280-
}
281-
// No triple, so just add the argument.
282-
ArgString = A->getValue();
283-
} else
284-
// Triple found, add the next argument in line.
285-
ArgString = A->getValue(1);
286-
// Do a simple parse of the args to pass back
287-
SmallVector<StringRef, 16> TargetArgs;
288-
ArgString.split(TargetArgs, ' ', -1, false);
289-
for (const auto &TA : TargetArgs)
290-
CmdArgs.push_back(Args.MakeArgString(TA));
291-
A->claim();
292-
}
293-
}
294-
295186
void SYCL::fpga::BackendCompiler::ConstructJob(Compilation &C,
296187
const JobAction &JA,
297188
const InputInfo &Output,
@@ -383,7 +274,11 @@ void SYCL::fpga::BackendCompiler::ConstructJob(Compilation &C,
383274
if (!ReportOptArg.empty())
384275
CmdArgs.push_back(C.getArgs().MakeArgString(
385276
Twine("-output-report-folder=") + ReportOptArg));
386-
TranslateSYCLTargetArgs(C, Args, getToolChain(), CmdArgs);
277+
// Add -Xsycl-target* options.
278+
const toolchains::SYCLToolChain &TC =
279+
static_cast<const toolchains::SYCLToolChain &>(getToolChain());
280+
TC.TranslateBackendTargetArgs(Args, CmdArgs);
281+
TC.TranslateLinkerTargetArgs(Args, CmdArgs);
387282
// Look for -reuse-exe=XX option
388283
if (Arg *A = Args.getLastArg(options::OPT_reuse_exe_EQ)) {
389284
Args.ClaimAllArgs(options::OPT_reuse_exe_EQ);
@@ -421,7 +316,11 @@ void SYCL::gen::BackendCompiler::ConstructJob(Compilation &C,
421316
// The next line prevents ocloc from modifying the image name
422317
CmdArgs.push_back("-output_no_suffix");
423318
CmdArgs.push_back("-spirv_input");
424-
TranslateSYCLTargetArgs(C, Args, getToolChain(), CmdArgs);
319+
// Add -Xsycl-target* options.
320+
const toolchains::SYCLToolChain &TC =
321+
static_cast<const toolchains::SYCLToolChain &>(getToolChain());
322+
TC.TranslateBackendTargetArgs(Args, CmdArgs);
323+
TC.TranslateLinkerTargetArgs(Args, CmdArgs);
425324
SmallString<128> ExecPath(getToolChain().GetProgramPath("ocloc"));
426325
const char *Exec = C.getArgs().MakeArgString(ExecPath);
427326
auto Cmd = std::make_unique<Command>(JA, *this, Exec, CmdArgs, None);
@@ -448,7 +347,11 @@ void SYCL::x86_64::BackendCompiler::ConstructJob(Compilation &C,
448347
ForeachInputs.push_back(II);
449348
CmdArgs.push_back(Args.MakeArgString(Filename));
450349
}
451-
TranslateSYCLTargetArgs(C, Args, getToolChain(), CmdArgs);
350+
// Add -Xsycl-target* options.
351+
const toolchains::SYCLToolChain &TC =
352+
static_cast<const toolchains::SYCLToolChain &>(getToolChain());
353+
TC.TranslateBackendTargetArgs(Args, CmdArgs);
354+
TC.TranslateLinkerTargetArgs(Args, CmdArgs);
452355
SmallString<128> ExecPath(getToolChain().GetProgramPath("opencl-aot"));
453356
const char *Exec = C.getArgs().MakeArgString(ExecPath);
454357
auto Cmd = std::make_unique<Command>(JA, *this, Exec, CmdArgs, None);
@@ -496,6 +399,93 @@ SYCLToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
496399
return DAL;
497400
}
498401

402+
// Expects a specific type of option (e.g. -Xsycl-target-backend) and will
403+
// extract the arguments.
404+
void SYCLToolChain::TranslateTargetOpt(const llvm::opt::ArgList &Args,
405+
llvm::opt::ArgStringList &CmdArgs, OptSpecifier Opt,
406+
OptSpecifier Opt_EQ) const {
407+
for (auto *A : Args) {
408+
bool OptNoTriple;
409+
OptNoTriple = A->getOption().matches(Opt);
410+
if (A->getOption().matches(Opt_EQ)) {
411+
// Passing device args: -X<Opt>=<triple> -opt=val.
412+
if (A->getValue() != getTripleString())
413+
// Provided triple does not match current tool chain.
414+
continue;
415+
} else if (!OptNoTriple)
416+
// Don't worry about any of the other args, we only want to pass what is
417+
// passed in -X<Opt>
418+
continue;
419+
420+
// Add the argument from -X<Opt>
421+
StringRef ArgString;
422+
if (OptNoTriple) {
423+
// With multiple -fsycl-targets, a triple is required so we know where
424+
// the options should go.
425+
if (Args.getAllArgValues(options::OPT_fsycl_targets_EQ).size() != 1) {
426+
getDriver().Diag(diag::err_drv_Xsycl_target_missing_triple)
427+
<< A->getSpelling();
428+
continue;
429+
}
430+
// No triple, so just add the argument.
431+
ArgString = A->getValue();
432+
} else
433+
// Triple found, add the next argument in line.
434+
ArgString = A->getValue(1);
435+
436+
// Do a simple parse of the args to pass back
437+
SmallVector<StringRef, 16> TargetArgs;
438+
// TODO: Improve parsing, as this only handles arguments separated by
439+
// spaces.
440+
ArgString.split(TargetArgs, ' ', -1, false);
441+
for (const auto &TA : TargetArgs)
442+
CmdArgs.push_back(Args.MakeArgString(TA));
443+
A->claim();
444+
}
445+
}
446+
447+
void SYCLToolChain::TranslateBackendTargetArgs(const llvm::opt::ArgList &Args,
448+
llvm::opt::ArgStringList &CmdArgs) const {
449+
// Handle -Xs flags.
450+
for (auto *A : Args) {
451+
// When parsing the target args, the -Xs<opt> type option applies to all
452+
// target compilations is not associated with a specific triple. The
453+
// option can be used in 3 different ways:
454+
// -Xs -DFOO -Xs -DBAR
455+
// -Xs "-DFOO -DBAR"
456+
// -XsDFOO -XsDBAR
457+
// All of the above examples will pass -DFOO -DBAR to the backend compiler.
458+
if (A->getOption().matches(options::OPT_Xs)) {
459+
// Take the arg and create an option out of it.
460+
CmdArgs.push_back(Args.MakeArgString(Twine("-") + A->getValue()));
461+
A->claim();
462+
continue;
463+
}
464+
if (A->getOption().matches(options::OPT_Xs_separate)) {
465+
StringRef ArgString(A->getValue());
466+
// Do a simple parse of the args to pass back
467+
SmallVector<StringRef, 16> TargetArgs;
468+
// TODO: Improve parsing, as this only handles arguments separated by
469+
// spaces.
470+
ArgString.split(TargetArgs, ' ', -1, false);
471+
for (const auto &TA : TargetArgs)
472+
CmdArgs.push_back(Args.MakeArgString(TA));
473+
A->claim();
474+
continue;
475+
}
476+
}
477+
// Handle -Xsycl-target-backend.
478+
TranslateTargetOpt(Args, CmdArgs, options::OPT_Xsycl_backend,
479+
options::OPT_Xsycl_backend_EQ);
480+
}
481+
482+
void SYCLToolChain::TranslateLinkerTargetArgs(const llvm::opt::ArgList &Args,
483+
llvm::opt::ArgStringList &CmdArgs) const {
484+
// Handle -Xsycl-target-linker.
485+
TranslateTargetOpt(Args, CmdArgs, options::OPT_Xsycl_linker,
486+
options::OPT_Xsycl_linker_EQ);
487+
}
488+
499489
Tool *SYCLToolChain::buildBackendCompiler() const {
500490
if (getTriple().getSubArch() == llvm::Triple::SPIRSubArch_fpga)
501491
return new tools::SYCL::fpga::BackendCompiler(*this);

clang/lib/Driver/ToolChains/SYCL.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,6 @@ class Command;
2020
namespace tools {
2121
namespace SYCL {
2222

23-
// Gather command line arguments for backend compilation call
24-
void TranslateSYCLTargetArgs(Compilation &C,
25-
const llvm::opt::ArgList &Args, const ToolChain &TC, llvm::opt::ArgStringList &CmdArgs);
26-
27-
// Gather command line arguments for device specific link
28-
void TranslateSYCLLinkerArgs(Compilation &C,
29-
const llvm::opt::ArgList &Args, const ToolChain &TC, llvm::opt::ArgStringList &CmdArgs);
30-
3123
void constructLLVMForeachCommand(Compilation &C, const JobAction &JA,
3224
std::unique_ptr<Command> InputCommand,
3325
const InputInfoList &InputFiles,
@@ -138,6 +130,10 @@ class LLVM_LIBRARY_VISIBILITY SYCLToolChain : public ToolChain {
138130
void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
139131
llvm::opt::ArgStringList &CC1Args,
140132
Action::OffloadKind DeviceOffloadKind) const override;
133+
void TranslateBackendTargetArgs(const llvm::opt::ArgList &Args,
134+
llvm::opt::ArgStringList &CmdArgs) const;
135+
void TranslateLinkerTargetArgs(const llvm::opt::ArgList &Args,
136+
llvm::opt::ArgStringList &CmdArgs) const;
141137

142138
bool useIntegratedAs() const override { return true; }
143139
bool isPICDefault() const override { return false; }
@@ -158,6 +154,11 @@ class LLVM_LIBRARY_VISIBILITY SYCLToolChain : public ToolChain {
158154
protected:
159155
Tool *buildBackendCompiler() const override;
160156
Tool *buildLinker() const override;
157+
158+
private:
159+
void TranslateTargetOpt(const llvm::opt::ArgList &Args,
160+
llvm::opt::ArgStringList &CmdArgs, llvm::opt::OptSpecifier Opt,
161+
llvm::opt::OptSpecifier Opt_EQ) const;
161162
};
162163

163164
} // end namespace toolchains

clang/test/Driver/sycl-offload.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,14 +735,41 @@
735735
// RUN: %clang -### -target x86_64-unknown-linux-gnu -fsycl -fintelfpga -Xs "-DFOO1 -DFOO2" %s 2>&1 \
736736
// RUN: | FileCheck -check-prefix=CHK-TOOLS-FPGA-OPTS %s
737737
// CHK-TOOLS-FPGA-OPTS: aoc{{.*}} "-o" {{.*}} "-DFOO1" "-DFOO2"
738+
// CHK-TOOLS-FPGA-OPTS: clang-offload-wrapper{{.*}} "-compile-opts=\"-DFOO1 -DFOO2\""
738739

739740
// RUN: %clang -### -target x86_64-unknown-linux-gnu -fsycl -fsycl-targets=spir64_gen-unknown-unknown-sycldevice -Xsycl-target-backend "-DFOO1 -DFOO2" %s 2>&1 \
740741
// RUN: | FileCheck -check-prefix=CHK-TOOLS-GEN-OPTS %s
741742
// CHK-TOOLS-GEN-OPTS: ocloc{{.*}} "-output" {{.*}} "-output_no_suffix" {{.*}} "-DFOO1" "-DFOO2"
743+
// CHK-TOOLS-GEN-OPTS: clang-offload-wrapper{{.*}} "-compile-opts=\"-DFOO1 -DFOO2\""
742744

743745
// RUN: %clang -### -target x86_64-unknown-linux-gnu -fsycl -fsycl-targets=spir64_x86_64-unknown-unknown-sycldevice -Xsycl-target-backend "-DFOO1 -DFOO2" %s 2>&1 \
744746
// RUN: | FileCheck -check-prefix=CHK-TOOLS-CPU-OPTS %s
745747
// CHK-TOOLS-CPU-OPTS: opencl-aot{{.*}} "-DFOO1" "-DFOO2"
748+
// CHK-TOOLS-CPU-OPTS: clang-offload-wrapper{{.*}} "-compile-opts=\"-DFOO1 -DFOO2\""
749+
750+
// RUN: %clang -### -target x86_64-unknown-linux-gnu -fsycl -fsycl-targets=spir64-unknown-unknown-sycldevice -Xsycl-target-backend "-DFOO1 -DFOO2" %s 2>&1 \
751+
// RUN: | FileCheck -check-prefix=CHK-TOOLS-OPTS %s
752+
// CHK-TOOLS-OPTS: clang-offload-wrapper{{.*}} "-compile-opts=\"-DFOO1 -DFOO2\""
753+
754+
/// Check -Xsycl-target-linker option passing
755+
// RUN: %clang -### -target x86_64-unknown-linux-gnu -fsycl -fsycl-targets=spir64_fpga-unknown-unknown-sycldevice -Xsycl-target-linker "-DFOO1 -DFOO2" %s 2>&1 \
756+
// RUN: | FileCheck -check-prefix=CHK-TOOLS-FPGA-OPTS2 %s
757+
// CHK-TOOLS-FPGA-OPTS2: aoc{{.*}} "-o" {{.*}} "-DFOO1" "-DFOO2"
758+
// CHK-TOOLS-FPGA-OPTS2: clang-offload-wrapper{{.*}} "-link-opts=\"-DFOO1 -DFOO2\""
759+
760+
// RUN: %clang -### -target x86_64-unknown-linux-gnu -fsycl -fsycl-targets=spir64_gen-unknown-unknown-sycldevice -Xsycl-target-linker "-DFOO1 -DFOO2" %s 2>&1 \
761+
// RUN: | FileCheck -check-prefix=CHK-TOOLS-GEN-OPTS2 %s
762+
// CHK-TOOLS-GEN-OPTS2: ocloc{{.*}} "-output" {{.*}} "-output_no_suffix" {{.*}} "-DFOO1" "-DFOO2"
763+
// CHK-TOOLS-GEN-OPTS2: clang-offload-wrapper{{.*}} "-link-opts=\"-DFOO1 -DFOO2\""
764+
765+
// RUN: %clang -### -target x86_64-unknown-linux-gnu -fsycl -fsycl-targets=spir64_x86_64-unknown-unknown-sycldevice -Xsycl-target-linker "-DFOO1 -DFOO2" %s 2>&1 \
766+
// RUN: | FileCheck -check-prefix=CHK-TOOLS-CPU-OPTS2 %s
767+
// CHK-TOOLS-CPU-OPTS2: opencl-aot{{.*}} "-DFOO1" "-DFOO2"
768+
// CHK-TOOLS-CPU-OPTS2: clang-offload-wrapper{{.*}} "-link-opts=\"-DFOO1 -DFOO2\""
769+
770+
// RUN: %clang -### -target x86_64-unknown-linux-gnu -fsycl -fsycl-targets=spir64-unknown-unknown-sycldevice -Xsycl-target-linker "-DFOO1 -DFOO2" %s 2>&1 \
771+
// RUN: | FileCheck -check-prefix=CHK-TOOLS-OPTS2 %s
772+
// CHK-TOOLS-OPTS2: clang-offload-wrapper{{.*}} "-link-opts=\"-DFOO1 -DFOO2\""
746773

747774
/// ###########################################################################
748775

0 commit comments

Comments
 (0)