From e1c99f1c8485a5311c067fae186f6421bfd94cd2 Mon Sep 17 00:00:00 2001 From: "Cai, Justin" Date: Wed, 24 Sep 2025 19:55:50 +0000 Subject: [PATCH 1/4] [SYCL] Enable new offload driver by default for SYCL --- clang/lib/Driver/Driver.cpp | 18 +++++++++++------- clang/lib/Driver/ToolChains/Clang.cpp | 12 +++++++----- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 46543ce5b2168..9b4a4b83ecd0d 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1403,7 +1403,7 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, std::string NormalizedName; bool UseNewOffload = (C.getArgs().hasFlag(options::OPT_offload_new_driver, - options::OPT_no_offload_new_driver, false)); + options::OPT_no_offload_new_driver, true)); NormalizedName = UseNewOffload ? TT.normalize() : getSYCLDeviceTriple(Triple).normalize(); @@ -1464,7 +1464,7 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, // Emit a diagnostic if '--offload-arch' is invoked without // '--offload-new driver' option. if (!C.getInputArgs().hasFlag(options::OPT_offload_new_driver, - options::OPT_no_offload_new_driver, false)) { + options::OPT_no_offload_new_driver, true)) { Diag(clang::diag::err_drv_sycl_offload_arch_new_driver); return; } @@ -2247,7 +2247,8 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) { TranslatedArgs->hasFlag(options::OPT_fopenmp_new_driver, options::OPT_no_offload_new_driver, true)) || TranslatedArgs->hasFlag(options::OPT_offload_new_driver, - options::OPT_no_offload_new_driver, false)) + options::OPT_no_offload_new_driver, + C->isOffloadingHostKind(Action::OFK_SYCL))) setUseNewOffloadingDriver(); // Construct the list of abstract actions to perform for this compilation. On @@ -7171,7 +7172,8 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, options::OPT_fno_offload_via_llvm, false) || Args.hasFlag(options::OPT_offload_new_driver, options::OPT_no_offload_new_driver, - C.isOffloadingHostKind(Action::OFK_Cuda)); + C.isOffloadingHostKind(Action::OFK_Cuda) || + C.isOffloadingHostKind(Action::OFK_SYCL)); bool HIPNoRDC = C.isOffloadingHostKind(Action::OFK_HIP) && @@ -8284,9 +8286,11 @@ Action *Driver::ConstructPhaseAction( (TargetDeviceOffloadKind == Action::OFK_None || offloadDeviceOnly() || (TargetDeviceOffloadKind == Action::OFK_HIP && - !Args.hasFlag(options::OPT_offload_new_driver, - options::OPT_no_offload_new_driver, - C.isOffloadingHostKind(Action::OFK_Cuda)))) + !Args.hasFlag( + options::OPT_offload_new_driver, + options::OPT_no_offload_new_driver, + C.isOffloadingHostKind(Action::OFK_Cuda) || + C.isOffloadingHostKind(Action::OFK_SYCL)))) ? types::TY_LLVM_IR : types::TY_LLVM_BC; return C.MakeAction(Input, Output); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 7926b8edd5821..ad16d263361ac 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5338,7 +5338,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, (JA.isHostOffloading(C.getActiveOffloadKinds()) && Args.hasFlag(options::OPT_offload_new_driver, options::OPT_no_offload_new_driver, - C.isOffloadingHostKind(Action::OFK_Cuda))); + C.isOffloadingHostKind(Action::OFK_Cuda) || + C.isOffloadingHostKind(Action::OFK_SYCL))); bool IsRDCMode = Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, IsSYCL); @@ -6025,9 +6026,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-emit-llvm-uselists"); if (IsUsingLTO) { - bool IsUsingOffloadNewDriver = - Args.hasFlag(options::OPT_offload_new_driver, - options::OPT_no_offload_new_driver, false); + bool IsUsingOffloadNewDriver = Args.hasFlag( + options::OPT_offload_new_driver, options::OPT_no_offload_new_driver, + C.isOffloadingHostKind(Action::OFK_SYCL)); Arg *SYCLSplitMode = Args.getLastArg(options::OPT_fsycl_device_code_split_EQ); bool IsDeviceCodeSplitDisabled = @@ -7603,7 +7604,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.append({"--offload-new-driver", "-foffload-via-llvm"}); } else if (Args.hasFlag(options::OPT_offload_new_driver, options::OPT_no_offload_new_driver, - C.isOffloadingHostKind(Action::OFK_Cuda))) { + C.isOffloadingHostKind(Action::OFK_Cuda) || + C.isOffloadingHostKind(Action::OFK_SYCL))) { CmdArgs.push_back("--offload-new-driver"); } From a9b5c14f4e418fbbc9f7058442c85e3c8cf2de1e Mon Sep 17 00:00:00 2001 From: "Cai, Justin" Date: Fri, 3 Oct 2025 21:16:13 +0000 Subject: [PATCH 2/4] link more libraries for nvptx --- clang/lib/Driver/ToolChains/Clang.cpp | 70 ++++++++++++++++++--------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index ad16d263361ac..e7b3c4a320819 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -11313,6 +11313,29 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, // populated with device binaries for all target triples in the current // compilation flow. + SmallString<128> DeviceLibDir(D.Dir); + llvm::sys::path::append(DeviceLibDir, "..", "lib"); + // Check the library location candidates for the the libsycl-crt library + // and use that location. Base the location on relative to driver if this + // is not resolved. + SmallVector, 4> LibLocCandidates; + SYCLInstallationDetector SYCLInstallation(D); + SYCLInstallation.getSYCLDeviceLibPath(LibLocCandidates); + SmallString<128> LibName("libsycl-crt"); + bool IsNewOffload = D.getUseNewOffloadingDriver(); + StringRef LibSuffix = TheTriple.isWindowsMSVCEnvironment() + ? (IsNewOffload ? ".new.obj" : ".obj") + : (IsNewOffload ? ".new.o" : ".o"); + llvm::sys::path::replace_extension(LibName, LibSuffix); + for (const auto &LibLoc : LibLocCandidates) { + SmallString<128> FullLibName(LibLoc); + llvm::sys::path::append(FullLibName, LibName); + if (llvm::sys::fs::exists(FullLibName)) { + DeviceLibDir = LibLoc; + break; + } + } + // Create a comma separated list to pass along to the linker wrapper. SmallString<256> LibList; llvm::Triple TargetTriple; @@ -11321,7 +11344,30 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, llvm::make_range(ToolChainRange.first, ToolChainRange.second)) { const ToolChain *TC = I.second; // Note: For AMD targets, we do not pass any SYCL device libraries. - if (TC->getTriple().isSPIROrSPIRV() || TC->getTriple().isNVPTX()) { + if (TC->getTriple().isNVPTX()) { + auto NVPTXLibNames = + SYCL::getDeviceLibraries(C, llvm::Triple("nvptx64-nvidia-cuda"), + /*UseAOTLink=*/false); + SmallVector, 8> NVPTXLibPaths; + for (const auto &LibName : NVPTXLibNames) { + SmallString<0> FullLibName(DeviceLibDir); + llvm::sys::path::append(FullLibName, LibName); + NVPTXLibPaths.push_back(FullLibName); + } + if (const char *LibSpirvFile = SYCLInstallation.findLibspirvPath( + TC->getTriple(), Args, *TC->getAuxTriple())) { + NVPTXLibPaths.push_back(StringRef(LibSpirvFile)); + } + + if (NVPTXLibPaths.size() != 0) + CmdArgs.push_back( + Args.MakeArgString(Twine("-sycl-nvptx-device-libraries=") + + llvm::join(NVPTXLibPaths, ","))); + + continue; + } + + if (TC->getTriple().isSPIROrSPIRV()) { TargetTriple = TC->getTriple(); SmallVector SYCLDeviceLibs; bool IsSPIR = TargetTriple.isSPIROrSPIRV(); @@ -11347,28 +11393,6 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, // -sycl-device-library-location= provides the location in which the // SYCL device libraries can be found. - SmallString<128> DeviceLibDir(D.Dir); - llvm::sys::path::append(DeviceLibDir, "..", "lib"); - // Check the library location candidates for the the libsycl-crt library - // and use that location. Base the location on relative to driver if this - // is not resolved. - SmallVector, 4> LibLocCandidates; - SYCLInstallationDetector SYCLInstallation(D); - SYCLInstallation.getSYCLDeviceLibPath(LibLocCandidates); - SmallString<128> LibName("libsycl-crt"); - bool IsNewOffload = D.getUseNewOffloadingDriver(); - StringRef LibSuffix = TheTriple.isWindowsMSVCEnvironment() - ? (IsNewOffload ? ".new.obj" : ".obj") - : (IsNewOffload ? ".new.o" : ".o"); - llvm::sys::path::replace_extension(LibName, LibSuffix); - for (const auto &LibLoc : LibLocCandidates) { - SmallString<128> FullLibName(LibLoc); - llvm::sys::path::append(FullLibName, LibName); - if (llvm::sys::fs::exists(FullLibName)) { - DeviceLibDir = LibLoc; - break; - } - } CmdArgs.push_back(Args.MakeArgString( Twine("-sycl-device-library-location=") + DeviceLibDir)); From 2da4a2617f192fc8ef8a88a94c592e6f9ed3cd1c Mon Sep 17 00:00:00 2001 From: "Cai, Justin" Date: Mon, 6 Oct 2025 20:56:32 +0000 Subject: [PATCH 3/4] updat device linking pt2 --- clang/lib/Driver/ToolChains/Clang.cpp | 63 +++++++------------ .../ClangLinkerWrapper.cpp | 32 +++++----- .../clang-linker-wrapper/LinkerWrapperOpts.td | 8 ++- 3 files changed, 44 insertions(+), 59 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 0051766872ab7..d0f4bd66610d3 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -11298,51 +11298,32 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, // Create a comma separated list to pass along to the linker wrapper. SmallString<256> LibList; + SmallString<256> BCLibList; llvm::Triple TargetTriple; auto ToolChainRange = C.getOffloadToolChains(); for (auto &I : llvm::make_range(ToolChainRange.first, ToolChainRange.second)) { const ToolChain *TC = I.second; - // Note: For AMD targets, we do not pass any SYCL device libraries. - if (TC->getTriple().isNVPTX()) { - auto NVPTXLibNames = - SYCL::getDeviceLibraries(C, llvm::Triple("nvptx64-nvidia-cuda"), - /*UseAOTLink=*/false); - SmallVector, 8> NVPTXLibPaths; - for (const auto &LibName : NVPTXLibNames) { - SmallString<0> FullLibName(DeviceLibDir); - llvm::sys::path::append(FullLibName, LibName); - NVPTXLibPaths.push_back(FullLibName); - } - if (const char *LibSpirvFile = SYCLInstallation.findLibspirvPath( - TC->getTriple(), Args, *TC->getAuxTriple())) { - NVPTXLibPaths.push_back(StringRef(LibSpirvFile)); - } - - if (NVPTXLibPaths.size() != 0) - CmdArgs.push_back( - Args.MakeArgString(Twine("-sycl-nvptx-device-libraries=") + - llvm::join(NVPTXLibPaths, ","))); - - continue; - } - - if (TC->getTriple().isSPIROrSPIRV()) { - TargetTriple = TC->getTriple(); - SmallVector SYCLDeviceLibs; - bool IsSPIR = TargetTriple.isSPIROrSPIRV(); - bool IsSpirvAOT = TargetTriple.isSPIRAOT(); - bool UseJitLink = - IsSPIR && - Args.hasFlag(options::OPT_fsycl_device_lib_jit_link, - options::OPT_fno_sycl_device_lib_jit_link, false); - bool UseAOTLink = IsSPIR && (IsSpirvAOT || !UseJitLink); - SYCLDeviceLibs = SYCL::getDeviceLibraries(C, TargetTriple, UseAOTLink); - for (const auto &AddLib : SYCLDeviceLibs) { - if (LibList.size() > 0) - LibList += ","; - LibList += AddLib; + TargetTriple = TC->getTriple(); + SmallVector SYCLDeviceLibs; + bool IsSPIR = TargetTriple.isSPIROrSPIRV(); + bool IsSpirvAOT = TargetTriple.isSPIRAOT(); + bool UseJitLink = + IsSPIR && + Args.hasFlag(options::OPT_fsycl_device_lib_jit_link, + options::OPT_fno_sycl_device_lib_jit_link, false); + bool UseAOTLink = IsSPIR && (IsSpirvAOT || !UseJitLink); + SYCLDeviceLibs = SYCL::getDeviceLibraries(C, TargetTriple, UseAOTLink); + for (const auto &AddLib : SYCLDeviceLibs) { + if (llvm::sys::path::extension(AddLib) == ".bc") { + if (BCLibList.size() > 0) + BCLibList += ","; + BCLibList += Twine(TC->getTriple().str() + "=" + AddLib).str(); + continue; } + if (LibList.size() > 0) + LibList += ","; + LibList += AddLib; } } // -sycl-device-libraries= provides a comma separate list of @@ -11351,6 +11332,10 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back( Args.MakeArgString(Twine("-sycl-device-libraries=") + LibList)); + if (BCLibList.size()) + CmdArgs.push_back( + Args.MakeArgString(Twine("--sycl-bc-device-libraries=") + BCLibList)); + // -sycl-device-library-location= provides the location in which the // SYCL device libraries can be found. CmdArgs.push_back(Args.MakeArgString( diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp index 9648635dc0d38..ad564f018248d 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -1417,24 +1417,22 @@ static Expected linkDevice(ArrayRef InputFiles, << "Compatible SYCL device library binary not found\n"; } - // For NVPTX backend we need to also link libclc and CUDA libdevice. - if (Triple.isNVPTX()) { - if (Arg *A = Args.getLastArg(OPT_sycl_nvptx_device_lib_EQ)) { - if (A->getValues().size() == 0) - return createStringError( - inconvertibleErrorCode(), - "Number of device library files cannot be zero."); - for (StringRef Val : A->getValues()) { - SmallString<128> LibName(Val); - if (llvm::sys::fs::exists(LibName)) - ExtractedDeviceLibFiles.emplace_back(std::string(LibName)); - else - return createStringError( - inconvertibleErrorCode(), - std::string(LibName) + - " SYCL device library file for NVPTX is not found."); - } + for (StringRef Library : Args.getAllArgValues(OPT_sycl_bc_device_lib_EQ)) { + auto [LibraryTriple, LibraryName] = Library.split('='); + if (llvm::Triple(LibraryTriple) != Triple) + continue; + StringRef DeviceLibraryDir(""); + if (Arg *DeviceLibDirArg = + Args.getLastArg(OPT_sycl_device_library_location_EQ)) + DeviceLibraryDir = DeviceLibDirArg->getValue(); + SmallString<128> DeviceLibPath(DeviceLibraryDir); + llvm::sys::path::append(DeviceLibPath, LibraryName); + if (!llvm::sys::fs::exists(DeviceLibPath)) { + return createStringError(inconvertibleErrorCode(), + "The specified device library " + DeviceLibPath + + " does not exist."); } + ExtractedDeviceLibFiles.emplace_back(DeviceLibPath.str()); } // Make sure that SYCL device library files are available. diff --git a/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td b/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td index 1e7cd060278cb..7c3d8f7ce96fe 100644 --- a/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td +++ b/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td @@ -156,9 +156,11 @@ def sycl_device_lib_EQ : CommaJoined<["--", "-"], "sycl-device-libraries=">, def sycl_device_library_location_EQ : Joined<["--", "-"], "sycl-device-library-location=">, Flags<[WrapperOnlyOption]>, HelpText<"Location of SYCL device library files">; -def sycl_nvptx_device_lib_EQ : CommaJoined<["--", "-"], "sycl-nvptx-device-libraries=">, - Flags<[WrapperOnlyOption]>, - HelpText<"A comma separated list of nvptx-specific device libraries that are linked during the device link.">; +def sycl_bc_device_lib_EQ + : CommaJoined<["--", "-"], "sycl-bc-device-libraries=">, + Flags<[WrapperOnlyOption]>, + HelpText<"A comma separated list of bitcode device libraries that are " + "linked during SYCL device link.">; // Options for SYCL backends and linker options for shared libraries. def sycl_backend_compile_options_EQ : From 21f519ddf0efcc8af334e5bba6fbd4ef212cbf1a Mon Sep 17 00:00:00 2001 From: "Cai, Justin" Date: Tue, 7 Oct 2025 18:49:55 +0000 Subject: [PATCH 4/4] update device linking pt3 --- clang/lib/Driver/ToolChains/Clang.cpp | 25 ++++++++++++++++--- .../ClangLinkerWrapper.cpp | 20 +++++++-------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index d0f4bd66610d3..6db991024019e 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -11299,6 +11299,15 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, // Create a comma separated list to pass along to the linker wrapper. SmallString<256> LibList; SmallString<256> BCLibList; + + // Lambda to append items to BCLibList with comma separation + auto appendToBCLibList = [&BCLibList](const llvm::Triple &Triple, + const Twine &Path) { + if (BCLibList.size() > 0) + BCLibList += ","; + BCLibList += (Twine(Triple.str()) + "=" + Path).str(); + }; + llvm::Triple TargetTriple; auto ToolChainRange = C.getOffloadToolChains(); for (auto &I : @@ -11316,15 +11325,23 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, SYCLDeviceLibs = SYCL::getDeviceLibraries(C, TargetTriple, UseAOTLink); for (const auto &AddLib : SYCLDeviceLibs) { if (llvm::sys::path::extension(AddLib) == ".bc") { - if (BCLibList.size() > 0) - BCLibList += ","; - BCLibList += Twine(TC->getTriple().str() + "=" + AddLib).str(); + SmallString<256> LibPath(DeviceLibDir); + llvm::sys::path::append(LibPath, AddLib); + appendToBCLibList(TC->getTriple(), LibPath); continue; } + if (LibList.size() > 0) LibList += ","; LibList += AddLib; } + + if (TC->getTriple().isNVPTX()) { + if (const char *LibSpirvFile = SYCLInstallation.findLibspirvPath( + TC->getTriple(), Args, *TC->getAuxTriple())) { + appendToBCLibList(TC->getTriple(), LibSpirvFile); + } + } } // -sycl-device-libraries= provides a comma separate list of // libraries to add to the device linking step. @@ -11334,7 +11351,7 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, if (BCLibList.size()) CmdArgs.push_back( - Args.MakeArgString(Twine("--sycl-bc-device-libraries=") + BCLibList)); + Args.MakeArgString(Twine("-sycl-bc-device-libraries=") + BCLibList)); // -sycl-device-library-location= provides the location in which the // SYCL device libraries can be found. diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp index ad564f018248d..6d3236970c86b 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -1418,21 +1418,21 @@ static Expected linkDevice(ArrayRef InputFiles, } for (StringRef Library : Args.getAllArgValues(OPT_sycl_bc_device_lib_EQ)) { - auto [LibraryTriple, LibraryName] = Library.split('='); + auto [LibraryTriple, LibraryPath] = Library.split('='); if (llvm::Triple(LibraryTriple) != Triple) continue; - StringRef DeviceLibraryDir(""); - if (Arg *DeviceLibDirArg = - Args.getLastArg(OPT_sycl_device_library_location_EQ)) - DeviceLibraryDir = DeviceLibDirArg->getValue(); - SmallString<128> DeviceLibPath(DeviceLibraryDir); - llvm::sys::path::append(DeviceLibPath, LibraryName); - if (!llvm::sys::fs::exists(DeviceLibPath)) { + // StringRef DeviceLibraryDir(""); + // if (Arg *DeviceLibDirArg = + // Args.getLastArg(OPT_sycl_device_library_location_EQ)) + // DeviceLibraryDir = DeviceLibDirArg->getValue(); + // SmallString<128> DeviceLibPath(DeviceLibraryDir); + // llvm::sys::path::append(DeviceLibPath, LibraryName); + if (!llvm::sys::fs::exists(LibraryPath)) { return createStringError(inconvertibleErrorCode(), - "The specified device library " + DeviceLibPath + + "The specified device library " + LibraryPath + " does not exist."); } - ExtractedDeviceLibFiles.emplace_back(DeviceLibPath.str()); + ExtractedDeviceLibFiles.emplace_back(LibraryPath.str()); } // Make sure that SYCL device library files are available.