Skip to content

Commit 5fcc96e

Browse files
committed
[Driver][SYCL] refactor -fsycl-device-only behaviors
Update -fsycl-device-only to go through the offload path, effectively removing the host dependencies when it is used. This allows for a cleaner representation of SYCL device specific compilation needs.
1 parent e31b94e commit 5fcc96e

File tree

3 files changed

+43
-54
lines changed

3 files changed

+43
-54
lines changed

clang/lib/Driver/Driver.cpp

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -792,9 +792,10 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
792792
// the -fsycl-targets, -fsycl-add-targets or -fsycl-link-targets option.
793793
// If -fsycl is supplied without any of these we will assume SPIR-V.
794794
// Use of -fsycl-device-only overrides -fsycl.
795-
bool HasValidSYCLRuntime = (C.getInputArgs().hasFlag(options::OPT_fsycl,
796-
options::OPT_fno_sycl, false) &&
797-
!C.getInputArgs().hasArg(options::OPT_fsycl_device_only));
795+
bool HasValidSYCLRuntime =
796+
(C.getInputArgs().hasFlag(options::OPT_fsycl, options::OPT_fno_sycl,
797+
false) ||
798+
C.getInputArgs().hasArg(options::OPT_fsycl_device_only));
798799

799800
// A mechanism for retrieving SYCL-specific options, erroring out
800801
// if SYCL offloading wasn't enabled prior to that
@@ -913,11 +914,18 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
913914
} else {
914915
// If -fsycl is supplied without -fsycl-*targets we will assume SPIR-V
915916
// unless -fintelfpga is supplied, which uses SPIR-V with fpga AOT.
916-
if (HasValidSYCLRuntime) {
917+
// For -fsycl-device-only, we also setup the implied triple as needed.
918+
StringRef SYCLTargetArch;
919+
if (C.getInputArgs().hasArg(options::OPT_fsycl_device_only))
920+
if (C.getDefaultToolChain().getTriple().getArch() == llvm::Triple::x86)
921+
SYCLTargetArch = "spir";
922+
else
923+
SYCLTargetArch = "spir64";
924+
else if (HasValidSYCLRuntime)
917925
// Triple for -fintelfpga is spir64_fpga-unknown-unknown-sycldevice.
918-
const char *SYCLTargetArch = SYCLfpga ? "spir64_fpga" : "spir64";
926+
SYCLTargetArch = SYCLfpga ? "spir64_fpga" : "spir64";
927+
if (!SYCLTargetArch.empty())
919928
UniqueSYCLTriplesVec.push_back(MakeSYCLDeviceTriple(SYCLTargetArch));
920-
}
921929
}
922930
// We'll need to use the SYCL and host triples as the key into
923931
// getOffloadingDeviceToolChain, because the device toolchains we're
@@ -3700,10 +3708,25 @@ class OffloadingActionBuilder final {
37003708
// The host depends on the generated integrated header from the device
37013709
// compilation.
37023710
if (CurPhase == phases::Compile) {
3711+
bool SYCLDeviceOnly = Args.hasArg(options::OPT_fsycl_device_only);
37033712
for (Action *&A : SYCLDeviceActions) {
37043713
DeviceCompilerInput =
37053714
C.MakeAction<CompileJobAction>(A, types::TY_SYCL_Header);
3706-
A = C.MakeAction<CompileJobAction>(A, types::TY_LLVM_BC);
3715+
types::ID OutputType = types::TY_LLVM_BC;
3716+
if (SYCLDeviceOnly) {
3717+
if (Args.hasArg(options::OPT_S)) {
3718+
OutputType = types::TY_LLVM_IR;
3719+
}
3720+
if (Args.hasFlag(options::OPT_fno_sycl_use_bitcode,
3721+
options::OPT_fsycl_use_bitcode, false)) {
3722+
auto *BackendAction =
3723+
C.MakeAction<BackendJobAction>(A, types::TY_LLVM_BC);
3724+
A = C.MakeAction<SPIRVTranslatorJobAction>(
3725+
BackendAction, types::TY_SPIRV);
3726+
break;
3727+
}
3728+
}
3729+
A = C.MakeAction<CompileJobAction>(A, OutputType);
37073730
}
37083731
const auto *TC = ToolChains.front();
37093732
const char *BoundArch = nullptr;
@@ -3713,7 +3736,7 @@ class OffloadingActionBuilder final {
37133736
// Clear the input file, it is already a dependence to a host
37143737
// action.
37153738
DeviceCompilerInput = nullptr;
3716-
return ABRT_Success;
3739+
return SYCLDeviceOnly ? ABRT_Ignore_Host : ABRT_Success;
37173740
}
37183741

37193742
// Backend/Assemble actions are obsolete for the SYCL device side
@@ -4351,8 +4374,8 @@ class OffloadingActionBuilder final {
43514374
Arg *SYCLTargets =
43524375
C.getInputArgs().getLastArg(options::OPT_fsycl_targets_EQ);
43534376
Arg *SYCLAddTargets = Args.getLastArg(options::OPT_fsycl_add_targets_EQ);
4354-
bool HasValidSYCLRuntime = C.getInputArgs().hasFlag(options::OPT_fsycl,
4355-
options::OPT_fno_sycl, false);
4377+
bool HasValidSYCLRuntime = C.getInputArgs().hasFlag(
4378+
options::OPT_fsycl, options::OPT_fno_sycl, false);
43564379
bool SYCLfpgaTriple = false;
43574380
if (SYCLTargets || SYCLAddTargets) {
43584381
if (SYCLTargets) {
@@ -5411,19 +5434,6 @@ Action *Driver::ConstructPhaseAction(
54115434
Args.hasArg(options::OPT_S) ? types::TY_LLVM_IR : types::TY_LLVM_BC;
54125435
return C.MakeAction<BackendJobAction>(Input, Output);
54135436
}
5414-
if (Args.hasArg(options::OPT_fsycl_device_only)) {
5415-
types::ID OutputType =
5416-
Args.hasArg(options::OPT_S) ? types::TY_LLVM_IR : types::TY_LLVM_BC;
5417-
if (Args.hasFlag(options::OPT_fsycl_use_bitcode,
5418-
options::OPT_fno_sycl_use_bitcode, true))
5419-
return C.MakeAction<BackendJobAction>(Input, OutputType);
5420-
// Use of -fsycl-device-only creates a bitcode file, we need to translate
5421-
// that to a SPIR-V file with -fno-sycl-use-bitcode
5422-
auto *BackendAction =
5423-
C.MakeAction<BackendJobAction>(Input, types::TY_LLVM_BC);
5424-
return C.MakeAction<SPIRVTranslatorJobAction>(BackendAction,
5425-
types::TY_SPIRV);
5426-
}
54275437
return C.MakeAction<BackendJobAction>(Input, types::TY_PP_Asm);
54285438
}
54295439
case phases::Assemble:

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,8 +1232,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
12321232
if (JA.isOffloading(Action::OFK_HIP))
12331233
getToolChain().AddHIPIncludeArgs(Args, CmdArgs);
12341234

1235-
if (JA.isOffloading(Action::OFK_SYCL) ||
1236-
Args.hasArg(options::OPT_fsycl_device_only))
1235+
if (JA.isOffloading(Action::OFK_SYCL))
12371236
toolchains::SYCLToolChain::AddSYCLIncludeArgs(D, Args, CmdArgs);
12381237

12391238
// If we are offloading to a target via OpenMP we need to include the
@@ -4029,24 +4028,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
40294028
const ArgList &Args, const char *LinkingOutput) const {
40304029
const auto &TC = getToolChain();
40314030
const llvm::Triple &RawTriple = TC.getTriple();
4032-
llvm::Triple Triple = TC.getEffectiveTriple();
4031+
const llvm::Triple &Triple = TC.getEffectiveTriple();
4032+
const std::string &TripleStr = Triple.getTriple();
40334033

40344034
bool KernelOrKext =
40354035
Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
40364036
const Driver &D = TC.getDriver();
40374037
ArgStringList CmdArgs;
40384038

4039-
// -fsycl-device-only implies a SPIRV arch triple. Do not set if current
4040-
// effective triple is SYCLDevice
4041-
if (Args.hasArg(options::OPT_fsycl_device_only) &&
4042-
Triple.getEnvironment() != llvm::Triple::SYCLDevice) {
4043-
const char *SYCLTargetArch = "spir64";
4044-
if (C.getDefaultToolChain().getTriple().getArch() == llvm::Triple::x86)
4045-
SYCLTargetArch = "spir";
4046-
Triple = C.getDriver().MakeSYCLDeviceTriple(SYCLTargetArch);
4047-
}
4048-
const std::string &TripleStr = Triple.getTriple();
4049-
40504039
// Check number of inputs for sanity. We need at least one input.
40514040
assert(Inputs.size() >= 1 && "Must have at least one input.");
40524041
// CUDA/HIP compilation may have multiple inputs (source file + results of
@@ -4061,8 +4050,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
40614050
bool IsHIP = JA.isOffloading(Action::OFK_HIP);
40624051
bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP);
40634052
bool IsSYCLOffloadDevice = JA.isDeviceOffloading(Action::OFK_SYCL);
4064-
bool IsSYCL = JA.isOffloading(Action::OFK_SYCL) ||
4065-
Args.hasArg(options::OPT_fsycl_device_only);
4053+
bool IsSYCL = JA.isOffloading(Action::OFK_SYCL);
40664054
bool IsHeaderModulePrecompile = isa<HeaderModulePrecompileJobAction>(JA);
40674055
assert((IsCuda || IsHIP || (IsOpenMPDevice && Inputs.size() == 2) || IsSYCL ||
40684056
IsHeaderModulePrecompile || Inputs.size() == 1) &&
@@ -4118,9 +4106,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
41184106
// step, and being part of the SYCL tool chain causes the incorrect target.
41194107
// FIXME - Is it possible to retain host environment when on a target
41204108
// device toolchain.
4121-
bool UseSYCLTriple =
4122-
IsSYCLDevice && (!IsSYCL || IsSYCLOffloadDevice ||
4123-
Args.hasArg(options::OPT_fsycl_device_only));
4109+
bool UseSYCLTriple = IsSYCLDevice && (!IsSYCL || IsSYCLOffloadDevice);
41244110

41254111
// Adjust IsWindowsXYZ for CUDA/HIP/SYCL compilations. Even when compiling in
41264112
// device mode (i.e., getToolchain().getTriple() is NVPTX/AMDGCN, not
@@ -4222,9 +4208,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
42224208

42234209
// Pass the triple of host when doing SYCL
42244210
llvm::Triple AuxT = C.getDefaultToolChain().getTriple();
4225-
if (Args.hasArg(options::OPT_fsycl_device_only) &&
4226-
RawTriple.getEnvironment() == llvm::Triple::SYCLDevice)
4227-
AuxT = llvm::Triple(llvm::sys::getProcessTriple());
42284211
std::string NormalizedTriple = AuxT.normalize();
42294212
CmdArgs.push_back("-aux-triple");
42304213
CmdArgs.push_back(Args.MakeArgString(NormalizedTriple));
@@ -6365,8 +6348,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
63656348
// SYCL library is guaranteed to work correctly only with dynamic
63666349
// MSVC runtime.
63676350
llvm::Triple AuxT = C.getDefaultToolChain().getTriple();
6368-
if (Args.hasFlag(options::OPT_fsycl_device_only, OptSpecifier(), false))
6369-
AuxT = llvm::Triple(llvm::sys::getProcessTriple());
63706351
if (AuxT.isWindowsMSVCEnvironment()) {
63716352
CmdArgs.push_back("-D_MT");
63726353
CmdArgs.push_back("-D_DLL");
@@ -6891,7 +6872,6 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
68916872
unsigned RTOptionID = options::OPT__SLASH_MT;
68926873
bool isNVPTX = getToolChain().getTriple().isNVPTX();
68936874
bool isSYCLDevice =
6894-
Args.hasArg(options::OPT_fsycl_device_only) ||
68956875
getToolChain().getTriple().getEnvironment() == llvm::Triple::SYCLDevice;
68966876
bool isSYCL = Args.hasArg(options::OPT_fsycl) || isSYCLDevice;
68976877
// For SYCL Windows, /MD is the default.
@@ -7906,8 +7886,7 @@ void SPIRVTranslator::ConstructJob(Compilation &C, const JobAction &JA,
79067886

79077887
TranslatorArgs.push_back("-o");
79087888
TranslatorArgs.push_back(Output.getFilename());
7909-
if (getToolChain().getTriple().isSYCLDeviceEnvironment() ||
7910-
TCArgs.hasArg(options::OPT_fsycl_device_only)) {
7889+
if (getToolChain().getTriple().isSYCLDeviceEnvironment()) {
79117890
TranslatorArgs.push_back("-spirv-max-version=1.1");
79127891
TranslatorArgs.push_back("-spirv-debug-info-version=legacy");
79137892
// Prevent crash in the translator if input IR contains DIExpression

clang/test/Driver/sycl.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,10 @@
7070

7171
/// Verify -fsycl-device-only phases
7272
// RUN: %clang -### -ccc-print-phases -fsycl-device-only %s 2>&1 | FileCheck %s --check-prefix=DEFAULT-PHASES
73-
// DEFAULT-PHASES: 0: input, "{{.*}}", c++
74-
// DEFAULT-PHASES: 1: preprocessor, {0}, c++-cpp-output
75-
// DEFAULT-PHASES: 2: compiler, {1}, ir
76-
// DEFAULT-PHASES: 3: backend, {2}, ir
73+
// DEFAULT-PHASES: 0: input, "{{.*}}", c++, (device-sycl)
74+
// DEFAULT-PHASES: 1: preprocessor, {0}, c++-cpp-output, (device-sycl)
75+
// DEFAULT-PHASES: 2: compiler, {1}, ir, (device-sycl)
76+
// DEFAULT-PHASES: 3: offload, "device-sycl (spir64-unknown-unknown-sycldevice)" {2}, ir
7777
// DEFAULT-PHASES-NOT: linker
7878

7979
// -fsycl-help tests

0 commit comments

Comments
 (0)