diff --git a/clang/include/clang/Driver/CudaInstallationDetector.h b/clang/include/clang/Driver/CudaInstallationDetector.h new file mode 100644 index 0000000000000..0fecbfe069ca4 --- /dev/null +++ b/clang/include/clang/Driver/CudaInstallationDetector.h @@ -0,0 +1,76 @@ +//===-- CudaInstallationDetector.h - Cuda Instalation Detector --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_DRIVER_CUDAINSTALLATIONDETECTOR_H +#define LLVM_CLANG_DRIVER_CUDAINSTALLATIONDETECTOR_H + +#include "clang/Basic/Cuda.h" +#include "clang/Driver/Driver.h" +#include + +namespace clang { +namespace driver { + +/// A class to find a viable CUDA installation +class CudaInstallationDetector { +private: + const Driver &D; + bool IsValid = false; + CudaVersion Version = CudaVersion::UNKNOWN; + std::string InstallPath; + std::string BinPath; + std::string LibDevicePath; + std::string IncludePath; + llvm::StringMap LibDeviceMap; + + // CUDA architectures for which we have raised an error in + // CheckCudaVersionSupportsArch. + mutable std::bitset<(int)OffloadArch::LAST> ArchsWithBadVersion; + +public: + CudaInstallationDetector(const Driver &D, const llvm::Triple &HostTriple, + const llvm::opt::ArgList &Args); + + void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const; + + /// Emit an error if Version does not support the given Arch. + /// + /// If either Version or Arch is unknown, does not emit an error. Emits at + /// most one error per Arch. + void CheckCudaVersionSupportsArch(OffloadArch Arch) const; + + /// Check whether we detected a valid Cuda install. + bool isValid() const { return IsValid; } + /// Print information about the detected CUDA installation. + void print(raw_ostream &OS) const; + + /// Get the detected Cuda install's version. + CudaVersion version() const { + return Version == CudaVersion::NEW ? CudaVersion::PARTIALLY_SUPPORTED + : Version; + } + /// Get the detected Cuda installation path. + StringRef getInstallPath() const { return InstallPath; } + /// Get the detected path to Cuda's bin directory. + StringRef getBinPath() const { return BinPath; } + /// Get the detected Cuda Include path. + StringRef getIncludePath() const { return IncludePath; } + /// Get the detected Cuda device library path. + StringRef getLibDevicePath() const { return LibDevicePath; } + /// Get libdevice file for given architecture + std::string getLibDeviceFile(StringRef Gpu) const { + return LibDeviceMap.lookup(Gpu); + } + void WarnIfUnsupportedVersion() const; +}; + +} // namespace driver +} // namespace clang + +#endif // LLVM_CLANG_DRIVER_CUDAINSTALLATIONDETECTOR_H diff --git a/clang/lib/Driver/ToolChains/LazyDetector.h b/clang/include/clang/Driver/LazyDetector.h similarity index 87% rename from clang/lib/Driver/ToolChains/LazyDetector.h rename to clang/include/clang/Driver/LazyDetector.h index 813d00a87bb88..5bd1d0131bbba 100644 --- a/clang/lib/Driver/ToolChains/LazyDetector.h +++ b/clang/include/clang/Driver/LazyDetector.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LAZYDETECTOR_H -#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LAZYDETECTOR_H +#ifndef LLVM_CLANG_DRIVER_LAZYDETECTOR_H +#define LLVM_CLANG_DRIVER_LAZYDETECTOR_H #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" @@ -42,4 +42,4 @@ template class LazyDetector { } // end namespace clang -#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LAZYDETECTOR_H +#endif // LLVM_CLANG_DRIVER_LAZYDETECTOR_H diff --git a/clang/lib/Driver/ToolChains/ROCm.h b/clang/include/clang/Driver/RocmInstallationDetector.h similarity index 88% rename from clang/lib/Driver/ToolChains/ROCm.h rename to clang/include/clang/Driver/RocmInstallationDetector.h index 2a09da0114898..3a325a61ddbb9 100644 --- a/clang/lib/Driver/ToolChains/ROCm.h +++ b/clang/include/clang/Driver/RocmInstallationDetector.h @@ -1,4 +1,4 @@ -//===--- ROCm.h - ROCm installation detector --------------------*- C++ -*-===// +//===-- RocmInstallationDetector.h - ROCm Instalation Detector --*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,19 +6,10 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ROCM_H -#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ROCM_H +#ifndef LLVM_CLANG_DRIVER_ROCMINSTALLATIONDETECTOR_H +#define LLVM_CLANG_DRIVER_ROCMINSTALLATIONDETECTOR_H -#include "clang/Basic/Cuda.h" -#include "clang/Basic/LLVM.h" #include "clang/Driver/Driver.h" -#include "clang/Driver/Options.h" -#include "clang/Driver/SanitizerArgs.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/Option/ArgList.h" -#include "llvm/Support/VersionTuple.h" -#include "llvm/TargetParser/Triple.h" namespace clang { namespace driver { @@ -77,6 +68,24 @@ class RocmInstallationDetector { SPACKReleaseStr(SPACKReleaseStr.str()) {} }; + struct CommonBitcodeLibsPreferences { + CommonBitcodeLibsPreferences(const Driver &D, + const llvm::opt::ArgList &DriverArgs, + StringRef GPUArch, + const Action::OffloadKind DeviceOffloadingKind, + const bool NeedsASanRT); + + DeviceLibABIVersion ABIVer; + bool IsOpenMP; + bool Wave64; + bool DAZ; + bool FiniteOnly; + bool UnsafeMathOpt; + bool FastRelaxedMath; + bool CorrectSqrt; + bool GPUSan; + }; + const Driver &D; bool HasHIPRuntime = false; bool HasDeviceLibrary = false; @@ -175,11 +184,11 @@ class RocmInstallationDetector { /// Get file paths of default bitcode libraries common to AMDGPU based /// toolchains. - llvm::SmallVector getCommonBitcodeLibs( - const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile, - bool Wave64, bool DAZ, bool FiniteOnly, bool UnsafeMathOpt, - bool FastRelaxedMath, bool CorrectSqrt, DeviceLibABIVersion ABIVer, - bool GPUSan, bool isOpenMP) const; + llvm::SmallVector + getCommonBitcodeLibs(const llvm::opt::ArgList &DriverArgs, + StringRef LibDeviceFile, StringRef GPUArch, + const Action::OffloadKind DeviceOffloadingKind, + const bool NeedsASanRT) const; /// Check file paths of default bitcode libraries common to AMDGPU based /// toolchains. \returns false if there are invalid or missing files. bool checkCommonBitcodeLibs(StringRef GPUArch, StringRef LibDeviceFile, @@ -288,7 +297,7 @@ class RocmInstallationDetector { StringRef getHIPVersion() const { return DetectedVersion; } }; -} // end namespace driver -} // end namespace clang +} // namespace driver +} // namespace clang -#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ROCM_H +#endif // LLVM_CLANG_DRIVER_ROCMINSTALLATIONDETECTOR_H diff --git a/clang/include/clang/Driver/SyclInstallationDetector.h b/clang/include/clang/Driver/SyclInstallationDetector.h new file mode 100644 index 0000000000000..0f41e54d958b7 --- /dev/null +++ b/clang/include/clang/Driver/SyclInstallationDetector.h @@ -0,0 +1,49 @@ +//===-- SyclInstallationDetector.h - SYCL Instalation Detector --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_DRIVER_SYCLINSTALLATIONDETECTOR_H +#define LLVM_CLANG_DRIVER_SYCLINSTALLATIONDETECTOR_H + +#include "clang/Driver/Driver.h" + +namespace clang { +namespace driver { + +class SYCLInstallationDetector { +public: + SYCLInstallationDetector(const Driver &D); + SYCLInstallationDetector(const Driver &D, const llvm::Triple &HostTriple, + const llvm::opt::ArgList &Args); + + /// \brief Find and return the path to the libspirv library for the target + /// \return The path to the libspirv library if found, otherwise nullptr. + /// The lifetime of the returned string is managed by \p Args. + const char *findLibspirvPath(const llvm::Triple &DeviceTriple, + const llvm::opt::ArgList &Args, + const llvm::Triple &HostTriple) const; + + void addLibspirvLinkArgs(const llvm::Triple &DeviceTriple, + const llvm::opt::ArgList &DriverArgs, + const llvm::Triple &HostTriple, + llvm::opt::ArgStringList &CC1Args) const; + + void getSYCLDeviceLibPath( + llvm::SmallVector, 4> &DeviceLibPaths) const; + void addSYCLIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const; + void print(llvm::raw_ostream &OS) const; + +private: + const Driver &D; + llvm::SmallVector, 4> InstallationCandidates; +}; + +} // namespace driver +} // namespace clang + +#endif // LLVM_CLANG_DRIVER_SYCLINSTALLATIONDETECTOR_H diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 838e115609a97..269c13b41c08e 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -1692,9 +1692,8 @@ void ToolChain::addSYCLIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const {} llvm::SmallVector -ToolChain::getDeviceLibs( - const ArgList &DriverArgs, - const Action::OffloadKind DeviceOffloadingKind) const { +ToolChain::getDeviceLibs(const ArgList &DriverArgs, + const Action::OffloadKind DeviceOffloadingKind) const { return {}; } diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp index e0c2446d13124..842b64115b5c7 100644 --- a/clang/lib/Driver/ToolChains/AMDGPU.cpp +++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp @@ -31,6 +31,75 @@ using namespace clang::driver::toolchains; using namespace clang; using namespace llvm::opt; +RocmInstallationDetector::CommonBitcodeLibsPreferences:: + CommonBitcodeLibsPreferences(const Driver &D, + const llvm::opt::ArgList &DriverArgs, + StringRef GPUArch, + const Action::OffloadKind DeviceOffloadingKind, + const bool NeedsASanRT) + : ABIVer(DeviceLibABIVersion::fromCodeObjectVersion( + tools::getAMDGPUCodeObjectVersion(D, DriverArgs))) { + const auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch); + const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind); + + IsOpenMP = DeviceOffloadingKind == Action::OFK_OpenMP; + + const bool HasWave32 = (ArchAttr & llvm::AMDGPU::FEATURE_WAVE32); + Wave64 = + !HasWave32 || DriverArgs.hasFlag(options::OPT_mwavefrontsize64, + options::OPT_mno_wavefrontsize64, false); + + const bool IsKnownOffloading = DeviceOffloadingKind == Action::OFK_OpenMP || + DeviceOffloadingKind == Action::OFK_HIP; + + // Default to enabling f32 denormals on subtargets where fma is fast with + // denormals + const bool DefaultDAZ = + (Kind == llvm::AMDGPU::GK_NONE) + ? false + : !((ArchAttr & llvm::AMDGPU::FEATURE_FAST_FMA_F32) && + (ArchAttr & llvm::AMDGPU::FEATURE_FAST_DENORMAL_F32)); + // TODO: There are way too many flags that change this. Do we need to + // check them all? + DAZ = IsKnownOffloading + ? DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero, + options::OPT_fno_gpu_flush_denormals_to_zero, + DefaultDAZ) + : DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) || DefaultDAZ; + + FiniteOnly = DriverArgs.hasArg(options::OPT_cl_finite_math_only) || + DriverArgs.hasFlag(options::OPT_ffinite_math_only, + options::OPT_fno_finite_math_only, false); + + UnsafeMathOpt = + DriverArgs.hasArg(options::OPT_cl_unsafe_math_optimizations) || + DriverArgs.hasFlag(options::OPT_funsafe_math_optimizations, + options::OPT_fno_unsafe_math_optimizations, false); + + FastRelaxedMath = DriverArgs.hasArg(options::OPT_cl_fast_relaxed_math) || + DriverArgs.hasFlag(options::OPT_ffast_math, + options::OPT_fno_fast_math, false); + + const bool DefaultSqrt = IsKnownOffloading ? true : false; + + if (DeviceOffloadingKind == Action::OFK_SYCL) + // When using SYCL, sqrt is only correctly rounded if the flag is specified. + CorrectSqrt = DriverArgs.hasArg(options::OPT_foffload_fp32_prec_sqrt); + else + CorrectSqrt = + DriverArgs.hasArg(options::OPT_cl_fp32_correctly_rounded_divide_sqrt) || + DriverArgs.hasFlag( + options::OPT_fhip_fp32_correctly_rounded_divide_sqrt, + options::OPT_fno_hip_fp32_correctly_rounded_divide_sqrt, + DefaultSqrt); + + // GPU Sanitizer currently only supports ASan and is enabled through host + // ASan. + GPUSan = (DriverArgs.hasFlag(options::OPT_fgpu_sanitize, + options::OPT_fno_gpu_sanitize, true) && + NeedsASanRT); +} + void RocmInstallationDetector::scanLibDevicePath(llvm::StringRef Path) { assert(!Path.empty()); @@ -884,33 +953,14 @@ void ROCMToolChain::addClangTargetOptions( ABIVer)) return; - bool Wave64 = isWave64(DriverArgs, Kind); - // TODO: There are way too many flags that change this. Do we need to check - // them all? - bool DAZ = DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) || - getDefaultDenormsAreZeroForTarget(Kind); - bool FiniteOnly = DriverArgs.hasArg(options::OPT_cl_finite_math_only); - - bool UnsafeMathOpt = - DriverArgs.hasArg(options::OPT_cl_unsafe_math_optimizations); - bool FastRelaxedMath = DriverArgs.hasArg(options::OPT_cl_fast_relaxed_math); - bool CorrectSqrt = - DriverArgs.hasArg(options::OPT_cl_fp32_correctly_rounded_divide_sqrt); - - // GPU Sanitizer currently only supports ASan and is enabled through host - // ASan. - bool GPUSan = DriverArgs.hasFlag(options::OPT_fgpu_sanitize, - options::OPT_fno_gpu_sanitize, true) && - getSanitizerArgs(DriverArgs).needsAsanRt(); - // Add the OpenCL specific bitcode library. llvm::SmallVector BCLibs; BCLibs.emplace_back(RocmInstallation->getOpenCLPath().str()); // Add the generic set of libraries. BCLibs.append(RocmInstallation->getCommonBitcodeLibs( - DriverArgs, LibDeviceFile, Wave64, DAZ, FiniteOnly, UnsafeMathOpt, - FastRelaxedMath, CorrectSqrt, ABIVer, GPUSan, false)); + DriverArgs, LibDeviceFile, GpuArch, DeviceOffloadingKind, + getSanitizerArgs(DriverArgs).needsAsanRt())); for (auto [BCFile, Internalize] : BCLibs) { if (Internalize) @@ -947,35 +997,37 @@ bool RocmInstallationDetector::checkCommonBitcodeLibs( llvm::SmallVector RocmInstallationDetector::getCommonBitcodeLibs( - const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile, bool Wave64, - bool DAZ, bool FiniteOnly, bool UnsafeMathOpt, bool FastRelaxedMath, - bool CorrectSqrt, DeviceLibABIVersion ABIVer, bool GPUSan, - bool isOpenMP) const { + const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile, + StringRef GPUArch, const Action::OffloadKind DeviceOffloadingKind, + const bool NeedsASanRT) const { llvm::SmallVector BCLibs; + CommonBitcodeLibsPreferences Pref{D, DriverArgs, GPUArch, + DeviceOffloadingKind, NeedsASanRT}; + auto AddBCLib = [&](ToolChain::BitCodeLibraryInfo BCLib, bool Internalize = true) { BCLib.ShouldInternalize = Internalize; BCLibs.emplace_back(BCLib); }; auto AddSanBCLibs = [&]() { - if (GPUSan) + if (Pref.GPUSan) AddBCLib(getAsanRTLPath(), false); }; AddSanBCLibs(); AddBCLib(getOCMLPath()); - if (!isOpenMP) + if (!Pref.IsOpenMP) AddBCLib(getOCKLPath()); - else if (GPUSan && isOpenMP) + else if (Pref.GPUSan && Pref.IsOpenMP) AddBCLib(getOCKLPath(), false); - AddBCLib(getDenormalsAreZeroPath(DAZ)); - AddBCLib(getUnsafeMathPath(UnsafeMathOpt || FastRelaxedMath)); - AddBCLib(getFiniteOnlyPath(FiniteOnly || FastRelaxedMath)); - AddBCLib(getCorrectlyRoundedSqrtPath(CorrectSqrt)); - AddBCLib(getWavefrontSize64Path(Wave64)); + AddBCLib(getDenormalsAreZeroPath(Pref.DAZ)); + AddBCLib(getUnsafeMathPath(Pref.UnsafeMathOpt || Pref.FastRelaxedMath)); + AddBCLib(getFiniteOnlyPath(Pref.FiniteOnly || Pref.FastRelaxedMath)); + AddBCLib(getCorrectlyRoundedSqrtPath(Pref.CorrectSqrt)); + AddBCLib(getWavefrontSize64Path(Pref.Wave64)); AddBCLib(LibDeviceFile); - auto ABIVerPath = getABIVersionPath(ABIVer); + auto ABIVerPath = getABIVersionPath(Pref.ABIVer); if (!ABIVerPath.empty()) AddBCLib(ABIVerPath); @@ -985,7 +1037,7 @@ RocmInstallationDetector::getCommonBitcodeLibs( llvm::SmallVector ROCMToolChain::getCommonDeviceLibNames( const llvm::opt::ArgList &DriverArgs, const std::string &GPUArch, - const Action::OffloadKind DeviceOffloadingKind, bool isOpenMP) const { + Action::OffloadKind DeviceOffloadingKind) const { auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch); const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind); @@ -996,38 +1048,9 @@ ROCMToolChain::getCommonDeviceLibNames( ABIVer)) return {}; - // If --hip-device-lib is not set, add the default bitcode libraries. - // TODO: There are way too many flags that change this. Do we need to check - // them all? - bool DAZ = DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero, - options::OPT_fno_gpu_flush_denormals_to_zero, - getDefaultDenormsAreZeroForTarget(Kind)); - bool FiniteOnly = DriverArgs.hasFlag( - options::OPT_ffinite_math_only, options::OPT_fno_finite_math_only, false); - bool UnsafeMathOpt = - DriverArgs.hasFlag(options::OPT_funsafe_math_optimizations, - options::OPT_fno_unsafe_math_optimizations, false); - bool FastRelaxedMath = DriverArgs.hasFlag(options::OPT_ffast_math, - options::OPT_fno_fast_math, false); - bool CorrectSqrt = false; - if (DeviceOffloadingKind == Action::OFK_SYCL) - // When using SYCL, sqrt is only correctly rounded if the flag is specified - CorrectSqrt = DriverArgs.hasArg(options::OPT_foffload_fp32_prec_sqrt); - else - CorrectSqrt = DriverArgs.hasFlag( - options::OPT_fhip_fp32_correctly_rounded_divide_sqrt, - options::OPT_fno_hip_fp32_correctly_rounded_divide_sqrt, true); - bool Wave64 = isWave64(DriverArgs, Kind); - - // GPU Sanitizer currently only supports ASan and is enabled through host - // ASan. - bool GPUSan = DriverArgs.hasFlag(options::OPT_fgpu_sanitize, - options::OPT_fno_gpu_sanitize, true) && - getSanitizerArgs(DriverArgs).needsAsanRt(); - return RocmInstallation->getCommonBitcodeLibs( - DriverArgs, LibDeviceFile, Wave64, DAZ, FiniteOnly, UnsafeMathOpt, - FastRelaxedMath, CorrectSqrt, ABIVer, GPUSan, isOpenMP); + DriverArgs, LibDeviceFile, GPUArch, DeviceOffloadingKind, + getSanitizerArgs(DriverArgs).needsAsanRt()); } bool AMDGPUToolChain::shouldSkipSanitizeOption( diff --git a/clang/lib/Driver/ToolChains/AMDGPU.h b/clang/lib/Driver/ToolChains/AMDGPU.h index 69a6237617f50..9fb8c3226dfc0 100644 --- a/clang/lib/Driver/ToolChains/AMDGPU.h +++ b/clang/lib/Driver/ToolChains/AMDGPU.h @@ -10,7 +10,6 @@ #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_AMDGPU_H #include "Gnu.h" -#include "ROCm.h" #include "clang/Basic/TargetID.h" #include "clang/Driver/Options.h" #include "clang/Driver/Tool.h" @@ -147,8 +146,7 @@ class LLVM_LIBRARY_VISIBILITY ROCMToolChain : public AMDGPUToolChain { llvm::SmallVector getCommonDeviceLibNames(const llvm::opt::ArgList &DriverArgs, const std::string &GPUArch, - const Action::OffloadKind DeviceOffloadingKind, - bool isOpenMP = false) const; + Action::OffloadKind DeviceOffloadingKind) const; SanitizerMask getSupportedSanitizers() const override { return SanitizerKind::Address; diff --git a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp index 4ee9595391b55..9b69801908a27 100644 --- a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp +++ b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp @@ -360,8 +360,7 @@ AMDGPUOpenMPToolChain::getDeviceLibs( SmallVector BCLibs; for (auto BCLib : - getCommonDeviceLibNames(Args, GpuArch.str(), DeviceOffloadingKind, - /*IsOpenMP=*/true)) + getCommonDeviceLibNames(Args, GpuArch.str(), DeviceOffloadingKind)) BCLibs.emplace_back(BCLib); return BCLibs; diff --git a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h index b46da215af78c..3892c9d648344 100644 --- a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h +++ b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h @@ -102,7 +102,7 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUOpenMPToolChain final llvm::SmallVector getDeviceLibs(const llvm::opt::ArgList &Args, - const Action::OffloadKind DeviceOffloadingKind) const override; + const Action::OffloadKind DeviceOffloadKind) const override; const ToolChain &HostTC; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 4c9699cd99419..cc79a3514d3d6 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -16,6 +16,7 @@ #include "Arch/SystemZ.h" #include "Hexagon.h" #include "PS4CPU.h" +#include "ToolChains/Cuda.h" #include "clang/Basic/CLWarnings.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/HeaderInclude.h" diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index c6f50d9218d6b..cc90b8e275b8e 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -23,6 +23,7 @@ #include "Hexagon.h" #include "MSP430.h" #include "Solaris.h" +#include "ToolChains/Cuda.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/Config/config.h" #include "clang/Driver/Action.h" diff --git a/clang/lib/Driver/ToolChains/Cuda.h b/clang/lib/Driver/ToolChains/Cuda.h index 1b1eb59082c2c..ad97a41a9aba8 100644 --- a/clang/lib/Driver/ToolChains/Cuda.h +++ b/clang/lib/Driver/ToolChains/Cuda.h @@ -12,6 +12,7 @@ #include "SYCL.h" #include "clang/Basic/Cuda.h" #include "clang/Driver/Action.h" +#include "clang/Driver/CudaInstallationDetector.h" #include "clang/Driver/Multilib.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" @@ -23,61 +24,6 @@ namespace clang { namespace driver { - -/// A class to find a viable CUDA installation -class CudaInstallationDetector { -private: - const Driver &D; - bool IsValid = false; - CudaVersion Version = CudaVersion::UNKNOWN; - std::string InstallPath; - std::string BinPath; - std::string LibDevicePath; - std::string IncludePath; - llvm::StringMap LibDeviceMap; - - // CUDA architectures for which we have raised an error in - // CheckCudaVersionSupportsArch. - mutable std::bitset<(int)OffloadArch::LAST> ArchsWithBadVersion; - -public: - CudaInstallationDetector(const Driver &D, const llvm::Triple &HostTriple, - const llvm::opt::ArgList &Args); - - void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const; - - /// Emit an error if Version does not support the given Arch. - /// - /// If either Version or Arch is unknown, does not emit an error. Emits at - /// most one error per Arch. - void CheckCudaVersionSupportsArch(OffloadArch Arch) const; - - /// Check whether we detected a valid Cuda install. - bool isValid() const { return IsValid; } - /// Print information about the detected CUDA installation. - void print(raw_ostream &OS) const; - - /// Get the detected Cuda install's version. - CudaVersion version() const { - return Version == CudaVersion::NEW ? CudaVersion::PARTIALLY_SUPPORTED - : Version; - } - /// Get the detected Cuda installation path. - StringRef getInstallPath() const { return InstallPath; } - /// Get the detected path to Cuda's bin directory. - StringRef getBinPath() const { return BinPath; } - /// Get the detected Cuda Include path. - StringRef getIncludePath() const { return IncludePath; } - /// Get the detected Cuda device library path. - StringRef getLibDevicePath() const { return LibDevicePath; } - /// Get libdevice file for given architecture - std::string getLibDeviceFile(StringRef Gpu) const { - return LibDeviceMap.lookup(Gpu); - } - void WarnIfUnsupportedVersion() const; -}; - namespace tools { namespace NVPTX { diff --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h index b38bfe6d1e554..d1cfb6f4a5bf7 100644 --- a/clang/lib/Driver/ToolChains/Darwin.h +++ b/clang/lib/Driver/ToolChains/Darwin.h @@ -9,12 +9,12 @@ #ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H -#include "Cuda.h" -#include "LazyDetector.h" -#include "ROCm.h" -#include "SYCL.h" #include "clang/Basic/DarwinSDKInfo.h" #include "clang/Basic/LangOptions.h" +#include "clang/Driver/CudaInstallationDetector.h" +#include "clang/Driver/LazyDetector.h" +#include "clang/Driver/RocmInstallationDetector.h" +#include "clang/Driver/SyclInstallationDetector.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include "clang/Driver/XRayArgs.h" diff --git a/clang/lib/Driver/ToolChains/Gnu.h b/clang/lib/Driver/ToolChains/Gnu.h index 3b8df71bbf9d3..4c42a5e535d56 100644 --- a/clang/lib/Driver/ToolChains/Gnu.h +++ b/clang/lib/Driver/ToolChains/Gnu.h @@ -9,10 +9,10 @@ #ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_GNU_H #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_GNU_H -#include "Cuda.h" -#include "LazyDetector.h" -#include "ROCm.h" -#include "SYCL.h" +#include "clang/Driver/CudaInstallationDetector.h" +#include "clang/Driver/LazyDetector.h" +#include "clang/Driver/RocmInstallationDetector.h" +#include "clang/Driver/SyclInstallationDetector.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include diff --git a/clang/lib/Driver/ToolChains/HIPAMD.cpp b/clang/lib/Driver/ToolChains/HIPAMD.cpp index 4b6d87b932531..378cac51908e7 100644 --- a/clang/lib/Driver/ToolChains/HIPAMD.cpp +++ b/clang/lib/Driver/ToolChains/HIPAMD.cpp @@ -281,7 +281,6 @@ void HIPAMDToolChain::addClangTargetOptions( : "-mlink-bitcode-file"); CC1Args.push_back(DriverArgs.MakeArgString(BCFile.Path)); } - } llvm::opt::DerivedArgList * @@ -381,9 +380,8 @@ VersionTuple HIPAMDToolChain::computeMSVCVersion(const Driver *D, } llvm::SmallVector -HIPAMDToolChain::getDeviceLibs( - const llvm::opt::ArgList &DriverArgs, - const Action::OffloadKind DeviceOffloadingKind) const { +HIPAMDToolChain::getDeviceLibs(const llvm::opt::ArgList &DriverArgs, + Action::OffloadKind DeviceOffloadingKind) const { llvm::SmallVector BCLibs; if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib, true) || diff --git a/clang/lib/Driver/ToolChains/HIPAMD.h b/clang/lib/Driver/ToolChains/HIPAMD.h index 9ea97c4a59898..c43271fef73cf 100644 --- a/clang/lib/Driver/ToolChains/HIPAMD.h +++ b/clang/lib/Driver/ToolChains/HIPAMD.h @@ -10,6 +10,8 @@ #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HIPAMD_H #include "AMDGPU.h" +#include "SYCL.h" +#include "clang/Driver/SyclInstallationDetector.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" @@ -94,9 +96,9 @@ class LLVM_LIBRARY_VISIBILITY HIPAMDToolChain final : public ROCMToolChain { llvm::opt::ArgStringList &CC1Args) const override; void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; - llvm::SmallVector getDeviceLibs( - const llvm::opt::ArgList &Args, - const Action::OffloadKind DeviceOffloadingKind) const override; + llvm::SmallVector + getDeviceLibs(const llvm::opt::ArgList &Args, + Action::OffloadKind DeviceOffloadKind) const override; SanitizerMask getSupportedSanitizers() const override; diff --git a/clang/lib/Driver/ToolChains/HIPSPV.h b/clang/lib/Driver/ToolChains/HIPSPV.h index 597228f9d77e0..caf6924151446 100644 --- a/clang/lib/Driver/ToolChains/HIPSPV.h +++ b/clang/lib/Driver/ToolChains/HIPSPV.h @@ -68,9 +68,9 @@ class LLVM_LIBRARY_VISIBILITY HIPSPVToolChain final : public ToolChain { llvm::opt::ArgStringList &CC1Args) const override; void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; - llvm::SmallVector getDeviceLibs( - const llvm::opt::ArgList &Args, - const Action::OffloadKind DeviceOffloadingKind) const override; + llvm::SmallVector + getDeviceLibs(const llvm::opt::ArgList &Args, + const Action::OffloadKind DeviceOffloadKind) const override; SanitizerMask getSupportedSanitizers() const override; diff --git a/clang/lib/Driver/ToolChains/MSVC.h b/clang/lib/Driver/ToolChains/MSVC.h index b35390c52a049..5c17edce087c7 100644 --- a/clang/lib/Driver/ToolChains/MSVC.h +++ b/clang/lib/Driver/ToolChains/MSVC.h @@ -9,11 +9,11 @@ #ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSVC_H #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSVC_H -#include "AMDGPU.h" -#include "Cuda.h" -#include "LazyDetector.h" -#include "SYCL.h" #include "clang/Driver/Compilation.h" +#include "clang/Driver/CudaInstallationDetector.h" +#include "clang/Driver/LazyDetector.h" +#include "clang/Driver/RocmInstallationDetector.h" +#include "clang/Driver/SyclInstallationDetector.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include "llvm/Frontend/Debug/Options.h" diff --git a/clang/lib/Driver/ToolChains/MinGW.h b/clang/lib/Driver/ToolChains/MinGW.h index a9963d8d06c29..1730da48cd434 100644 --- a/clang/lib/Driver/ToolChains/MinGW.h +++ b/clang/lib/Driver/ToolChains/MinGW.h @@ -11,8 +11,9 @@ #include "Cuda.h" #include "Gnu.h" -#include "LazyDetector.h" -#include "ROCm.h" +#include "clang/Driver/CudaInstallationDetector.h" +#include "clang/Driver/LazyDetector.h" +#include "clang/Driver/RocmInstallationDetector.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include "llvm/Support/ErrorOr.h" diff --git a/clang/lib/Driver/ToolChains/SYCL.h b/clang/lib/Driver/ToolChains/SYCL.h index bc95910dcf34e..c1403ae1d5036 100644 --- a/clang/lib/Driver/ToolChains/SYCL.h +++ b/clang/lib/Driver/ToolChains/SYCL.h @@ -9,8 +9,7 @@ #ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_SYCL_H #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_SYCL_H -#include "clang/Basic/Cuda.h" -#include "clang/Driver/Options.h" +#include "clang/Driver/SyclInstallationDetector.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" @@ -22,36 +21,6 @@ namespace driver { // AOT compiler). StringRef mapIntelGPUArchName(StringRef ArchName); -class SYCLInstallationDetector { -public: - SYCLInstallationDetector(const Driver &D); - SYCLInstallationDetector(const Driver &D, const llvm::Triple &HostTriple, - const llvm::opt::ArgList &Args); - - /// \brief Find and return the path to the libspirv library for the target - /// \return The path to the libspirv library if found, otherwise nullptr. - /// The lifetime of the returned string is managed by \p Args. - const char *findLibspirvPath(const llvm::Triple &DeviceTriple, - const llvm::opt::ArgList &Args, - const llvm::Triple &HostTriple) const; - - void addLibspirvLinkArgs(const llvm::Triple &DeviceTriple, - const llvm::opt::ArgList &DriverArgs, - const llvm::Triple &HostTriple, - llvm::opt::ArgStringList &CC1Args) const; - - void getSYCLDeviceLibPath( - llvm::SmallVector, 4> &DeviceLibPaths) const; - void addSYCLIncludeArgs(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const; - void print(llvm::raw_ostream &OS) const; - -private: - const Driver &D; - llvm::SmallVector, 4> InstallationCandidates; -}; - - class Command; namespace tools { @@ -151,7 +120,6 @@ class LLVM_LIBRARY_VISIBILITY BackendCompiler : public Tool { }; } // end namespace x86_64 - } // end namespace SYCL } // end namespace tools diff --git a/sycl-jit/jit-compiler/lib/rtc/DeviceCompilation.cpp b/sycl-jit/jit-compiler/lib/rtc/DeviceCompilation.cpp index fd4e55c2d5f14..1547894ca4223 100644 --- a/sycl-jit/jit-compiler/lib/rtc/DeviceCompilation.cpp +++ b/sycl-jit/jit-compiler/lib/rtc/DeviceCompilation.cpp @@ -15,8 +15,11 @@ #include #include #include +#include #include +#include #include +#include #include #include #include @@ -42,6 +45,7 @@ #include #include #include +#include #include #include @@ -622,67 +626,57 @@ Error jit_compiler::linkDeviceLibraries(llvm::Module &Module, // For GPU targets we need to link against vendor provided libdevice. if (IsCudaHIP) { - std::string Argv0 = DPCPPRoot + "/bin/clang++"; Triple T{Module.getTargetTriple()}; - IntrusiveRefCntPtr OFS{ - new OverlayFileSystem{getRealFileSystem()}}; - IntrusiveRefCntPtr VFS{new InMemoryFileSystem}; - std::string CppFileName{"a.cpp"}; - VFS->addFile(CppFileName, /*ModificationTime=*/0, - MemoryBuffer::getMemBuffer("", "")); - OFS->pushOverlay(VFS); - Driver D{Argv0, T.getTriple(), Diags, "dpcpp compiler driver", OFS}; - - SmallVector CommandLine; - CommandLine.push_back(Argv0); - adjustArgs(UserArgList, DPCPPRoot, Format, CommandLine); - CommandLine.push_back(CppFileName); - SmallVector CommandLineCStr(CommandLine.size()); - llvm::transform(CommandLine, CommandLineCStr.begin(), - [](const auto &S) { return S.c_str(); }); - - Compilation *C = D.BuildCompilation(CommandLineCStr); - if (!C) { - return createStringError("Unable to construct driver for CUDA/HIP"); - } - - const ToolChain *OffloadTC = - C->getSingleOffloadToolChain(); - InputArgList EmptyArgList; - auto Archs = - D.getOffloadArchs(*C, EmptyArgList, Action::OFK_SYCL, OffloadTC); - assert(Archs.size() == 1 && - "Offload toolchain should be configured to single architecture"); - StringRef CPU = *Archs.begin(); - - // Pass only `-march=` or `-mcpu=` with the GPU arch determined by the - // driver to `getDeviceLibs`. - DerivedArgList CPUArgList{EmptyArgList}; + Driver D{(Twine(DPCPPRoot) + "/bin/clang++").str(), T.getTriple(), Diags}; + auto [CPU, Features] = + Translator::getTargetCPUAndFeatureAttrs(&Module, "", Format); + (void)Features; + // Helper lambda to link modules. + auto LinkInLib = [&](const StringRef LibDevice) -> Error { + ModuleUPtr LibDeviceModule; + if (auto Error = loadBitcodeLibrary(LibDevice, Context) + .moveInto(LibDeviceModule)) { + return Error; + } + if (Linker::linkModules(Module, std::move(LibDeviceModule), + Linker::LinkOnlyNeeded)) { + return createStringError("Unable to link libdevice: %s", + BuildLog.c_str()); + } + return Error::success(); + }; + SmallVector LibDeviceFiles; if (Format == BinaryFormat::PTX) { - CPUArgList.AddJoinedArg(nullptr, D.getOpts().getOption(OPT_march_EQ), - CPU); + // For NVPTX we can get away with CudaInstallationDetector. + LazyDetector CudaInstallation{D, T, + UserArgList}; + auto LibDevice = CudaInstallation->getLibDeviceFile(CPU); + if (LibDevice.empty()) { + return createStringError("Unable to find Cuda libdevice"); + } + LibDeviceFiles.push_back(LibDevice); } else { - CPUArgList.AddJoinedArg(nullptr, D.getOpts().getOption(OPT_mcpu_EQ), CPU); - } - - SmallVector CommonDeviceLibs = - OffloadTC->getDeviceLibs(CPUArgList, Action::OffloadKind::OFK_SYCL); - if (CommonDeviceLibs.empty()) { - return createStringError("Unable to find common device libraries"); + LazyDetector RocmInstallation{D, T, + UserArgList}; + RocmInstallation->detectDeviceLibrary(); + StringRef CanonArch = + llvm::AMDGPU::getArchNameAMDGCN(llvm::AMDGPU::parseArchAMDGCN(CPU)); + StringRef LibDeviceFile = RocmInstallation->getLibDeviceFile(CanonArch); + auto CommonBCLibs = RocmInstallation->getCommonBitcodeLibs( + UserArgList, LibDeviceFile, CPU, Action::OFK_SYCL, + /*NeedsASanRT=*/false); + if (CommonBCLibs.empty()) { + return createStringError("Unable to find ROCm bitcode libraries"); + } + for (auto &Lib : CommonBCLibs) { + LibDeviceFiles.push_back(Lib.Path); + } } - - for (auto &Lib : CommonDeviceLibs) { - ModuleUPtr LibModule; - if (auto Error = - loadBitcodeLibrary(Lib.Path, Context).moveInto(LibModule)) { + for (auto &LibDeviceFile : LibDeviceFiles) { + // llvm::Error converts to false on success. + if (auto Error = LinkInLib(LibDeviceFile)) { return Error; } - - if (Linker::linkModules(Module, std::move(LibModule), - Linker::LinkOnlyNeeded)) { - return createStringError("Unable to link device library %s: %s", - Lib.Path.c_str(), BuildLog.c_str()); - } } }