Skip to content

Commit 4112034

Browse files
committed
[Driver][SYCL] Add initial SYCL offload compilation support
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
1 parent 9df92cb commit 4112034

File tree

20 files changed

+565
-26
lines changed

20 files changed

+565
-26
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/Driver.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,10 @@ class Driver {
582582
/// @name Helper Methods
583583
/// @{
584584

585+
/// MakeSYCLDeviceTriple - Returns the SYCL device triple for the
586+
/// specified ArchType.
587+
llvm::Triple MakeSYCLDeviceTriple(StringRef TargetArch = "spir64") const;
588+
585589
/// PrintActions - Print the list of actions.
586590
void PrintActions(const Compilation &C) const;
587591

clang/include/clang/Driver/Options.td

Lines changed: 10 additions & 5 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">,
@@ -6691,12 +6692,16 @@ defm : FlangIgnoredDiagOpt<"frontend-loop-interchange">;
66916692
defm : FlangIgnoredDiagOpt<"target-lifetime">;
66926693

66936694
// C++ SYCL options
6695+
let Group = sycl_Group in {
66946696
def fsycl : Flag<["-"], "fsycl">,
6695-
Visibility<[ClangOption, CLOption]>,
6696-
Group<sycl_Group>, HelpText<"Enables SYCL kernels compilation for device">;
6697+
HelpText<"Enables SYCL kernels compilation for device">;
66976698
def fno_sycl : Flag<["-"], "fno-sycl">,
6698-
Visibility<[ClangOption, CLOption]>,
6699-
Group<sycl_Group>, HelpText<"Disables SYCL kernels compilation for device">;
6699+
HelpText<"Disables SYCL kernels compilation for device">;
6700+
def fsycl_device_only : Flag<["-"], "fsycl-device-only">,
6701+
Alias<offload_device_only>, HelpText<"Compile SYCL kernels for device only">;
6702+
def fsycl_host_only : Flag<["-"], "fsycl-host-only">,
6703+
Alias<offload_host_only>, HelpText<"Compile SYCL kernels for host only">;
6704+
} // let Group = sycl_Group
67006705

67016706
// OS-specific options
67026707
let Flags = [TargetSpecific] in {

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 SYCL specific 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
@@ -85,6 +85,7 @@ add_clang_library(clangDriver
8585
ToolChains/PPCFreeBSD.cpp
8686
ToolChains/InterfaceStubs.cpp
8787
ToolChains/ZOS.cpp
88+
ToolChains/SYCL.cpp
8889
Types.cpp
8990
XRayArgs.cpp
9091

clang/lib/Driver/Compilation.cpp

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

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

226227
for (const auto &CI : FailingCommands)

clang/lib/Driver/Driver.cpp

Lines changed: 102 additions & 7 deletions
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/VEToolchain.h"
@@ -767,6 +768,26 @@ Driver::OpenMPRuntimeKind Driver::getOpenMPRuntime(const ArgList &Args) const {
767768
return RT;
768769
}
769770

771+
static const char *getDefaultSYCLArch(Compilation &C) {
772+
if (C.getDefaultToolChain().getTriple().getArch() == llvm::Triple::x86)
773+
return "spir";
774+
return "spir64";
775+
}
776+
777+
static bool addSYCLDefaultTriple(Compilation &C,
778+
SmallVectorImpl<llvm::Triple> &SYCLTriples) {
779+
for (const auto &SYCLTriple : SYCLTriples) {
780+
if (SYCLTriple.getSubArch() == llvm::Triple::NoSubArch &&
781+
SYCLTriple.isSPIROrSPIRV())
782+
return false;
783+
}
784+
// Add the default triple as it was not found.
785+
llvm::Triple DefaultTriple =
786+
C.getDriver().MakeSYCLDeviceTriple(getDefaultSYCLArch(C));
787+
SYCLTriples.insert(SYCLTriples.begin(), DefaultTriple);
788+
return true;
789+
}
790+
770791
void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
771792
InputList &Inputs) {
772793

@@ -979,6 +1000,44 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
9791000
return;
9801001
}
9811002

1003+
//
1004+
// SYCL
1005+
//
1006+
// We need to generate a SYCL toolchain if the user specified -fsycl.
1007+
// If -fsycl is supplied we will assume SPIR-V.
1008+
bool IsSYCL =
1009+
C.getInputArgs().hasFlag(options::OPT_fsycl, options::OPT_fno_sycl,
1010+
false);
1011+
1012+
auto argSYCLIncompatible = [&](OptSpecifier OptId) {
1013+
if (!IsSYCL)
1014+
return;
1015+
if (Arg *IncompatArg = C.getInputArgs().getLastArg(OptId))
1016+
Diag(clang::diag::err_drv_argument_not_allowed_with)
1017+
<< IncompatArg->getSpelling() << "-fsycl";
1018+
};
1019+
// -static-libstdc++ is not compatible with -fsycl.
1020+
argSYCLIncompatible(options::OPT_static_libstdcxx);
1021+
// -ffreestanding cannot be used with -fsycl
1022+
argSYCLIncompatible(options::OPT_ffreestanding);
1023+
1024+
llvm::SmallVector<llvm::Triple, 4> UniqueSYCLTriplesVec;
1025+
1026+
// If -fsycl is supplied we will assume SPIR-V.
1027+
if (IsSYCL) {
1028+
addSYCLDefaultTriple(C, UniqueSYCLTriplesVec);
1029+
1030+
// We'll need to use the SYCL and host triples as the key into
1031+
// getOffloadingDeviceToolChain, because the device toolchains we're
1032+
// going to create will depend on both.
1033+
const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
1034+
for (const auto &TT : UniqueSYCLTriplesVec) {
1035+
auto SYCLTC = &getOffloadingDeviceToolChain(C.getInputArgs(), TT, *HostTC,
1036+
Action::OFK_SYCL);
1037+
C.addOffloadDeviceToolChain(SYCLTC, Action::OFK_SYCL);
1038+
}
1039+
}
1040+
9821041
//
9831042
// TODO: Add support for other offloading programming models here.
9841043
//
@@ -2001,6 +2060,19 @@ void Driver::PrintHelp(bool ShowHidden) const {
20012060
VisibilityMask);
20022061
}
20032062

2063+
llvm::Triple Driver::MakeSYCLDeviceTriple(StringRef TargetArch) const {
2064+
SmallVector<StringRef, 5> SYCLAlias = { "spir", "spir64", "spirv32", "spirv64"};
2065+
if (std::find(SYCLAlias.begin(), SYCLAlias.end(), TargetArch) !=
2066+
SYCLAlias.end()) {
2067+
llvm::Triple TT;
2068+
TT.setArchName(TargetArch);
2069+
TT.setVendor(llvm::Triple::UnknownVendor);
2070+
TT.setOS(llvm::Triple::UnknownOS);
2071+
return TT;
2072+
}
2073+
return llvm::Triple(TargetArch);
2074+
}
2075+
20042076
void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const {
20052077
if (IsFlangMode()) {
20062078
OS << getClangToolFullVersion("flang-new") << '\n';
@@ -4155,6 +4227,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
41554227

41564228
bool UseNewOffloadingDriver =
41574229
C.isOffloadingHostKind(Action::OFK_OpenMP) ||
4230+
C.isOffloadingHostKind(Action::OFK_SYCL) ||
41584231
Args.hasFlag(options::OPT_foffload_via_llvm,
41594232
options::OPT_fno_offload_via_llvm, false) ||
41604233
Args.hasFlag(options::OPT_offload_new_driver,
@@ -4565,6 +4638,8 @@ Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,
45654638
Archs.insert(OffloadArchToString(OffloadArch::HIPDefault));
45664639
else if (Kind == Action::OFK_OpenMP)
45674640
Archs.insert(StringRef());
4641+
else if (Kind == Action::OFK_SYCL)
4642+
Archs.insert(StringRef());
45684643
} else {
45694644
Args.ClaimAllArgs(options::OPT_offload_arch_EQ);
45704645
Args.ClaimAllArgs(options::OPT_no_offload_arch_EQ);
@@ -4589,7 +4664,7 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
45894664
OffloadAction::DeviceDependences DDeps;
45904665

45914666
const Action::OffloadKind OffloadKinds[] = {
4592-
Action::OFK_OpenMP, Action::OFK_Cuda, Action::OFK_HIP};
4667+
Action::OFK_OpenMP, Action::OFK_Cuda, Action::OFK_HIP, Action::OFK_SYCL};
45934668

45944669
for (Action::OffloadKind Kind : OffloadKinds) {
45954670
SmallVector<const ToolChain *, 2> ToolChains;
@@ -4634,6 +4709,11 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
46344709
break;
46354710
}
46364711

4712+
// Assemble actions are not used for the SYCL device side. Both compile
4713+
// and backend actions are used to generate IR and textual IR if needed.
4714+
if (Kind == Action::OFK_SYCL && Phase == phases::Assemble)
4715+
continue;
4716+
46374717
auto TCAndArch = TCAndArchs.begin();
46384718
for (Action *&A : DeviceActions) {
46394719
if (A->getType() == types::TY_Nothing)
@@ -4867,12 +4947,13 @@ Action *Driver::ConstructPhaseAction(
48674947
return C.MakeAction<BackendJobAction>(Input, Output);
48684948
}
48694949
if (Args.hasArg(options::OPT_emit_llvm) ||
4870-
(((Input->getOffloadingToolChain() &&
4871-
Input->getOffloadingToolChain()->getTriple().isAMDGPU()) ||
4872-
TargetDeviceOffloadKind == Action::OFK_HIP) &&
4873-
(Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
4874-
false) ||
4875-
TargetDeviceOffloadKind == Action::OFK_OpenMP))) {
4950+
(TargetDeviceOffloadKind == Action::OFK_SYCL ||
4951+
(((Input->getOffloadingToolChain() &&
4952+
Input->getOffloadingToolChain()->getTriple().isAMDGPU()) ||
4953+
TargetDeviceOffloadKind == Action::OFK_HIP) &&
4954+
(Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
4955+
false) ||
4956+
TargetDeviceOffloadKind == Action::OFK_OpenMP)))) {
48764957
types::ID Output =
48774958
Args.hasArg(options::OPT_S) &&
48784959
(TargetDeviceOffloadKind == Action::OFK_None ||
@@ -6553,6 +6634,20 @@ const ToolChain &Driver::getOffloadingDeviceToolChain(
65536634
HostTC, Args);
65546635
break;
65556636
}
6637+
case Action::OFK_SYCL:
6638+
// TODO: Add additional Arch values for Ahead of Time support for SYCL.
6639+
switch (Target.getArch()) {
6640+
case llvm::Triple::spir:
6641+
case llvm::Triple::spir64:
6642+
case llvm::Triple::spirv32:
6643+
case llvm::Triple::spirv64:
6644+
TC = std::make_unique<toolchains::SYCLToolChain>(*this, Target, HostTC,
6645+
Args);
6646+
break;
6647+
default:
6648+
break;
6649+
}
6650+
break;
65566651
default:
65576652
break;
65586653
}

clang/lib/Driver/ToolChain.cpp

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

1444+
void ToolChain::AddSYCLIncludeArgs(const ArgList &DriverArgs,
1445+
ArgStringList &CC1Args) const {}
1446+
14441447
llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
14451448
ToolChain::getDeviceLibs(const ArgList &DriverArgs) const {
14461449
return {};

0 commit comments

Comments
 (0)