Skip to content

Commit c23c339

Browse files
authored
[Driver][SYCL] Refactor -fsycl-device-only behaviors (#2713)
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 ce3ac09 commit c23c339

File tree

5 files changed

+45
-56
lines changed

5 files changed

+45
-56
lines changed

clang/lib/Driver/Driver.cpp

Lines changed: 32 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,24 @@ 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+
if (Args.hasFlag(options::OPT_fno_sycl_use_bitcode,
3720+
options::OPT_fsycl_use_bitcode, false)) {
3721+
auto *CompileAction =
3722+
C.MakeAction<CompileJobAction>(A, types::TY_LLVM_BC);
3723+
A = C.MakeAction<SPIRVTranslatorJobAction>(CompileAction,
3724+
types::TY_SPIRV);
3725+
continue;
3726+
}
3727+
}
3728+
A = C.MakeAction<CompileJobAction>(A, OutputType);
37073729
}
37083730
const auto *TC = ToolChains.front();
37093731
const char *BoundArch = nullptr;
@@ -3713,7 +3735,7 @@ class OffloadingActionBuilder final {
37133735
// Clear the input file, it is already a dependence to a host
37143736
// action.
37153737
DeviceCompilerInput = nullptr;
3716-
return ABRT_Success;
3738+
return SYCLDeviceOnly ? ABRT_Ignore_Host : ABRT_Success;
37173739
}
37183740

37193741
// Backend/Assemble actions are obsolete for the SYCL device side
@@ -4351,8 +4373,8 @@ class OffloadingActionBuilder final {
43514373
Arg *SYCLTargets =
43524374
C.getInputArgs().getLastArg(options::OPT_fsycl_targets_EQ);
43534375
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);
4376+
bool HasValidSYCLRuntime = C.getInputArgs().hasFlag(
4377+
options::OPT_fsycl, options::OPT_fno_sycl, false);
43564378
bool SYCLfpgaTriple = false;
43574379
if (SYCLTargets || SYCLAddTargets) {
43584380
if (SYCLTargets) {
@@ -5411,19 +5433,6 @@ Action *Driver::ConstructPhaseAction(
54115433
Args.hasArg(options::OPT_S) ? types::TY_LLVM_IR : types::TY_LLVM_BC;
54125434
return C.MakeAction<BackendJobAction>(Input, Output);
54135435
}
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-
}
54275436
return C.MakeAction<BackendJobAction>(Input, types::TY_PP_Asm);
54285437
}
54295438
case phases::Assemble:

clang/lib/Driver/ToolChains/Clang.cpp

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

1241-
if (JA.isOffloading(Action::OFK_SYCL) ||
1242-
Args.hasArg(options::OPT_fsycl_device_only))
1241+
if (JA.isOffloading(Action::OFK_SYCL))
12431242
toolchains::SYCLToolChain::AddSYCLIncludeArgs(D, Args, CmdArgs);
12441243

