-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[Driver][SYCL] Add initial SYCL offload compilation support #107493
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
4112034
47cc846
8c29ad5
7884962
5e204cd
db45e5c
f57670e
05c7584
b810ae2
8a0826a
92cab9a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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">, | ||
|
|
@@ -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">; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
| 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
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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: 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 { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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" | ||
|
|
@@ -767,6 +768,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) { | ||
|
|
||
|
|
@@ -979,6 +1001,42 @@ 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. | ||
| // | ||
|
|
@@ -2001,6 +2059,19 @@ 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-new") << '\n'; | ||
|
|
@@ -4155,6 +4226,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, | ||
|
|
@@ -4565,6 +4637,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); | ||
|
|
@@ -4589,7 +4663,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; | ||
|
|
@@ -4634,6 +4708,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) | ||
|
|
@@ -4867,6 +4946,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) && | ||
|
|
@@ -6553,6 +6633,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
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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, |
||
| } | ||
|
|
||
There was a problem hiding this comment.
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 astaticfunction inDriver.cpp? There are similarstaticfunctions there for CUDA and HIP; seegetNVIDIAOffloadTargetTriple()andgetHIPOffloadTargetTriple(). I think this should follow that precedent if there isn't a good reason to deviate.