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
/// @{

/// getSYCLDeviceTriple - Returns the SYCL device triple for the
/// specified ArchType.
llvm::Triple getSYCLDeviceTriple(StringRef TargetArch = "spir64") const;
Comment on lines +585 to +587
Copy link
Contributor

Choose a reason for hiding this comment

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

It doesn't look like getSYCLDeviceTriple() needs to be exposed in the header. Can this just be a static function in Driver.cpp? There are similar static functions there for CUDA and HIP; see getNVIDIAOffloadTargetTriple() and getHIPOffloadTargetTriple(). I think this should follow that precedent if there isn't a good reason to deviate.


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

Expand Down
19 changes: 12 additions & 7 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 @@ -6774,16 +6775,20 @@ 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).

def sycl_link : Flag<["--"], "sycl-link">, Flags<[HelpHidden]>,
Visibility<[ClangOption, CLOption]>,
Group<sycl_Group>, HelpText<"Perform link through clang-sycl-linker via the target "
HelpText<"Perform link through clang-sycl-linker via the target "
"offloading toolchain.">;
} // let Group = sycl_Group

// OS-specific options
let Flags = [TargetSpecific] in {
defm android_pad_segment : BooleanFFlag<"android-pad-segment">, Group<f_Group>;
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 system-specific SYCL 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 @@ -77,6 +77,7 @@ add_clang_library(clangDriver
ToolChains/RISCVToolchain.cpp
ToolChains/Solaris.cpp
ToolChains/SPIRV.cpp
ToolChains/SYCL.cpp
ToolChains/TCE.cpp
ToolChains/UEFI.cpp
ToolChains/VEToolchain.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/HIP/SYCL 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
95 changes: 94 additions & 1 deletion 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/UEFI.h"
Expand Down Expand Up @@ -781,6 +782,27 @@ Driver::OpenMPRuntimeKind Driver::getOpenMPRuntime(const ArgList &Args) const {
return RT;
}

static const char *getDefaultSYCLArch(Compilation &C) {
// If -fsycl is supplied we will assume SPIR-V
if (C.getDefaultToolChain().getTriple().isArch32Bit())
return "spirv32";
return "spirv64";
}

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().getSYCLDeviceTriple(getDefaultSYCLArch(C));
SYCLTriples.insert(SYCLTriples.begin(), DefaultTriple);
return true;
}

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

Expand Down Expand Up @@ -994,6 +1016,41 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
return;
}

//
// SYCL
//
// We need to generate a SYCL toolchain if the user specified -fsycl.
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 (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 @@ -2027,6 +2084,20 @@ void Driver::PrintHelp(bool ShowHidden) const {
VisibilityMask);
}

llvm::Triple Driver::getSYCLDeviceTriple(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") << '\n';
Expand Down Expand Up @@ -4184,6 +4255,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 @@ -4594,6 +4666,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 @@ -4618,7 +4692,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 @@ -4663,6 +4737,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 @@ -4901,6 +4980,7 @@ Action *Driver::ConstructPhaseAction(
return C.MakeAction<BackendJobAction>(Input, Output);
}
if (Args.hasArg(options::OPT_emit_llvm) ||
TargetDeviceOffloadKind == Action::OFK_SYCL ||
(((Input->getOffloadingToolChain() &&
Input->getOffloadingToolChain()->getTriple().isAMDGPU()) ||
TargetDeviceOffloadKind == Action::OFK_HIP) &&
Expand Down Expand Up @@ -6592,6 +6672,19 @@ const ToolChain &Driver::getOffloadingDeviceToolChain(
HostTC, Args);
break;
}
case Action::OFK_SYCL:
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 @@ -1459,6 +1459,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