12451244
// If we are offloading to a target via OpenMP we need to include the
@@ -4035,24 +4034,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
40354034
const ArgList &Args, const char *LinkingOutput) const {
40364035
const auto &TC = getToolChain();
40374036
const llvm::Triple &RawTriple = TC.getTriple();
4038-
llvm::Triple Triple = TC.getEffectiveTriple();
4037+
const llvm::Triple &Triple = TC.getEffectiveTriple();
4038+
const std::string &TripleStr = Triple.getTriple();
40394039

40404040
bool KernelOrKext =
40414041
Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
40424042
const Driver &D = TC.getDriver();
40434043
ArgStringList CmdArgs;
40444044

4045-
// -fsycl-device-only implies a SPIRV arch triple. Do not set if current
4046-
// effective triple is SYCLDevice
4047-
if (Args.hasArg(options::OPT_fsycl_device_only) &&
4048-
Triple.getEnvironment() != llvm::Triple::SYCLDevice) {
4049-
const char *SYCLTargetArch = "spir64";
4050-
if (C.getDefaultToolChain().getTriple().getArch() == llvm::Triple::x86)
4051-
SYCLTargetArch = "spir";
4052-
Triple = C.getDriver().MakeSYCLDeviceTriple(SYCLTargetArch);
4053-
}
4054-
const std::string &TripleStr = Triple.getTriple();
4055-
40564045
// Check number of inputs for sanity. We need at least one input.
40574046
assert(Inputs.size() >= 1 && "Must have at least one input.");
40584047
// CUDA/HIP compilation may have multiple inputs (source file + results of
@@ -4067,8 +4056,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
40674056
bool IsHIP = JA.isOffloading(Action::OFK_HIP);
40684057
bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP);
40694058
bool IsSYCLOffloadDevice = JA.isDeviceOffloading(Action::OFK_SYCL);
4070-
bool IsSYCL = JA.isOffloading(Action::OFK_SYCL) ||
4071-
Args.hasArg(options::OPT_fsycl_device_only);
4059+
bool IsSYCL = JA.isOffloading(Action::OFK_SYCL);
40724060
bool IsHeaderModulePrecompile = isa<HeaderModulePrecompileJobAction>(JA);
40734061
assert((IsCuda || IsHIP || (IsOpenMPDevice && Inputs.size() == 2) || IsSYCL ||
40744062
IsHeaderModulePrecompile || Inputs.size() == 1) &&
@@ -4124,9 +4112,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
41244112
// step, and being part of the SYCL tool chain causes the incorrect target.
41254113
// FIXME - Is it possible to retain host environment when on a target
41264114
// device toolchain.
4127-
bool UseSYCLTriple =
4128-
IsSYCLDevice && (!IsSYCL || IsSYCLOffloadDevice ||
4129-
Args.hasArg(options::OPT_fsycl_device_only));
4115+
bool UseSYCLTriple = IsSYCLDevice && (!IsSYCL || IsSYCLOffloadDevice);
41304116

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

42294215
// Pass the triple of host when doing SYCL
42304216
llvm::Triple AuxT = C.getDefaultToolChain().getTriple();
4231-
if (Args.hasArg(options::OPT_fsycl_device_only) &&
4232-
RawTriple.getEnvironment() == llvm::Triple::SYCLDevice)
4233-
AuxT = llvm::Triple(llvm::sys::getProcessTriple());
42344217
std::string NormalizedTriple = AuxT.normalize();
42354218
CmdArgs.push_back("-aux-triple");
42364219
CmdArgs.push_back(Args.MakeArgString(NormalizedTriple));
@@ -6371,8 +6354,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
63716354
// SYCL library is guaranteed to work correctly only with dynamic
63726355
// MSVC runtime.
63736356
llvm::Triple AuxT = C.getDefaultToolChain().getTriple();
6374-
if (Args.hasFlag(options::OPT_fsycl_device_only, OptSpecifier(), false))
6375-
AuxT = llvm::Triple(llvm::sys::getProcessTriple());
63766357
if (AuxT.isWindowsMSVCEnvironment()) {
63776358
CmdArgs.push_back("-D_MT");
63786359
CmdArgs.push_back("-D_DLL");
@@ -6897,7 +6878,6 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
68976878
unsigned RTOptionID = options::OPT__SLASH_MT;
68986879
bool isNVPTX = getToolChain().getTriple().isNVPTX();
68996880
bool isSYCLDevice =
6900-
Args.hasArg(options::OPT_fsycl_device_only) ||
69016881
getToolChain().getTriple().getEnvironment() == llvm::Triple::SYCLDevice;
69026882
bool isSYCL = Args.hasArg(options::OPT_fsycl) || isSYCLDevice;
69036883
// For SYCL Windows, /MD is the default.
@@ -7912,8 +7892,7 @@ void SPIRVTranslator::ConstructJob(Compilation &C, const JobAction &JA,
79127892

79137893
TranslatorArgs.push_back("-o");
79147894
TranslatorArgs.push_back(Output.getFilename());
7915-
if (getToolChain().getTriple().isSYCLDeviceEnvironment() ||
7916-
TCArgs.hasArg(options::OPT_fsycl_device_only)) {
7895+
if (getToolChain().getTriple().isSYCLDeviceEnvironment()) {
79177896
TranslatorArgs.push_back("-spirv-max-version=1.1");
79187897
TranslatorArgs.push_back("-spirv-debug-info-version=legacy");
79197898
// Prevent crash in the translator if input IR contains DIExpression

clang/lib/Driver/ToolChains/Cuda.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,8 @@ void CudaToolChain::addClangTargetOptions(
642642
CC1Args);
643643
}
644644

645-
auto NoLibSpirv = DriverArgs.hasArg(options::OPT_fno_sycl_libspirv);
645+
auto NoLibSpirv = DriverArgs.hasArg(options::OPT_fno_sycl_libspirv,
646+
options::OPT_fsycl_device_only);
646647
if (DeviceOffloadingKind == Action::OFK_SYCL && !NoLibSpirv) {
647648
std::string LibSpirvFile;
648649

clang/test/Driver/sycl.c

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

7474
/// Verify -fsycl-device-only phases
7575
// RUN: %clang -### -ccc-print-phases -fsycl-device-only %s 2>&1 | FileCheck %s --check-prefix=DEFAULT-PHASES
76-
// DEFAULT-PHASES: 0: input, "{{.*}}", c++
77-
// DEFAULT-PHASES: 1: preprocessor, {0}, c++-cpp-output
78-
// DEFAULT-PHASES: 2: compiler, {1}, ir
79-
// DEFAULT-PHASES: 3: backend, {2}, ir
76+
// DEFAULT-PHASES: 0: input, "{{.*}}", c++, (device-sycl)
77+
// DEFAULT-PHASES: 1: preprocessor, {0}, c++-cpp-output, (device-sycl)
78+
// DEFAULT-PHASES: 2: compiler, {1}, ir, (device-sycl)
79+
// DEFAULT-PHASES: 3: offload, "device-sycl (spir64-unknown-unknown-sycldevice)" {2}, ir
8080
// DEFAULT-PHASES-NOT: linker
8181

8282
// -fsycl-help tests

libclc/cmake/modules/AddLibclc.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ function(add_libclc_sycl_binding OUT_LIST)
219219
COMMAND ${CMAKE_COMMAND} -E make_directory
220220
${CMAKE_CURRENT_BINARY_DIR}/sycldevice-binding-${ARG_TRIPLE}
221221
COMMAND ${LLVM_CLANG}
222-
-target ${ARG_TRIPLE}-sycldevice
222+
-fsycl-targets=${ARG_TRIPLE}-sycldevice
223223
-fsycl
224224
-fsycl-device-only
225225
-Dcl_khr_fp64

0 commit comments

Comments
 (0)