Skip to content
Merged
1 change: 1 addition & 0 deletions clang/include/clang/Driver/Action.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ class Action {
OFK_Cuda = 0x02,
OFK_OpenMP = 0x04,
OFK_HIP = 0x08,
OFK_SYCL = 0x10,
};

static const char *getClassName(ActionClass AC);
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Driver/Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,10 @@ class Driver {
/// @name Helper Methods
/// @{

/// MakeSYCLDeviceTriple - Returns the SYCL device triple for the
/// specified ArchType.
llvm::Triple MakeSYCLDeviceTriple(StringRef TargetArch = "spir64") const;

/// PrintActions - Print the list of actions.
void PrintActions(const Compilation &C) const;

Expand Down
15 changes: 10 additions & 5 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ def opencl_Group : OptionGroup<"<opencl group>">, Group<f_Group>,
DocName<"OpenCL options">;

def sycl_Group : OptionGroup<"<SYCL group>">, Group<f_Group>,
DocName<"SYCL options">;
DocName<"SYCL options">,
Visibility<[ClangOption, CLOption]>;

def cuda_Group : OptionGroup<"<CUDA group>">, Group<f_Group>,
DocName<"CUDA options">,
Expand Down Expand Up @@ -6691,12 +6692,16 @@ defm : FlangIgnoredDiagOpt<"frontend-loop-interchange">;
defm : FlangIgnoredDiagOpt<"target-lifetime">;

// C++ SYCL options
let Group = sycl_Group in {
def fsycl : Flag<["-"], "fsycl">,
Visibility<[ClangOption, CLOption]>,
Group<sycl_Group>, HelpText<"Enables SYCL kernels compilation for device">;
HelpText<"Enables SYCL kernels compilation for device">;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing help text could use some improvement,. How about simply "Enable SYCL C++ extensions" (and "Disable SYCL C++ extensions" for -fno-sycl below)?

def fno_sycl : Flag<["-"], "fno-sycl">,
Visibility<[ClangOption, CLOption]>,
Group<sycl_Group>, HelpText<"Disables SYCL kernels compilation for device">;
HelpText<"Disables SYCL kernels compilation for device">;
def fsycl_device_only : Flag<["-"], "fsycl-device-only">,
Alias<offload_device_only>, HelpText<"Compile SYCL kernels for device only">;
Comment on lines +6783 to +6784
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"kernels" seems out of place in the help text. How about more closely following the existing help text for CUDA? "Compile SYCL code for device only".

def fsycl_host_only : Flag<["-"], "fsycl-host-only">,
Alias<offload_host_only>, HelpText<"Compile SYCL kernels for host only">;
Comment on lines +6785 to +6786
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the above comment; "kernels" seems out of place here. There is also an interesting deviation from the equivalent option for CUDA:

def cuda_host_only : Flag<["--"], "cuda-host-only">, Alias<offload_host_only>,
  HelpText<"Compile CUDA code for host only. Has no effect on non-CUDA compilations.">;

SYCL should presumably follow suit here and add the "Has no effect on non-SYCL compilations." qualification (and the behavior of the option should presumably match).

} // let Group = sycl_Group

// OS-specific options
let Flags = [TargetSpecific] in {
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Driver/ToolChain.h
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,10 @@ class ToolChain {
virtual void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const;

/// Add arguments to use SYCL specific includes.
virtual void AddSYCLIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const;

/// Add arguments to use MCU GCC toolchain includes.
virtual void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const;
Expand Down
8 changes: 7 additions & 1 deletion clang/lib/Driver/Action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ std::string Action::getOffloadingKindPrefix() const {
return "device-openmp";
case OFK_HIP:
return "device-hip";
case OFK_SYCL:
return "device-sycl";

// TODO: Add other programming models here.
}
Expand All @@ -128,6 +130,8 @@ std::string Action::getOffloadingKindPrefix() const {
Res += "-hip";
if (ActiveOffloadKindMask & OFK_OpenMP)
Res += "-openmp";
if (ActiveOffloadKindMask & OFK_SYCL)
Res += "-sycl";

// TODO: Add other programming models here.

Expand Down Expand Up @@ -164,6 +168,8 @@ StringRef Action::GetOffloadKindName(OffloadKind Kind) {
return "openmp";
case OFK_HIP:
return "hip";
case OFK_SYCL:
return "sycl";

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

// Add each active offloading kind from a mask.
for (OffloadKind OKind : {OFK_OpenMP, OFK_Cuda, OFK_HIP})
for (OffloadKind OKind : {OFK_OpenMP, OFK_Cuda, OFK_HIP, OFK_SYCL})
if (OKind & OffloadKindMask)
DeviceOffloadKinds.push_back(OKind);
}
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ add_clang_library(clangDriver
ToolChains/PPCFreeBSD.cpp
ToolChains/InterfaceStubs.cpp
ToolChains/ZOS.cpp
ToolChains/SYCL.cpp
Types.cpp
XRayArgs.cpp

Expand Down
9 changes: 5 additions & 4 deletions clang/lib/Driver/Compilation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,10 +217,11 @@ static bool ActionFailed(const Action *A,
if (FailingCommands.empty())
return false;

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

for (const auto &CI : FailingCommands)
Expand Down
109 changes: 102 additions & 7 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "ToolChains/PS4CPU.h"
#include "ToolChains/RISCVToolchain.h"
#include "ToolChains/SPIRV.h"
#include "ToolChains/SYCL.h"
#include "ToolChains/Solaris.h"
#include "ToolChains/TCE.h"
#include "ToolChains/VEToolchain.h"
Expand Down Expand Up @@ -767,6 +768,26 @@ Driver::OpenMPRuntimeKind Driver::getOpenMPRuntime(const ArgList &Args) const {
return RT;
}

static const char *getDefaultSYCLArch(Compilation &C) {
if (C.getDefaultToolChain().getTriple().getArch() == llvm::Triple::x86)
return "spir";
return "spir64";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these perhaps be "spirv32" and "spirv64"? Driver::MakeSYCLDeviceTriple() below seems to indicate that distinct architecture targets exist and comments elsewhere indicate that SPIR-V (not SPIR) is the intended default.

}

static bool addSYCLDefaultTriple(Compilation &C,
SmallVectorImpl<llvm::Triple> &SYCLTriples) {
for (const auto &SYCLTriple : SYCLTriples) {
if (SYCLTriple.getSubArch() == llvm::Triple::NoSubArch &&
SYCLTriple.isSPIROrSPIRV())
return false;
}
// Add the default triple as it was not found.
llvm::Triple DefaultTriple =
C.getDriver().MakeSYCLDeviceTriple(getDefaultSYCLArch(C));
SYCLTriples.insert(SYCLTriples.begin(), DefaultTriple);
return true;
}

void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
InputList &Inputs) {

Expand Down Expand Up @@ -979,6 +1000,44 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
return;
}

//
// SYCL
//
// We need to generate a SYCL toolchain if the user specified -fsycl.
// If -fsycl is supplied we will assume SPIR-V.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is repeated below where it appears to be more relevant to the surrounding code. I recommend removing this one.

Suggested change
// If -fsycl is supplied we will assume SPIR-V.

bool IsSYCL =
C.getInputArgs().hasFlag(options::OPT_fsycl, options::OPT_fno_sycl,
false);

auto argSYCLIncompatible = [&](OptSpecifier OptId) {
if (!IsSYCL)
return;
if (Arg *IncompatArg = C.getInputArgs().getLastArg(OptId))
Diag(clang::diag::err_drv_argument_not_allowed_with)
<< IncompatArg->getSpelling() << "-fsycl";
};
// -static-libstdc++ is not compatible with -fsycl.
argSYCLIncompatible(options::OPT_static_libstdcxx);
// -ffreestanding cannot be used with -fsycl
argSYCLIncompatible(options::OPT_ffreestanding);

llvm::SmallVector<llvm::Triple, 4> UniqueSYCLTriplesVec;

// If -fsycl is supplied we will assume SPIR-V.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, this comment doesn't seem all that helpful here either. Perhaps it would be better colocated with addSYCLDefaultTriple(). Hmm, no, perhaps getDefaultSYCLArch() then?

if (IsSYCL) {
addSYCLDefaultTriple(C, UniqueSYCLTriplesVec);

// We'll need to use the SYCL and host triples as the key into
// getOffloadingDeviceToolChain, because the device toolchains we're
// going to create will depend on both.
const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
for (const auto &TT : UniqueSYCLTriplesVec) {
auto SYCLTC = &getOffloadingDeviceToolChain(C.getInputArgs(), TT, *HostTC,
Action::OFK_SYCL);
C.addOffloadDeviceToolChain(SYCLTC, Action::OFK_SYCL);
}
}

//
// TODO: Add support for other offloading programming models here.
//
Expand Down Expand Up @@ -2001,6 +2060,19 @@ void Driver::PrintHelp(bool ShowHidden) const {
VisibilityMask);
}

llvm::Triple Driver::MakeSYCLDeviceTriple(StringRef TargetArch) const {
SmallVector<StringRef, 5> SYCLAlias = { "spir", "spir64", "spirv32", "spirv64"};
if (std::find(SYCLAlias.begin(), SYCLAlias.end(), TargetArch) !=
SYCLAlias.end()) {
llvm::Triple TT;
TT.setArchName(TargetArch);
TT.setVendor(llvm::Triple::UnknownVendor);
TT.setOS(llvm::Triple::UnknownOS);
return TT;
}
return llvm::Triple(TargetArch);
}

void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const {
if (IsFlangMode()) {
OS << getClangToolFullVersion("flang-new") << '\n';
Expand Down Expand Up @@ -4155,6 +4227,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,

bool UseNewOffloadingDriver =
C.isOffloadingHostKind(Action::OFK_OpenMP) ||
C.isOffloadingHostKind(Action::OFK_SYCL) ||
Args.hasFlag(options::OPT_foffload_via_llvm,
options::OPT_fno_offload_via_llvm, false) ||
Args.hasFlag(options::OPT_offload_new_driver,
Expand Down Expand Up @@ -4565,6 +4638,8 @@ Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,
Archs.insert(OffloadArchToString(OffloadArch::HIPDefault));
else if (Kind == Action::OFK_OpenMP)
Archs.insert(StringRef());
else if (Kind == Action::OFK_SYCL)
Archs.insert(StringRef());
} else {
Args.ClaimAllArgs(options::OPT_offload_arch_EQ);
Args.ClaimAllArgs(options::OPT_no_offload_arch_EQ);
Expand All @@ -4589,7 +4664,7 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
OffloadAction::DeviceDependences DDeps;

const Action::OffloadKind OffloadKinds[] = {
Action::OFK_OpenMP, Action::OFK_Cuda, Action::OFK_HIP};
Action::OFK_OpenMP, Action::OFK_Cuda, Action::OFK_HIP, Action::OFK_SYCL};

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

// Assemble actions are not used for the SYCL device side. Both compile
// and backend actions are used to generate IR and textual IR if needed.
if (Kind == Action::OFK_SYCL && Phase == phases::Assemble)
continue;

auto TCAndArch = TCAndArchs.begin();
for (Action *&A : DeviceActions) {
if (A->getType() == types::TY_Nothing)
Expand Down Expand Up @@ -4867,12 +4947,13 @@ Action *Driver::ConstructPhaseAction(
return C.MakeAction<BackendJobAction>(Input, Output);
}
if (Args.hasArg(options::OPT_emit_llvm) ||
(((Input->getOffloadingToolChain() &&
Input->getOffloadingToolChain()->getTriple().isAMDGPU()) ||
TargetDeviceOffloadKind == Action::OFK_HIP) &&
(Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
false) ||
TargetDeviceOffloadKind == Action::OFK_OpenMP))) {
(TargetDeviceOffloadKind == Action::OFK_SYCL ||
(((Input->getOffloadingToolChain() &&
Input->getOffloadingToolChain()->getTriple().isAMDGPU()) ||
TargetDeviceOffloadKind == Action::OFK_HIP) &&
(Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
false) ||
TargetDeviceOffloadKind == Action::OFK_OpenMP)))) {
types::ID Output =
Args.hasArg(options::OPT_S) &&
(TargetDeviceOffloadKind == Action::OFK_None ||
Expand Down Expand Up @@ -6553,6 +6634,20 @@ const ToolChain &Driver::getOffloadingDeviceToolChain(
HostTC, Args);
break;
}
case Action::OFK_SYCL:
// TODO: Add additional Arch values for Ahead of Time support for SYCL.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since AoT support doesn't exist in Clang yet, this TODO comment seems premature.

switch (Target.getArch()) {
case llvm::Triple::spir:
case llvm::Triple::spir64:
case llvm::Triple::spirv32:
case llvm::Triple::spirv64:
TC = std::make_unique<toolchains::SYCLToolChain>(*this, Target, HostTC,
Args);
break;
default:
break;
}
break;
default:
break;
Comment on lines +6684 to 6689
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that something needs to be done in these default cases. In this context, TC is known to be null, but falling through leads to an unconditional dereference of it below. Some llvm_unreachable() or similar calls seem appropriate.

}
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1441,6 +1441,9 @@ void ToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
void ToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {}

void ToolChain::AddSYCLIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {}

llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
ToolChain::getDeviceLibs(const ArgList &DriverArgs) const {
return {};
Expand Down
Loading