Skip to content
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

[Driver][SYCL] Add support for -fsycl-force-target #6653

Merged
merged 2 commits into from
Aug 31, 2022
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
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticDriverKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,8 @@ def warn_drv_sycl_offload_target_duplicate : Warning<
def warn_drv_sycl_target_missing : Warning<
"linked binaries do not contain expected '%0' target; found targets: '%1'">,
InGroup<SyclTarget>;
def err_drv_multiple_target_with_forced_target : Error<
"multiple target usage with '%0' is not supported with '%1'">;
def err_drv_failed_to_deduce_target_from_arch : Error<
"failed to deduce triple for target architecture '%0'; specify the triple "
"using '-fopenmp-targets' and '-Xopenmp-target' instead.">;
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -2848,6 +2848,10 @@ def fsycl_link_targets_EQ : CommaJoined<["-"], "fsycl-link-targets=">,
Flags<[NoXarchOption, CC1Option, CoreOption, Deprecated]>,
HelpText<"Specify comma-separated list of triples SYCL offloading targets "
"to produce linked device images (deprecated)">;
def fsycl_force_target_EQ : Joined<["-"], "fsycl-force-target=">,
Flags<[NoXarchOption, CoreOption]>,
HelpText<"Force the usage of the given triple when extracting device code "
"from any given objects on the command line">;
def fsycl_device_code_split_EQ : Joined<["-"], "fsycl-device-code-split=">,
Flags<[CC1Option, CoreOption]>, HelpText<"Perform SYCL device code split: per_kernel (device code module is "
"created for each SYCL kernel) | per_source (device code module is created for each source (translation unit)) | off (no device code split). | auto (use heuristic to select the best way of splitting device code). "
Expand Down
19 changes: 19 additions & 0 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,8 @@ static bool addSYCLDefaultTriple(Compilation &C,
/// Returns true if a triple is added to SYCLTriples, false otherwise
if (!C.getDriver().isSYCLDefaultTripleImplied())
return false;
if (C.getInputArgs().hasArg(options::OPT_fsycl_force_target_EQ))
return false;
for (const auto &SYCLTriple : SYCLTriples) {
if (SYCLTriple.getSubArch() == llvm::Triple::NoSubArch &&
SYCLTriple.isSPIR())
Expand Down Expand Up @@ -1057,6 +1059,14 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
C.getInputArgs().getLastArg(options::OPT_fsycl_device_code_split_EQ),
{"per_kernel", "per_source", "auto", "off"});

Arg *SYCLForceTarget =
getArgRequiringSYCLRuntime(options::OPT_fsycl_force_target_EQ);
if (SYCLForceTarget) {
StringRef Val(SYCLForceTarget->getValue());
llvm::Triple TT(MakeSYCLDeviceTriple(Val));
if (!isValidSYCLTriple(TT))
Diag(clang::diag::err_drv_invalid_sycl_target) << Val;
}
bool HasSYCLTargetsOption = SYCLTargets || SYCLLinkTargets || SYCLAddTargets;
llvm::StringMap<StringRef> FoundNormalizedTriples;
llvm::SmallVector<llvm::Triple, 4> UniqueSYCLTriplesVec;
Expand All @@ -1066,6 +1076,15 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
Arg *SYCLTargetsValues = SYCLTargets ? SYCLTargets : SYCLLinkTargets;
if (SYCLTargetsValues) {
if (SYCLTargetsValues->getNumValues()) {

// Multiple targets are currently not supported when using
// -fsycl-force-target as the bundler does not allow for multiple
// outputs of the same target.
if (SYCLForceTarget && SYCLTargetsValues->getNumValues() > 1)
Diag(clang::diag::err_drv_multiple_target_with_forced_target)
<< SYCLTargetsValues->getAsString(C.getInputArgs())
<< SYCLForceTarget->getAsString(C.getInputArgs());

for (StringRef Val : SYCLTargetsValues->getValues()) {
llvm::Triple TT(MakeSYCLDeviceTriple(Val));
if (!isValidSYCLTriple(TT)) {
Expand Down
11 changes: 10 additions & 1 deletion clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8916,7 +8916,16 @@ void OffloadBundler::ConstructJobMultipleOutputs(
Triples += ',';
Triples += Action::GetOffloadKindName(Dep.DependentOffloadKind);
Triples += '-';
Triples += Dep.DependentToolChain->getTriple().normalize();
// When -fsycl-force-target is used, this value overrides the expected
// output type we are unbundling.
if (Dep.DependentOffloadKind == Action::OFK_SYCL &&
TCArgs.hasArg(options::OPT_fsycl_force_target_EQ)) {
StringRef Val(
TCArgs.getLastArg(options::OPT_fsycl_force_target_EQ)->getValue());
llvm::Triple TT(C.getDriver().MakeSYCLDeviceTriple(Val));
Triples += TT.normalize();
} else
Triples += Dep.DependentToolChain->getTriple().normalize();
if ((Dep.DependentOffloadKind == Action::OFK_HIP ||
Dep.DependentOffloadKind == Action::OFK_OpenMP ||
Dep.DependentOffloadKind == Action::OFK_Cuda ||
Expand Down
26 changes: 26 additions & 0 deletions clang/test/Driver/sycl-force-target.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/// Verify the usage of -fsycl-force-target applies to all expected unbundlings
// RUN: touch %t.o
// RUN: %clangxx -fsycl -fsycl-targets=spir64_gen -fsycl-force-target=spir64 \
// RUN: %s --sysroot=%S/Inputs/SYCL %t.o -### 2>&1 \
// RUN: | FileCheck %s -check-prefix=CHECK_FORCE_TARGET
// RUN: %clangxx -fsycl -fsycl-targets=spir64_gen \
// RUN: -fsycl-force-target=spir64-unknown-unknown \
// RUN: %s --sysroot=%S/Inputs/SYCL %t.o -### 2>&1 \
// RUN: | FileCheck %s -check-prefixes=CHECK_FORCE_TARGET,CHECK_FORCE_TARGET_GEN
// RUN: %clangxx -fsycl -fsycl-targets=spir64_x86_64 \
// RUN: -fsycl-force-target=spir64 %s \
// RUN: --sysroot=%S/Inputs/SYCL %t.o -### 2>&1 \
// RUN: | FileCheck %s -check-prefixes=CHECK_FORCE_TARGET,CHECK_FORCE_TARGET_CPU
// CHECK_FORCE_TARGET: clang-offload-bundler{{.*}} "-type=o" "-targets=host-{{.*}},sycl-spir64-unknown-unknown" "-input={{.*}}" "-output={{.*}}" "-output=[[DEVICEOBJECTOUT:.+]]" "-unbundle" "-allow-missing-bundles"
// CHECK_FORCE_TARGET: spirv-to-ir-wrapper{{.*}} "[[DEVICEOBJECTOUT]]" "-o" "[[DEVICEOBJECTBC:.+\.bc]]"
// CHECK_FORCE_TARGET: llvm-link{{.*}} "[[DEVICEOBJECTBC]]"{{.*}} "-o" "[[DEVICEOBJLINKED:.+\.bc]]" "--suppress-warnings"
// CHECK_FORCE_TARGET: clang-offload-bundler{{.*}} "-type=o" "-targets=sycl-spir64-unknown-unknown" "-input={{.*}}libsycl-complex{{.*}}" "-output={{.*}}libsycl-complex-{{.*}}" "-unbundle"
// CHECK_FORCE_TARGET_GEN: llvm-foreach{{.*}} {{.*}}ocloc{{.*}}
// CHECK_FORCE_TARGET_CPU: llvm-foreach{{.*}} {{.*}}opencl-aot{{.*}}

/// -fsycl-force-target is only valid with -fsycl-target with single targets
// RUN: %clangxx -fsycl -fsycl-targets=spir64_gen,spir64_x86_64 \
// RUN: -fsycl-force-target=spir64 %s -### 2>&1 \
// RUN: | FileCheck %s -check-prefix=MULTIPLE_TARGET
// MULTIPLE_TARGET: error: multiple target usage with '-fsycl-targets=spir64_gen,spir64_x86_64' is not supported with '-fsycl-force-target=spir64'

8 changes: 8 additions & 0 deletions sycl/doc/UsersManual.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,14 @@ and not recommended to use in production environment.

NOTE: This option is currently only supported on Linux.

**`-fsycl-force-target=<T>`**

When used along with '-fsycl-targets', force the device object being
unbundled to match the target <T> given. This allows the user to override
the expected unbundling type even though the target given does not match.
The forced target applies to all objects, archives and default device
libraries.

## Intel FPGA specific options

**`-fintelfpga`**
Expand Down