Index: clang/include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticDriverKinds.td +++ clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -56,12 +56,12 @@ "cannot find libdevice for %0. Provide path to different CUDA installation " "via --cuda-path, or pass -nocudalib to build without linking with libdevice.">; -def err_drv_no_rocm_installation : Error< - "cannot find ROCm installation. Provide its path via --rocm-path, or pass " - "-nogpulib and -nogpuinc to build without ROCm device library and HIP includes.">; def err_drv_no_rocm_device_lib : Error< - "cannot find device library for %0. Provide path to different ROCm installation " - "via --rocm-path, or pass -nogpulib to build without linking default libraries.">; + "cannot find ROCm device library%select{| for %1}0. Provide its path via --rocm-path or " + "--rocm-device-lib-path, or pass -nogpulib to build without ROCm device library.">; +def err_drv_no_hip_runtime : Error< + "cannot find HIP runtime. Provide its path via --rocm-path, or pass " + "-nogpuinc to build without HIP runtime.">; def err_drv_cuda_version_unsupported : Error< "GPU arch %0 is supported by CUDA versions between %1 and %2 (inclusive), " Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -637,15 +637,19 @@ "Use 32-bit pointers for accessing const/local/shared address spaces">; def rocm_path_EQ : Joined<["--"], "rocm-path=">, Group, HelpText<"ROCm installation path, used for finding and automatically linking required bitcode libraries.">; -def hip_device_lib_path_EQ : Joined<["--"], "hip-device-lib-path=">, Group, - HelpText<"HIP device library path. Alternative to rocm-path.">; +def rocm_device_lib_path_EQ : Joined<["--"], "rocm-device-lib-path=">, Group, + HelpText<"ROCm device library path. Alternative to rocm-path.">; +def : Joined<["--"], "hip-device-lib-path=">, Alias; def hip_device_lib_EQ : Joined<["--"], "hip-device-lib=">, Group, HelpText<"HIP device library">; +def hip_version_EQ : Joined<["--"], "hip-version=">, + HelpText<"HIP version in the format of major.minor.patch">; def fhip_dump_offload_linker_script : Flag<["-"], "fhip-dump-offload-linker-script">, Group, Flags<[NoArgumentUnused, HelpHidden]>; defm hip_new_launch_api : OptInFFlag<"hip-new-launch-api", - "Use new kernel launching API for HIP">; -defm gpu_allow_device_init : OptInFFlag<"gpu-allow-device-init", "Allow device side init function in HIP">; + "Use", "Don't use", " new kernel launching API for HIP">; +defm gpu_allow_device_init : OptInFFlag<"gpu-allow-device-init", + "Allow", "Don't allow", " device side init function in HIP">; def gpu_max_threads_per_block_EQ : Joined<["--"], "gpu-max-threads-per-block=">, Flags<[CC1Option]>, HelpText<"Default max threads per block for kernel launch bounds for HIP">; Index: clang/lib/CodeGen/CGCUDANV.cpp =================================================================== --- clang/lib/CodeGen/CGCUDANV.cpp +++ clang/lib/CodeGen/CGCUDANV.cpp @@ -242,7 +242,7 @@ EmittedKernels.push_back({CGF.CurFn, CGF.CurFuncDecl}); if (CudaFeatureEnabled(CGM.getTarget().getSDKVersion(), CudaFeature::CUDA_USES_NEW_LAUNCH) || - CGF.getLangOpts().HIPUseNewLaunchAPI) + (CGF.getLangOpts().HIP && CGF.getLangOpts().HIPUseNewLaunchAPI)) emitDeviceStubBodyNew(CGF, Args); else emitDeviceStubBodyLegacy(CGF, Args); Index: clang/lib/Driver/ToolChains/AMDGPU.cpp =================================================================== --- clang/lib/Driver/ToolChains/AMDGPU.cpp +++ clang/lib/Driver/ToolChains/AMDGPU.cpp @@ -89,60 +89,111 @@ } } -RocmInstallationDetector::RocmInstallationDetector( - const Driver &D, const llvm::Triple &HostTriple, - const llvm::opt::ArgList &Args) - : D(D) { - struct Candidate { - std::string Path; - bool StrictChecking; - - Candidate(std::string Path, bool StrictChecking = false) - : Path(Path), StrictChecking(StrictChecking) {} - }; +void RocmInstallationDetector::ParseHIPVersionFile(llvm::StringRef V) { + SmallVector VersionParts; + V.split(VersionParts, '\n'); + unsigned Major; + unsigned Minor; + for (auto Part : VersionParts) { + auto Splits = Part.split('='); + if (Splits.first == "HIP_VERSION_MAJOR") + Splits.second.getAsInteger(0, Major); + else if (Splits.first == "HIP_VERSION_MINOR") + Splits.second.getAsInteger(0, Minor); + else if (Splits.first == "HIP_VERSION_PATCH") + VersionPatch = Splits.second.str(); + } + VersionMajorMinor = llvm::VersionTuple(Major, Minor); + DetectedVersion = + (Twine(Major) + "." + Twine(Minor) + "." + VersionPatch).str(); +} +// For candidate specified by --rocm-path we do not do strict check. +SmallVector +RocmInstallationDetector::getInstallationPathCandidates() { SmallVector Candidates; + if (!RocmPathArg.empty()) { + Candidates.emplace_back(RocmPathArg.str()); + return Candidates; + } - if (Args.hasArg(clang::driver::options::OPT_rocm_path_EQ)) { - Candidates.emplace_back( - Args.getLastArgValue(clang::driver::options::OPT_rocm_path_EQ).str()); - } else { - // Try to find relative to the compiler binary. - const char *InstallDir = D.getInstalledDir(); + // Try to find relative to the compiler binary. + const char *InstallDir = D.getInstalledDir(); - // Check both a normal Unix prefix position of the clang binary, as well as - // the Windows-esque layout the ROCm packages use with the host architecture - // subdirectory of bin. + // Check both a normal Unix prefix position of the clang binary, as well as + // the Windows-esque layout the ROCm packages use with the host architecture + // subdirectory of bin. - // Strip off directory (usually bin) - StringRef ParentDir = llvm::sys::path::parent_path(InstallDir); - StringRef ParentName = llvm::sys::path::filename(ParentDir); + // Strip off directory (usually bin) + StringRef ParentDir = llvm::sys::path::parent_path(InstallDir); + StringRef ParentName = llvm::sys::path::filename(ParentDir); - // Some builds use bin/{host arch}, so go up again. - if (ParentName == "bin") { - ParentDir = llvm::sys::path::parent_path(ParentDir); - ParentName = llvm::sys::path::filename(ParentDir); - } + // Some builds use bin/{host arch}, so go up again. + if (ParentName == "bin") { + ParentDir = llvm::sys::path::parent_path(ParentDir); + ParentName = llvm::sys::path::filename(ParentDir); + } - if (ParentName == "llvm") { - // Some versions of the rocm llvm package install to /opt/rocm/llvm/bin - Candidates.emplace_back(llvm::sys::path::parent_path(ParentDir).str(), - /*StrictChecking=*/true); - } + // Some versions of the rocm llvm package install to /opt/rocm/llvm/bin + if (ParentName == "llvm") + ParentDir = llvm::sys::path::parent_path(ParentDir); - Candidates.emplace_back(D.SysRoot + "/opt/rocm"); + Candidates.emplace_back(ParentDir.str(), /*StrictChecking=*/true); + + // Device library may be installed in clang resource directory. + Candidates.emplace_back(D.ResourceDir, /*StrictChecking=*/true); + + Candidates.emplace_back(D.SysRoot + "/opt/rocm", /*StrictChecking=*/true); + return Candidates; +} + +RocmInstallationDetector::RocmInstallationDetector( + const Driver &D, const llvm::Triple &HostTriple, + const llvm::opt::ArgList &Args, bool DetectHIPRuntime, bool DetectDeviceLib) + : D(D) { + RocmPathArg = Args.getLastArgValue(clang::driver::options::OPT_rocm_path_EQ); + RocmDeviceLibPathArg = + Args.getAllArgValues(clang::driver::options::OPT_rocm_device_lib_path_EQ); + if (auto *A = Args.getLastArg(clang::driver::options::OPT_hip_version_EQ)) { + HIPVersionArg = A->getValue(); + unsigned Major = 0; + unsigned Minor = 0; + auto Splits = HIPVersionArg.split('.'); + Splits.first.getAsInteger(0, Major); + Splits = Splits.second.split('.'); + Splits.first.getAsInteger(0, Minor); + VersionPatch = Splits.second.str(); + if (VersionPatch.empty()) + VersionPatch = "0"; + if (Major == 0 || Minor == 0) + D.Diag(diag::err_drv_invalid_value) + << A->getAsString(Args) << HIPVersionArg; + + VersionMajorMinor = llvm::VersionTuple(Major, Minor); + DetectedVersion = + (Twine(Major) + "." + Twine(Minor) + "." + VersionPatch).str(); + } else { + VersionPatch = DefaultVersionPatch; + VersionMajorMinor = + llvm::VersionTuple(DefaultVersionMajor, DefaultVersionMinor); + DetectedVersion = (Twine(DefaultVersionMajor) + "." + + Twine(DefaultVersionMinor) + "." + VersionPatch) + .str(); } - bool NoBuiltinLibs = Args.hasArg(options::OPT_nogpulib); + if (DetectHIPRuntime) + detectHIPRuntime(); + if (DetectDeviceLib) + detectDeviceLibrary(); +} +void RocmInstallationDetector::detectDeviceLibrary() { assert(LibDevicePath.empty()); - if (Args.hasArg(clang::driver::options::OPT_hip_device_lib_path_EQ)) { - LibDevicePath - = Args.getLastArgValue(clang::driver::options::OPT_hip_device_lib_path_EQ); - } else if (const char *LibPathEnv = ::getenv("HIP_DEVICE_LIB_PATH")) { + if (!RocmDeviceLibPathArg.empty()) + LibDevicePath = RocmDeviceLibPathArg[RocmDeviceLibPathArg.size() - 1]; + else if (const char *LibPathEnv = ::getenv("HIP_DEVICE_LIB_PATH")) LibDevicePath = LibPathEnv; - } auto &FS = D.getVFS(); if (!LibDevicePath.empty()) { @@ -153,60 +204,100 @@ return; scanLibDevicePath(); - IsValid = allGenericLibsValid() && !LibDeviceMap.empty(); + HasDeviceLibrary = allGenericLibsValid() && !LibDeviceMap.empty(); return; } + // The install path situation in old versions of ROCm is a real mess, and + // use a different install layout. Multiple copies of the device libraries + // exist for each frontend project, and differ depending on which build + // system produced the packages. Standalone OpenCL builds also have a + // different directory structure from the ROCm OpenCL package. + // + // The desired structure is ${ROCM_ROOT})/amdgcn/bitcode/* or + // ${ROCM_ROOT}/lib/* or ${ROCM_ROOT}/lib/bitcode/* so try to detect this + // layout. + auto Candidates = getInstallationPathCandidates(); for (const auto &Candidate : Candidates) { InstallPath = Candidate.Path; - if (InstallPath.empty() || !FS.exists(InstallPath)) - continue; - - // The install path situation in old versions of ROCm is a real mess, and - // use a different install layout. Multiple copies of the device libraries - // exist for each frontend project, and differ depending on which build - // system produced the packages. Standalone OpenCL builds also have a - // different directory structure from the ROCm OpenCL package. - // - // The desired structure is (${ROCM_ROOT} or - // ${OPENCL_ROOT})/amdgcn/bitcode/*, so try to detect this layout. - - // BinPath = InstallPath + "/bin"; - llvm::sys::path::append(IncludePath, InstallPath, "include"); - llvm::sys::path::append(LibDevicePath, InstallPath, "amdgcn", "bitcode"); + auto CheckDeviceLib = [&]() { + bool CheckLibDevice = (!NoBuiltinLibs || Candidate.StrictChecking); + if (CheckLibDevice && !FS.exists(LibDevicePath)) + return false; + + scanLibDevicePath(); + + if (!NoBuiltinLibs) { + // Check that the required non-target libraries are all available. + if (!allGenericLibsValid()) + return false; + + // Check that we have found at least one libdevice that we can link in + // if -nobuiltinlib hasn't been specified. + if (LibDeviceMap.empty()) + return false; + } + return true; + }; + + LibDevicePath = InstallPath; + llvm::sys::path::append(LibDevicePath, "amdgcn", "bitcode"); + HasDeviceLibrary = CheckDeviceLib(); + if (HasDeviceLibrary) + return; + LibDevicePath = InstallPath; + llvm::sys::path::append(LibDevicePath, "lib"); + HasDeviceLibrary = CheckDeviceLib(); + if (HasDeviceLibrary) + return; + LibDevicePath = InstallPath; + llvm::sys::path::append(LibDevicePath, "lib", "bitcode"); + HasDeviceLibrary = CheckDeviceLib(); + if (HasDeviceLibrary) + return; + } +} - // We don't need the include path for OpenCL, since clang already ships with - // the default header. +void RocmInstallationDetector::detectHIPRuntime() { + auto Candidates = getInstallationPathCandidates(); + auto &FS = D.getVFS(); - bool CheckLibDevice = (!NoBuiltinLibs || Candidate.StrictChecking); - if (CheckLibDevice && !FS.exists(LibDevicePath)) + for (const auto &Candidate : Candidates) { + InstallPath = Candidate.Path; + if (InstallPath.empty() || !FS.exists(InstallPath)) continue; - scanLibDevicePath(); + BinPath = InstallPath; + llvm::sys::path::append(BinPath, "bin"); + IncludePath = InstallPath; + llvm::sys::path::append(IncludePath, "include"); + LibPath = InstallPath; + llvm::sys::path::append(LibPath, "lib"); - if (!NoBuiltinLibs) { - // Check that the required non-target libraries are all available. - if (!allGenericLibsValid()) - continue; + llvm::ErrorOr> VersionFile = + FS.getBufferForFile(BinPath + "/.hipVersion"); + if (!VersionFile && Candidate.StrictChecking) + continue; - // Check that we have found at least one libdevice that we can link in if - // -nobuiltinlib hasn't been specified. - if (LibDeviceMap.empty()) - continue; - } + if (HIPVersionArg.empty() && VersionFile) + ParseHIPVersionFile((*VersionFile)->getBuffer()); - IsValid = true; - break; + HasHIPRuntime = true; + return; } + HasHIPRuntime = false; } void RocmInstallationDetector::print(raw_ostream &OS) const { - if (isValid()) - OS << "Found ROCm installation: " << InstallPath << '\n'; + if (hasHIPRuntime()) + OS << "Found HIP installation: " << InstallPath << ", version " + << DetectedVersion << '\n'; } void RocmInstallationDetector::AddHIPIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { + bool IsRocm35 = VersionMajorMinor <= llvm::VersionTuple(3, 5); + if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { // HIP header includes standard library wrapper headers under clang // cuda_wrappers directory. Since these wrapper headers include_next @@ -218,9 +309,12 @@ // Since standard C++ and other clang include paths are added in other // places after this function, here we only need to make sure wrapper // include path is added. + // + // ROCm 3.5 does not fully support the wrapper headers. Therefore it needs + // a workaround. SmallString<128> P(D.ResourceDir); - llvm::sys::path::append(P, "include"); - llvm::sys::path::append(P, "cuda_wrappers"); + if (!IsRocm35) + llvm::sys::path::append(P, "include", "cuda_wrappers"); CC1Args.push_back("-internal-isystem"); CC1Args.push_back(DriverArgs.MakeArgString(P)); } @@ -228,15 +322,17 @@ if (DriverArgs.hasArg(options::OPT_nogpuinc)) return; - if (!isValid()) { - D.Diag(diag::err_drv_no_rocm_installation); + if (!hasHIPRuntime()) { + D.Diag(diag::err_drv_no_hip_runtime); return; } CC1Args.push_back("-internal-isystem"); CC1Args.push_back(DriverArgs.MakeArgString(getIncludePath())); - CC1Args.push_back("-include"); - CC1Args.push_back("__clang_hip_runtime_wrapper.h"); + if (!IsRocm35) { + CC1Args.push_back("-include"); + CC1Args.push_back("__clang_hip_runtime_wrapper.h"); + } } void amdgpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -386,8 +482,9 @@ /// ROCM Toolchain ROCMToolChain::ROCMToolChain(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) - : AMDGPUToolChain(D, Triple, Args), - RocmInstallation(D, Triple, Args) { } + : AMDGPUToolChain(D, Triple, Args), + RocmInstallation(D, Triple, Args, /*DetectHIPRuntime=*/false, + /*DetectDeviceLib=*/true) {} void AMDGPUToolChain::addClangTargetOptions( const llvm::opt::ArgList &DriverArgs, @@ -418,8 +515,8 @@ if (DriverArgs.hasArg(options::OPT_nogpulib)) return; - if (!RocmInstallation.isValid()) { - getDriver().Diag(diag::err_drv_no_rocm_installation); + if (!RocmInstallation.hasDeviceLibrary()) { + getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 0; return; } @@ -429,7 +526,7 @@ const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind); std::string LibDeviceFile = RocmInstallation.getLibDeviceFile(CanonArch); if (LibDeviceFile.empty()) { - getDriver().Diag(diag::err_drv_no_rocm_device_lib) << GpuArch; + getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 1 << GpuArch; return; } Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -3951,7 +3951,8 @@ } } - const llvm::Triple *AuxTriple = IsCuda ? TC.getAuxTriple() : nullptr; + const llvm::Triple *AuxTriple = + (IsCuda || IsHIP) ? TC.getAuxTriple() : nullptr; bool IsWindowsMSVC = RawTriple.isWindowsMSVCEnvironment(); bool IsIAMCU = RawTriple.isOSIAMCU(); @@ -4866,10 +4867,10 @@ options::OPT_finstrument_functions_after_inlining, options::OPT_finstrument_function_entry_bare); - // NVPTX doesn't support PGO or coverage. There's no runtime support for - // sampling, overhead of call arc collection is way too high and there's no - // way to collect the output. - if (!Triple.isNVPTX()) + // NVPTX/AMDGCN doesn't support PGO or coverage. There's no runtime support + // for sampling, overhead of call arc collection is way too high and there's + // no way to collect the output. + if (!Triple.isNVPTX() && !Triple.isAMDGCN()) addPGOAndCoverageFlags(TC, C, D, Output, Args, CmdArgs); Args.AddLastArg(CmdArgs, options::OPT_fclang_abi_compat_EQ); @@ -4988,6 +4989,11 @@ Args.AddLastArg(CmdArgs, options::OPT_ftrigraphs, options::OPT_fno_trigraphs); + + // HIP headers has minimum C++ standard requirements. Therefore set the + // default language standard. + if (IsHIP) + CmdArgs.push_back(IsWindowsMSVC ? "-std=c++14" : "-std=c++11"); } // GCC's behavior for -Wwrite-strings is a bit strange: @@ -5396,8 +5402,8 @@ // Forward -cl options to -cc1 RenderOpenCLOptions(Args, CmdArgs); - if (Args.hasFlag(options::OPT_fhip_new_launch_api, - options::OPT_fno_hip_new_launch_api, false)) + if (IsHIP && Args.hasFlag(options::OPT_fhip_new_launch_api, + options::OPT_fno_hip_new_launch_api, true)) CmdArgs.push_back("-fhip-new-launch-api"); if (Arg *A = Args.getLastArg(options::OPT_fcf_protection_EQ)) { Index: clang/lib/Driver/ToolChains/Gnu.cpp =================================================================== --- clang/lib/Driver/ToolChains/Gnu.cpp +++ clang/lib/Driver/ToolChains/Gnu.cpp @@ -2658,6 +2658,7 @@ // Print the information about how we detected the GCC installation. GCCInstallation.print(OS); CudaInstallation.print(OS); + RocmInstallation.print(OS); } bool Generic_GCC::IsUnwindTablesDefault(const ArgList &Args) const { Index: clang/lib/Driver/ToolChains/HIP.cpp =================================================================== --- clang/lib/Driver/ToolChains/HIP.cpp +++ clang/lib/Driver/ToolChains/HIP.cpp @@ -224,6 +224,7 @@ // Lookup binaries into the driver directory, this is used to // discover the clang-offload-bundler executable. getProgramPaths().push_back(getDriver().Dir); + RocmInstallation.detectHIPRuntime(); } void HIPToolChain::addClangTargetOptions( @@ -279,9 +280,8 @@ ArgStringList LibraryPaths; // Find in --hip-device-lib-path and HIP_LIBRARY_PATH. - for (auto Path : - DriverArgs.getAllArgValues(options::OPT_hip_device_lib_path_EQ)) - LibraryPaths.push_back(DriverArgs.MakeArgString(Path)); + for (auto P : RocmInstallation.getRocmDeviceLibPathArg()) + LibraryPaths.push_back(DriverArgs.MakeArgString(P)); addDirectoryList(DriverArgs, LibraryPaths, "", "HIP_DEVICE_LIB_PATH"); @@ -291,14 +291,14 @@ for (auto Lib : BCLibs) addBCLib(getDriver(), DriverArgs, CC1Args, LibraryPaths, Lib); } else { - if (!RocmInstallation.isValid()) { - getDriver().Diag(diag::err_drv_no_rocm_installation); + if (!RocmInstallation.hasDeviceLibrary()) { + getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 0; return; } std::string LibDeviceFile = RocmInstallation.getLibDeviceFile(CanonArch); if (LibDeviceFile.empty()) { - getDriver().Diag(diag::err_drv_no_rocm_device_lib) << GpuArch; + getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 1 << GpuArch; return; } Index: clang/lib/Driver/ToolChains/MSVC.cpp =================================================================== --- clang/lib/Driver/ToolChains/MSVC.cpp +++ clang/lib/Driver/ToolChains/MSVC.cpp @@ -807,6 +807,7 @@ void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const { CudaInstallation.print(OS); + RocmInstallation.print(OS); } // Windows SDKs and VC Toolchains group their contents into subdirectories based Index: clang/lib/Driver/ToolChains/ROCm.h =================================================================== --- clang/lib/Driver/ToolChains/ROCm.h +++ clang/lib/Driver/ToolChains/ROCm.h @@ -18,6 +18,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Triple.h" #include "llvm/Option/ArgList.h" +#include "llvm/Support/VersionTuple.h" namespace clang { namespace driver { @@ -38,11 +39,43 @@ } }; + // Installation path candidate. + struct Candidate { + std::string Path; + bool StrictChecking; + + Candidate(std::string Path, bool StrictChecking = false) + : Path(Path), StrictChecking(StrictChecking) {} + }; + const Driver &D; - bool IsValid = false; - // RocmVersion Version = RocmVersion::UNKNOWN; + bool HasHIPRuntime = false; + bool HasDeviceLibrary = false; + + // Default version if not detected or specified. + const unsigned DefaultVersionMajor = 3; + const unsigned DefaultVersionMinor = 5; + const char *DefaultVersionPatch = "0"; + + // The version string in Major.Minor.Patch format. + std::string DetectedVersion; + // Version containing major and minor. + llvm::VersionTuple VersionMajorMinor; + // Version containing patch. + std::string VersionPatch; + + // ROCm path specified by --rocm-path. + StringRef RocmPathArg; + // ROCm device library paths specified by --rocm-device-lib-path. + std::vector RocmDeviceLibPathArg; + // HIP version specified by --hip-version. + StringRef HIPVersionArg; + // Wheter -nogpulib is specified. + bool NoBuiltinLibs = false; + + // Paths SmallString<0> InstallPath; - // SmallString<0> BinPath; + SmallString<0> BinPath; SmallString<0> LibPath; SmallString<0> LibDevicePath; SmallString<0> IncludePath; @@ -75,10 +108,14 @@ mutable llvm::SmallSet ArchsWithBadVersion; void scanLibDevicePath(); + void ParseHIPVersionFile(llvm::StringRef V); + SmallVector getInstallationPathCandidates(); public: RocmInstallationDetector(const Driver &D, const llvm::Triple &HostTriple, - const llvm::opt::ArgList &Args); + const llvm::opt::ArgList &Args, + bool DetectHIPRuntime = true, + bool DetectDeviceLib = false); /// Add arguments needed to link default bitcode libraries. void addCommonBitcodeLibCC1Args(const llvm::opt::ArgList &DriverArgs, @@ -93,8 +130,12 @@ /// most one error per Arch. void CheckRocmVersionSupportsArch(CudaArch Arch) const; - /// Check whether we detected a valid Rocm install. - bool isValid() const { return IsValid; } + /// Check whether we detected a valid HIP runtime. + bool hasHIPRuntime() const { return HasHIPRuntime; } + + /// Check whether we detected a valid ROCm device library. + bool hasDeviceLibrary() const { return HasDeviceLibrary; } + /// Print information about the detected ROCm installation. void print(raw_ostream &OS) const; @@ -163,6 +204,22 @@ void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const; + + void detectDeviceLibrary(); + void detectHIPRuntime(); + + /// Get the values for --rocm-device-lib-path arguments + std::vector getRocmDeviceLibPathArg() const { + return RocmDeviceLibPathArg; + } + + /// Get the value for --rocm-path argument + StringRef getRocmPathArg() const { return RocmPathArg; } + + /// Get the value for --hip-version argument + StringRef getHIPVersionArg() const { return HIPVersionArg; } + + std::string getHIPVersion() const { return DetectedVersion; } }; } // end namespace driver Index: clang/test/Driver/Inputs/rocm/bin/.hipVersion =================================================================== --- /dev/null +++ clang/test/Driver/Inputs/rocm/bin/.hipVersion @@ -0,0 +1,4 @@ +# Auto-generated by cmake +HIP_VERSION_MAJOR=3 +HIP_VERSION_MINOR=6 +HIP_VERSION_PATCH=20214-a2917cd Index: clang/test/Driver/hip-launch-api.hip =================================================================== --- /dev/null +++ clang/test/Driver/hip-launch-api.hip @@ -0,0 +1,17 @@ +// REQUIRES: clang-driver +// REQUIRES: x86-registered-target +// REQUIRES: amdgpu-registered-target + +// By default FE assumes -fhip-new-launch-api. + +// RUN: %clang -### -target x86_64-unknown-linux-gnu -offload-arch=gfx906 %s \ +// RUN: 2>&1 | FileCheck -check-prefixes=NEW %s +// NEW: "-fhip-new-launch-api" + +// RUN: %clang -### -target x86_64-unknown-linux-gnu -offload-arch=gfx906 %s \ +// RUN: -fhip-new-launch-api 2>&1 | FileCheck -check-prefixes=NEW %s +// NEW: "-fhip-new-launch-api" + +// RUN: %clang -### -target x86_64-unknown-linux-gnu -offload-arch=gfx906 %s \ +// RUN: -fno-hip-new-launch-api 2>&1 | FileCheck -check-prefixes=OLD %s +// OLD-NOT: "-fhip-new-launch-api" Index: clang/test/Driver/hip-std.hip =================================================================== --- /dev/null +++ clang/test/Driver/hip-std.hip @@ -0,0 +1,23 @@ +// REQUIRES: clang-driver +// REQUIRES: x86-registered-target +// REQUIRES: amdgpu-registered-target + +// RUN: %clang -### -target x86_64-unknown-linux-gnu -offload-arch=gfx906 %s \ +// RUN: 2>&1 | FileCheck -check-prefixes=DEFAULT %s +// DEFAULT: "{{.*}}clang{{.*}}" "-cc1"{{.*}}"-fcuda-is-device"{{.*}}"-std=c++11" +// DEFAULT: "{{.*}}clang{{.*}}" "-cc1"{{.*}}"-std=c++11" + +// RUN: %clang -### -target x86_64-unknown-linux-gnu -offload-arch=gfx906 %s \ +// RUN: -std=c++17 %s 2>&1 | FileCheck -check-prefixes=SPECIFIED %s +// SPECIFIED: "{{.*}}clang{{.*}}" "-cc1"{{.*}}"-fcuda-is-device"{{.*}}"-std=c++17" +// SPECIFIED: "{{.*}}clang{{.*}}" "-cc1"{{.*}}"-std=c++17" + +// RUN: %clang -### -target x86_64-pc-windows-msvc -offload-arch=gfx906 %s \ +// RUN: 2>&1 | FileCheck -check-prefixes=MSVC-DEF %s +// MSVC-DEF: "{{.*}}clang{{.*}}" "-cc1"{{.*}}"-fcuda-is-device"{{.*}}"-std=c++14" +// MSVC-DEF: "{{.*}}clang{{.*}}" "-cc1"{{.*}}"-std=c++14" + +// RUN: %clang -### -target x86_64-pc-windows-msvc -offload-arch=gfx906 %s \ +// RUN: -std=c++17 %s 2>&1 | FileCheck -check-prefixes=MSVC-SPEC %s +// MSVC-SPEC: "{{.*}}clang{{.*}}" "-cc1"{{.*}}"-fcuda-is-device"{{.*}}"-std=c++17" +// MSVC-SPEC: "{{.*}}clang{{.*}}" "-cc1"{{.*}}"-std=c++17" Index: clang/test/Driver/hip-version.hip =================================================================== --- /dev/null +++ clang/test/Driver/hip-version.hip @@ -0,0 +1,30 @@ +// REQUIRES: clang-driver +// REQUIRES: x86-registered-target +// REQUIRES: amdgpu-registered-target + +// RUN: %clang -v --rocm-path=%S/Inputs/rocm 2>&1 \ +// RUN: | FileCheck -check-prefixes=FOUND %s + +// FOUND: Found HIP installation: {{.*Inputs.*rocm}}, version 3.6.20214-a2917cd + +// When --rocm-path is set and .hipVersion is not found, use default version + +// RUN: %clang -v --rocm-path=%S 2>&1 \ +// RUN: | FileCheck -check-prefixes=DEFAULT %s + +// DEFAULT: Found HIP installation: {{.*Driver}}, version 3.5. + +// RUN: %clang -v --rocm-path=%S --hip-version=3.7.0 2>&1 \ +// RUN: | FileCheck -check-prefixes=SPECIFIED %s + +// SPECIFIED: Found HIP installation: {{.*Driver}}, version 3.7.0 + +// RUN: %clang -v --rocm-path=%S --hip-version=3.7 2>&1 \ +// RUN: | FileCheck -check-prefixes=SPECIFIED2 %s + +// SPECIFIED2: Found HIP installation: {{.*Driver}}, version 3.7.0 + +// RUN: not %clang -v --rocm-path=%S --hip-version=x.y 2>&1 \ +// RUN: | FileCheck -check-prefixes=INVALID %s + +// INVALID: error: invalid value 'x.y' in '--hip-version=x.y' Index: clang/test/Driver/rocm-detect.hip =================================================================== --- clang/test/Driver/rocm-detect.hip +++ clang/test/Driver/rocm-detect.hip @@ -22,6 +22,6 @@ // RUN: | FileCheck -check-prefixes=COMMON,GFX902,NODEFAULTLIBS %s -// GFX902-DEFAULTLIBS: error: cannot find device library for gfx902. Provide path to different ROCm installation via --rocm-path, or pass -nogpulib to build without linking default libraries. +// GFX902-DEFAULTLIBS: error: cannot find ROCm device library for gfx902. Provide its path via --rocm-path or --rocm-device-lib-path, or pass -nogpulib to build without ROCm device library // NODEFAULTLIBS-NOT: error: cannot find Index: clang/test/Driver/rocm-detect.cl =================================================================== --- clang/test/Driver/rocm-detect.cl +++ clang/test/Driver/rocm-detect.cl @@ -16,6 +16,6 @@ // RUN: | FileCheck -check-prefixes=COMMON,GFX902,NODEFAULTLIBS %s -// GFX902-DEFAULTLIBS: error: cannot find device library for gfx902. Provide path to different ROCm installation via --rocm-path, or pass -nogpulib to build without linking default libraries. +// GFX902-DEFAULTLIBS: error: cannot find ROCm device library for gfx902. Provide its path via --rocm-path or --rocm-device-lib-path, or pass -nogpulib to build without ROCm device library // NODEFAULTLIBS-NOT: error: cannot find Index: clang/test/Driver/rocm-not-found.cl =================================================================== --- clang/test/Driver/rocm-not-found.cl +++ clang/test/Driver/rocm-not-found.cl @@ -5,7 +5,7 @@ // RUN: %clang -### --sysroot=%s/no-rocm-there -target amdgcn--amdhsa %s 2>&1 | FileCheck %s --check-prefix ERR // RUN: %clang -### --rocm-path=%s/no-rocm-there -target amdgcn--amdhsa %s 2>&1 | FileCheck %s --check-prefix ERR -// ERR: cannot find ROCm installation. Provide its path via --rocm-path, or pass -nogpulib and -nogpuinc to build without ROCm device library and HIP includes. +// ERR: cannot find ROCm device library. Provide its path via --rocm-path or --rocm-device-lib-path, or pass -nogpulib to build without ROCm device library // Accept nogpulib or nostdlib for OpenCL. // RUN: %clang -### -nogpulib --rocm-path=%s/no-rocm-there %s 2>&1 | FileCheck %s --check-prefix OK