Skip to content

Commit 3fdc746

Browse files
committed
Reland - [Driver][SYCL] Add initial SYCL offload compilation support (#107493)
Introduces the SYCL based toolchain and initial toolchain construction when using the '-fsycl' option. This option will enable SYCL based offloading, creating a SPIR-V based IR file packaged into the compiled host object. This includes early support for creating the host/device object using the new offloading model. The device object is created using the spir64-unknown-unknown target triple. New/Updated Options: -fsycl Enables SYCL offloading for host and device -fsycl-device-only Enables device only compilation for SYCL -fsycl-host-only Enables host only compilation for SYCL RFC Reference: https://discourse.llvm.org/t/rfc-sycl-driver-enhancements/74092 Was reverted due to buildbot issues. Contains additional fixes to pull in the SYCL header dependencies to other toolchains.
1 parent 6f68d03 commit 3fdc746

File tree

23 files changed

+579
-28
lines changed

23 files changed

+579
-28
lines changed

clang/include/clang/Driver/Action.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ class Action {
9494
OFK_Cuda = 0x02,
9595
OFK_OpenMP = 0x04,
9696
OFK_HIP = 0x08,
97+
OFK_SYCL = 0x10,
9798
};
9899

99100
static const char *getClassName(ActionClass AC);

clang/include/clang/Driver/Options.td

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,8 @@ def opencl_Group : OptionGroup<"<opencl group>">, Group<f_Group>,
182182
DocName<"OpenCL options">;
183183

184184
def sycl_Group : OptionGroup<"<SYCL group>">, Group<f_Group>,
185-
DocName<"SYCL options">;
185+
DocName<"SYCL options">,
186+
Visibility<[ClangOption, CLOption]>;
186187

187188
def cuda_Group : OptionGroup<"<CUDA group>">, Group<f_Group>,
188189
DocName<"CUDA options">,
@@ -6782,16 +6783,21 @@ defm : FlangIgnoredDiagOpt<"frontend-loop-interchange">;
67826783
defm : FlangIgnoredDiagOpt<"target-lifetime">;
67836784

67846785
// C++ SYCL options
6786+
let Group = sycl_Group in {
67856787
def fsycl : Flag<["-"], "fsycl">,
6786-
Visibility<[ClangOption, CLOption]>,
6787-
Group<sycl_Group>, HelpText<"Enables SYCL kernels compilation for device">;
6788+
HelpText<"Enable SYCL C++ extensions">;
67886789
def fno_sycl : Flag<["-"], "fno-sycl">,
6789-
Visibility<[ClangOption, CLOption]>,
6790-
Group<sycl_Group>, HelpText<"Disables SYCL kernels compilation for device">;
6790+
HelpText<"Disable SYCL C++ extensions">;
6791+
def fsycl_device_only : Flag<["-"], "fsycl-device-only">,
6792+
Alias<offload_device_only>, HelpText<"Compile SYCL code for device only">;
6793+
def fsycl_host_only : Flag<["-"], "fsycl-host-only">,
6794+
Alias<offload_host_only>, HelpText<"Compile SYCL code for host only. Has no "
6795+
"effect on non-SYCL compilations">;
67916796
def sycl_link : Flag<["--"], "sycl-link">, Flags<[HelpHidden]>,
6792-
Visibility<[ClangOption, CLOption]>,
6793-
Group<sycl_Group>, HelpText<"Perform link through clang-sycl-linker via the target "
6797+
HelpText<"Perform link through clang-sycl-linker via the target "
67946798
"offloading toolchain.">;
6799+
} // let Group = sycl_Group
6800+
67956801
// OS-specific options
67966802
let Flags = [TargetSpecific] in {
67976803
defm android_pad_segment : BooleanFFlag<"android-pad-segment">, Group<f_Group>;

clang/include/clang/Driver/ToolChain.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,10 @@ class ToolChain {
762762
virtual void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
763763
llvm::opt::ArgStringList &CC1Args) const;
764764

765+
/// Add arguments to use system-specific SYCL includes.
766+
virtual void AddSYCLIncludeArgs(const llvm::opt::ArgList &DriverArgs,
767+
llvm::opt::ArgStringList &CC1Args) const;
768+
765769
/// Add arguments to use MCU GCC toolchain includes.
766770
virtual void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs,
767771
llvm::opt::ArgStringList &CC1Args) const;

clang/lib/Driver/Action.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ std::string Action::getOffloadingKindPrefix() const {
111111
return "device-openmp";
112112
case OFK_HIP:
113113
return "device-hip";
114+
case OFK_SYCL:
115+
return "device-sycl";
114116

115117
// TODO: Add other programming models here.
116118
}
@@ -128,6 +130,8 @@ std::string Action::getOffloadingKindPrefix() const {
128130
Res += "-hip";
129131
if (ActiveOffloadKindMask & OFK_OpenMP)
130132
Res += "-openmp";
133+
if (ActiveOffloadKindMask & OFK_SYCL)
134+
Res += "-sycl";
131135

132136
// TODO: Add other programming models here.
133137

@@ -164,6 +168,8 @@ StringRef Action::GetOffloadKindName(OffloadKind Kind) {
164168
return "openmp";
165169
case OFK_HIP:
166170
return "hip";
171+
case OFK_SYCL:
172+
return "sycl";
167173

168174
// TODO: Add other programming models here.
169175
}
@@ -320,7 +326,7 @@ void OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC,
320326
DeviceBoundArchs.push_back(BoundArch);
321327

322328
// Add each active offloading kind from a mask.
323-
for (OffloadKind OKind : {OFK_OpenMP, OFK_Cuda, OFK_HIP})
329+
for (OffloadKind OKind : {OFK_OpenMP, OFK_Cuda, OFK_HIP, OFK_SYCL})
324330
if (OKind & OffloadKindMask)
325331
DeviceOffloadKinds.push_back(OKind);
326332
}

clang/lib/Driver/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ add_clang_library(clangDriver
7777
ToolChains/RISCVToolchain.cpp
7878
ToolChains/Solaris.cpp
7979
ToolChains/SPIRV.cpp
80+
ToolChains/SYCL.cpp
8081
ToolChains/TCE.cpp
8182
ToolChains/UEFI.cpp
8283
ToolChains/VEToolchain.cpp

clang/lib/Driver/Compilation.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,11 @@ static bool ActionFailed(const Action *A,
214214
if (FailingCommands.empty())
215215
return false;
216216

217-
// CUDA/HIP can have the same input source code compiled multiple times so do
218-
// not compiled again if there are already failures. It is OK to abort the
219-
// CUDA pipeline on errors.
220-
if (A->isOffloading(Action::OFK_Cuda) || A->isOffloading(Action::OFK_HIP))
217+
// CUDA/HIP/SYCL can have the same input source code compiled multiple times
218+
// so do not compile again if there are already failures. It is OK to abort
219+
// the CUDA/HIP/SYCL pipeline on errors.
220+
if (A->isOffloading(Action::OFK_Cuda) || A->isOffloading(Action::OFK_HIP) ||
221+
A->isOffloading(Action::OFK_SYCL))
221222
return true;
222223

223224
for (const auto &CI : FailingCommands)

clang/lib/Driver/Driver.cpp

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "ToolChains/PS4CPU.h"
4444
#include "ToolChains/RISCVToolchain.h"
4545
#include "ToolChains/SPIRV.h"
46+
#include "ToolChains/SYCL.h"
4647
#include "ToolChains/Solaris.h"
4748
#include "ToolChains/TCE.h"
4849
#include "ToolChains/UEFI.h"
@@ -780,6 +781,41 @@ Driver::OpenMPRuntimeKind Driver::getOpenMPRuntime(const ArgList &Args) const {
780781
return RT;
781782
}
782783

784+
static const char *getDefaultSYCLArch(Compilation &C) {
785+
// If -fsycl is supplied we will assume SPIR-V
786+
if (C.getDefaultToolChain().getTriple().isArch32Bit())
787+
return "spirv32";
788+
return "spirv64";
789+
}
790+
791+
static llvm::Triple getSYCLDeviceTriple(StringRef TargetArch) {
792+
SmallVector<StringRef, 5> SYCLAlias = {"spir", "spir64", "spirv", "spirv32",
793+
"spirv64"};
794+
if (std::find(SYCLAlias.begin(), SYCLAlias.end(), TargetArch) !=
795+
SYCLAlias.end()) {
796+
llvm::Triple TargetTriple;
797+
TargetTriple.setArchName(TargetArch);
798+
TargetTriple.setVendor(llvm::Triple::UnknownVendor);
799+
TargetTriple.setOS(llvm::Triple::UnknownOS);
800+
return TargetTriple;
801+
}
802+
return llvm::Triple(TargetArch);
803+
}
804+
805+
static bool addSYCLDefaultTriple(Compilation &C,
806+
SmallVectorImpl<llvm::Triple> &SYCLTriples) {
807+
// Check current set of triples to see if the default has already been set.
808+
for (const auto &SYCLTriple : SYCLTriples) {
809+
if (SYCLTriple.getSubArch() == llvm::Triple::NoSubArch &&
810+
SYCLTriple.isSPIROrSPIRV())
811+
return false;
812+
}
813+
// Add the default triple as it was not found.
814+
llvm::Triple DefaultTriple = getSYCLDeviceTriple(getDefaultSYCLArch(C));
815+
SYCLTriples.insert(SYCLTriples.begin(), DefaultTriple);
816+
return true;
817+
}
818+
783819
void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
784820
InputList &Inputs) {
785821

@@ -993,6 +1029,42 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
9931029
return;
9941030
}
9951031

1032+
//
1033+
// SYCL
1034+
//
1035+
// We need to generate a SYCL toolchain if the user specified -fsycl.
1036+
bool IsSYCL = C.getInputArgs().hasFlag(options::OPT_fsycl,
1037+
options::OPT_fno_sycl, false);
1038+
1039+
auto argSYCLIncompatible = [&](OptSpecifier OptId) {
1040+
if (!IsSYCL)
1041+
return;
1042+
if (Arg *IncompatArg = C.getInputArgs().getLastArg(OptId))
1043+
Diag(clang::diag::err_drv_argument_not_allowed_with)
1044+
<< IncompatArg->getSpelling() << "-fsycl";
1045+
};
1046+
// -static-libstdc++ is not compatible with -fsycl.
1047+
argSYCLIncompatible(options::OPT_static_libstdcxx);
1048+
// -ffreestanding cannot be used with -fsycl
1049+
argSYCLIncompatible(options::OPT_ffreestanding);
1050+
1051+
llvm::SmallVector<llvm::Triple, 4> UniqueSYCLTriplesVec;
1052+
1053+
if (IsSYCL) {
1054+
addSYCLDefaultTriple(C, UniqueSYCLTriplesVec);
1055+
1056+
// We'll need to use the SYCL and host triples as the key into
1057+
// getOffloadingDeviceToolChain, because the device toolchains we're
1058+
// going to create will depend on both.
1059+
const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
1060+
for (const auto &TargetTriple : UniqueSYCLTriplesVec) {
1061+
auto SYCLTC = &getOffloadingDeviceToolChain(
1062+
C.getInputArgs(), TargetTriple, *HostTC, Action::OFK_SYCL);
1063+
assert(SYCLTC && "Could not create offloading device tool chain.");
1064+
C.addOffloadDeviceToolChain(SYCLTC, Action::OFK_SYCL);
1065+
}
1066+
}
1067+
9961068
//
9971069
// TODO: Add support for other offloading programming models here.
9981070
//
@@ -4183,6 +4255,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
41834255

41844256
bool UseNewOffloadingDriver =
41854257
C.isOffloadingHostKind(Action::OFK_OpenMP) ||
4258+
C.isOffloadingHostKind(Action::OFK_SYCL) ||
41864259
Args.hasFlag(options::OPT_foffload_via_llvm,
41874260
options::OPT_fno_offload_via_llvm, false) ||
41884261
Args.hasFlag(options::OPT_offload_new_driver,
@@ -4593,6 +4666,8 @@ Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,
45934666
Archs.insert(OffloadArchToString(OffloadArch::HIPDefault));
45944667
else if (Kind == Action::OFK_OpenMP)
45954668
Archs.insert(StringRef());
4669+
else if (Kind == Action::OFK_SYCL)
4670+
Archs.insert(StringRef());
45964671
} else {
45974672
Args.ClaimAllArgs(options::OPT_offload_arch_EQ);
45984673
Args.ClaimAllArgs(options::OPT_no_offload_arch_EQ);
@@ -4617,7 +4692,7 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
46174692
OffloadAction::DeviceDependences DDeps;
46184693

46194694
const Action::OffloadKind OffloadKinds[] = {
4620-
Action::OFK_OpenMP, Action::OFK_Cuda, Action::OFK_HIP};
4695+
Action::OFK_OpenMP, Action::OFK_Cuda, Action::OFK_HIP, Action::OFK_SYCL};
46214696

46224697
for (Action::OffloadKind Kind : OffloadKinds) {
46234698
SmallVector<const ToolChain *, 2> ToolChains;
@@ -4654,6 +4729,15 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
46544729
if (DeviceActions.empty())
46554730
return HostAction;
46564731

4732+
// FIXME: Do not collapse the host side for Darwin targets with SYCL offload
4733+
// compilations. The toolchain is not properly initialized for the target.
4734+
if (isa<CompileJobAction>(HostAction) && Kind == Action::OFK_SYCL &&
4735+
HostAction->getType() != types::TY_Nothing &&
4736+
C.getSingleOffloadToolChain<Action::OFK_Host>()
4737+
->getTriple()
4738+
.isOSDarwin())
4739+
HostAction->setCannotBeCollapsedWithNextDependentAction();
4740+
46574741
auto PL = types::getCompilationPhases(*this, Args, InputType);
46584742

46594743
for (phases::ID Phase : PL) {
@@ -4662,6 +4746,11 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
46624746
break;
46634747
}
46644748

4749+
// Assemble actions are not used for the SYCL device side. Both compile
4750+
// and backend actions are used to generate IR and textual IR if needed.
4751+
if (Kind == Action::OFK_SYCL && Phase == phases::Assemble)
4752+
continue;
4753+
46654754
auto TCAndArch = TCAndArchs.begin();
46664755
for (Action *&A : DeviceActions) {
46674756
if (A->getType() == types::TY_Nothing)
@@ -4900,6 +4989,7 @@ Action *Driver::ConstructPhaseAction(
49004989
return C.MakeAction<BackendJobAction>(Input, Output);
49014990
}
49024991
if (Args.hasArg(options::OPT_emit_llvm) ||
4992+
TargetDeviceOffloadKind == Action::OFK_SYCL ||
49034993
(((Input->getOffloadingToolChain() &&
49044994
Input->getOffloadingToolChain()->getTriple().isAMDGPU()) ||
49054995
TargetDeviceOffloadKind == Action::OFK_HIP) &&
@@ -6591,6 +6681,18 @@ const ToolChain &Driver::getOffloadingDeviceToolChain(
65916681
HostTC, Args);
65926682
break;
65936683
}
6684+
case Action::OFK_SYCL:
6685+
switch (Target.getArch()) {
6686+
case llvm::Triple::spir:
6687+
case llvm::Triple::spir64:
6688+
case llvm::Triple::spirv32:
6689+
case llvm::Triple::spirv64:
6690+
TC = std::make_unique<toolchains::SYCLToolChain>(*this, Target, HostTC,
6691+
Args);
6692+
break;
6693+
default:
6694+
break;
6695+
}
65946696
default:
65956697
break;
65966698
}

clang/lib/Driver/ToolChain.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,6 +1485,9 @@ void ToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
14851485
void ToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
14861486
ArgStringList &CC1Args) const {}
14871487

1488+
void ToolChain::AddSYCLIncludeArgs(const ArgList &DriverArgs,
1489+
ArgStringList &CC1Args) const {}
1490+
14881491
llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
14891492
ToolChain::getDeviceLibs(const ArgList &DriverArgs) const {
14901493
return {};

0 commit comments

Comments
 (0)