diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp index 345a24b10018b..fd81fec5f452d 100644 --- a/clang/lib/Driver/ToolChains/AMDGPU.cpp +++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp @@ -21,6 +21,67 @@ using namespace clang::driver::toolchains; using namespace clang; using namespace llvm::opt; +void RocmInstallationDetector::scanLibDevicePath() { + assert(!LibDevicePath.empty()); + + const StringRef Suffix(".bc"); + + std::error_code EC; + for (llvm::sys::fs::directory_iterator LI(LibDevicePath, EC), LE; + !EC && LI != LE; LI = LI.increment(EC)) { + StringRef FilePath = LI->path(); + StringRef FileName = llvm::sys::path::filename(FilePath); + if (!FileName.endswith(Suffix)) + continue; + + StringRef BaseName = FileName.drop_back(Suffix.size()); + + if (BaseName == "ocml") { + OCML = FilePath; + } else if (BaseName == "ockl") { + OCKL = FilePath; + } else if (BaseName == "opencl") { + OpenCL = FilePath; + } else if (BaseName == "hip") { + HIP = FilePath; + } else if (BaseName == "oclc_finite_only_off") { + FiniteOnly.Off = FilePath; + } else if (BaseName == "oclc_finite_only_on") { + FiniteOnly.On = FilePath; + } else if (BaseName == "oclc_daz_opt_on") { + DenormalsAreZero.On = FilePath; + } else if (BaseName == "oclc_daz_opt_off") { + DenormalsAreZero.Off = FilePath; + } else if (BaseName == "oclc_correctly_rounded_sqrt_on") { + CorrectlyRoundedSqrt.On = FilePath; + } else if (BaseName == "oclc_correctly_rounded_sqrt_off") { + CorrectlyRoundedSqrt.Off = FilePath; + } else if (BaseName == "oclc_unsafe_math_on") { + UnsafeMath.On = FilePath; + } else if (BaseName == "oclc_unsafe_math_off") { + UnsafeMath.Off = FilePath; + } else if (BaseName == "oclc_wavefrontsize64_on") { + WavefrontSize64.On = FilePath; + } else if (BaseName == "oclc_wavefrontsize64_off") { + WavefrontSize64.Off = FilePath; + } else { + // Process all bitcode filenames that look like + // ocl_isa_version_XXX.amdgcn.bc + const StringRef DeviceLibPrefix = "oclc_isa_version_"; + if (!BaseName.startswith(DeviceLibPrefix)) + continue; + + StringRef IsaVersionNumber = + BaseName.drop_front(DeviceLibPrefix.size()); + + llvm::Twine GfxName = Twine("gfx") + IsaVersionNumber; + SmallString<8> Tmp; + LibDeviceMap.insert( + std::make_pair(GfxName.toStringRef(Tmp), FilePath.str())); + } + } +} + RocmInstallationDetector::RocmInstallationDetector( const Driver &D, const llvm::Triple &HostTriple, const llvm::opt::ArgList &Args) @@ -60,6 +121,27 @@ RocmInstallationDetector::RocmInstallationDetector( bool NoBuiltinLibs = Args.hasArg(options::OPT_nogpulib); + 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")) { + LibDevicePath = LibPathEnv; + } + + if (!LibDevicePath.empty()) { + // Maintain compatability with HIP flag/envvar pointing directly at the + // bitcode library directory. This points directly at the library path instead + // of the rocm root installation. + if (!D.getVFS().exists(LibDevicePath)) + return; + + scanLibDevicePath(); + IsValid = allGenericLibsValid() && !LibDeviceMap.empty(); + return; + } + for (const auto &Candidate : Candidates) { InstallPath = Candidate.Path; if (InstallPath.empty() || !D.getVFS().exists(InstallPath)) @@ -87,62 +169,7 @@ RocmInstallationDetector::RocmInstallationDetector( if (CheckLibDevice && !FS.exists(LibDevicePath)) continue; - const StringRef Suffix(".bc"); - - std::error_code EC; - for (llvm::sys::fs::directory_iterator LI(LibDevicePath, EC), LE; - !EC && LI != LE; LI = LI.increment(EC)) { - StringRef FilePath = LI->path(); - StringRef FileName = llvm::sys::path::filename(FilePath); - if (!FileName.endswith(Suffix)) - continue; - - StringRef BaseName = FileName.drop_back(Suffix.size()); - - if (BaseName == "ocml") { - OCML = FilePath; - } else if (BaseName == "ockl") { - OCKL = FilePath; - } else if (BaseName == "opencl") { - OpenCL = FilePath; - } else if (BaseName == "hip") { - HIP = FilePath; - } else if (BaseName == "oclc_finite_only_off") { - FiniteOnly.Off = FilePath; - } else if (BaseName == "oclc_finite_only_on") { - FiniteOnly.On = FilePath; - } else if (BaseName == "oclc_daz_opt_on") { - DenormalsAreZero.On = FilePath; - } else if (BaseName == "oclc_daz_opt_off") { - DenormalsAreZero.Off = FilePath; - } else if (BaseName == "oclc_correctly_rounded_sqrt_on") { - CorrectlyRoundedSqrt.On = FilePath; - } else if (BaseName == "oclc_correctly_rounded_sqrt_off") { - CorrectlyRoundedSqrt.Off = FilePath; - } else if (BaseName == "oclc_unsafe_math_on") { - UnsafeMath.On = FilePath; - } else if (BaseName == "oclc_unsafe_math_off") { - UnsafeMath.Off = FilePath; - } else if (BaseName == "oclc_wavefrontsize64_on") { - WavefrontSize64.On = FilePath; - } else if (BaseName == "oclc_wavefrontsize64_off") { - WavefrontSize64.Off = FilePath; - } else { - // Process all bitcode filenames that look like - // ocl_isa_version_XXX.amdgcn.bc - const StringRef DeviceLibPrefix = "oclc_isa_version_"; - if (!BaseName.startswith(DeviceLibPrefix)) - continue; - - StringRef IsaVersionNumber = - BaseName.drop_front(DeviceLibPrefix.size()); - - llvm::Twine GfxName = Twine("gfx") + IsaVersionNumber; - SmallString<8> Tmp; - LibDeviceMap.insert( - std::make_pair(GfxName.toStringRef(Tmp), FilePath.str())); - } - } + scanLibDevicePath(); if (!NoBuiltinLibs) { // Check that the required non-target libraries are all available. @@ -298,6 +325,16 @@ llvm::DenormalMode AMDGPUToolChain::getDefaultDenormalModeForType( llvm::DenormalMode::getIEEE(); } +bool AMDGPUToolChain::isWave64(const llvm::opt::ArgList &DriverArgs, + llvm::AMDGPU::GPUKind Kind) { + const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind); + static bool HasWave32 = (ArchAttr & llvm::AMDGPU::FEATURE_WAVE32); + + return !HasWave32 || DriverArgs.hasFlag( + options::OPT_mwavefrontsize64, options::OPT_mno_wavefrontsize64, false); +} + + /// ROCM Toolchain ROCMToolChain::ROCMToolChain(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) @@ -342,11 +379,7 @@ void ROCMToolChain::addClangTargetOptions( return; } - const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind); - static bool HasWave32 = (ArchAttr & llvm::AMDGPU::FEATURE_WAVE32); - - bool Wave64 = !HasWave32 || DriverArgs.hasFlag( - options::OPT_mwavefrontsize64, options::OPT_mno_wavefrontsize64, false); + bool Wave64 = isWave64(DriverArgs, Kind); // TODO: There are way too many flags that change this. Do we need to check // them all? diff --git a/clang/lib/Driver/ToolChains/AMDGPU.h b/clang/lib/Driver/ToolChains/AMDGPU.h index afd71e1f595b3..230af868298ff 100644 --- a/clang/lib/Driver/ToolChains/AMDGPU.h +++ b/clang/lib/Driver/ToolChains/AMDGPU.h @@ -75,6 +75,8 @@ class RocmInstallationDetector { // CheckRocmVersionSupportsArch. mutable llvm::SmallSet ArchsWithBadVersion; + void scanLibDevicePath(); + public: RocmInstallationDetector(const Driver &D, const llvm::Triple &HostTriple, const llvm::opt::ArgList &Args); @@ -216,10 +218,13 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUToolChain : public Generic_ELF { llvm::DenormalMode getDefaultDenormalModeForType( const llvm::opt::ArgList &DriverArgs, const JobAction &JA, const llvm::fltSemantics *FPType = nullptr) const override; + + static bool isWave64(const llvm::opt::ArgList &DriverArgs, + llvm::AMDGPU::GPUKind Kind); }; class LLVM_LIBRARY_VISIBILITY ROCMToolChain : public AMDGPUToolChain { -private: +protected: RocmInstallationDetector RocmInstallation; public: diff --git a/clang/lib/Driver/ToolChains/HIP.cpp b/clang/lib/Driver/ToolChains/HIP.cpp index 3c56229e6bc4e..a7510f721145d 100644 --- a/clang/lib/Driver/ToolChains/HIP.cpp +++ b/clang/lib/Driver/ToolChains/HIP.cpp @@ -287,6 +287,7 @@ void HIPToolChain::addClangTargetOptions( assert(DeviceOffloadingKind == Action::OFK_HIP && "Only HIP offloading kinds are supported for GPUs."); auto Kind = llvm::AMDGPU::parseArchAMDGCN(GpuArch); + const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind); CC1Args.push_back("-target-cpu"); CC1Args.push_back(DriverArgs.MakeArgStringRef(GpuArch)); @@ -333,44 +334,45 @@ void HIPToolChain::addClangTargetOptions( addDirectoryList(DriverArgs, LibraryPaths, "", "HIP_DEVICE_LIB_PATH"); - llvm::SmallVector BCLibs; + // Maintain compatability with --hip-device-lib. + auto BCLibs = DriverArgs.getAllArgValues(options::OPT_hip_device_lib_EQ); + if (!BCLibs.empty()) { + for (auto Lib : BCLibs) + addBCLib(getDriver(), DriverArgs, CC1Args, LibraryPaths, Lib); + } else { + if (!RocmInstallation.isValid()) { + getDriver().Diag(diag::err_drv_no_rocm_installation); + return; + } - // Add bitcode library in --hip-device-lib. - for (auto Lib : DriverArgs.getAllArgValues(options::OPT_hip_device_lib_EQ)) { - BCLibs.push_back(DriverArgs.MakeArgString(Lib)); - } + std::string LibDeviceFile = RocmInstallation.getLibDeviceFile(CanonArch); + if (LibDeviceFile.empty()) { + getDriver().Diag(diag::err_drv_no_rocm_device_lib) << GpuArch; + return; + } - // If --hip-device-lib is not set, add the default bitcode libraries. - if (BCLibs.empty()) { - // Get the bc lib file name for ISA version. For example, - // gfx803 => oclc_isa_version_803.amdgcn.bc. - std::string GFXVersion = GpuArch.drop_front(3).str(); - std::string ISAVerBC = "oclc_isa_version_" + GFXVersion + ".amdgcn.bc"; - - bool FTZDAZ = DriverArgs.hasFlag( - options::OPT_fcuda_flush_denormals_to_zero, - options::OPT_fno_cuda_flush_denormals_to_zero, - getDefaultDenormsAreZeroForTarget(Kind)); - - std::string FlushDenormalControlBC = FTZDAZ ? - "oclc_daz_opt_on.amdgcn.bc" : - "oclc_daz_opt_off.amdgcn.bc"; - - llvm::StringRef WaveFrontSizeBC; - if (stoi(GFXVersion) < 1000) - WaveFrontSizeBC = "oclc_wavefrontsize64_on.amdgcn.bc"; - else - WaveFrontSizeBC = "oclc_wavefrontsize64_off.amdgcn.bc"; - - BCLibs.append({"hip.amdgcn.bc", "ocml.amdgcn.bc", "ockl.amdgcn.bc", - "oclc_finite_only_off.amdgcn.bc", - FlushDenormalControlBC, - "oclc_correctly_rounded_sqrt_on.amdgcn.bc", - "oclc_unsafe_math_off.amdgcn.bc", ISAVerBC, - std::string(WaveFrontSizeBC)}); + // 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_fcuda_flush_denormals_to_zero, + options::OPT_fno_cuda_flush_denormals_to_zero, + getDefaultDenormsAreZeroForTarget(Kind)); + // TODO: Check standard C++ flags? + bool FiniteOnly = false; + bool UnsafeMathOpt = false; + bool FastRelaxedMath = false; + bool CorrectSqrt = true; + bool Wave64 = isWave64(DriverArgs, Kind); + + // Add the HIP specific bitcode library. + CC1Args.push_back("-mlink-builtin-bitcode"); + CC1Args.push_back(DriverArgs.MakeArgString(RocmInstallation.getHIPPath())); + + // Add the generic set of libraries. + RocmInstallation.addCommonBitcodeLibCC1Args( + DriverArgs, CC1Args, LibDeviceFile, Wave64, DAZ, FiniteOnly, + UnsafeMathOpt, FastRelaxedMath, CorrectSqrt); } - for (auto Lib : BCLibs) - addBCLib(getDriver(), DriverArgs, CC1Args, LibraryPaths, Lib); } llvm::opt::DerivedArgList * diff --git a/clang/test/Driver/hip-device-libs.hip b/clang/test/Driver/hip-device-libs.hip index cb1747c2d7984..7135bc6d9cfd4 100644 --- a/clang/test/Driver/hip-device-libs.hip +++ b/clang/test/Driver/hip-device-libs.hip @@ -7,16 +7,16 @@ // Test subtarget with flushing on by default. // RUN: %clang -### -target x86_64-linux-gnu \ -// RUN: --cuda-gpu-arch=gfx803 \ -// RUN: --hip-device-lib-path=%S/Inputs/hip_dev_lib \ +// RUN: --cuda-gpu-arch=gfx803 \ +// RUN: --rocm-path=%S/Inputs/rocm-device-libs \ // RUN: %S/Inputs/hip_multiple_inputs/b.hip \ // RUN: 2>&1 | FileCheck %s --check-prefixes=COM,FLUSHD // Test subtarget with flushing off by ddefault. // RUN: %clang -### -target x86_64-linux-gnu \ -// RUN: --cuda-gpu-arch=gfx900 \ -// RUN: --hip-device-lib-path=%S/Inputs/hip_dev_lib \ +// RUN: --cuda-gpu-arch=gfx900 \ +// RUN: --rocm-path=%S/Inputs/rocm-device-libs \ // RUN: %S/Inputs/hip_multiple_inputs/b.hip \ // RUN: 2>&1 | FileCheck %s --check-prefixes=COM,NOFLUSHD @@ -25,7 +25,7 @@ // RUN: %clang -### -target x86_64-linux-gnu \ // RUN: --cuda-gpu-arch=gfx900 \ // RUN: -fcuda-flush-denormals-to-zero \ -// RUN: --hip-device-lib-path=%S/Inputs/hip_dev_lib \ +// RUN: --rocm-path=%S/Inputs/rocm-device-libs \ // RUN: %S/Inputs/hip_multiple_inputs/b.hip \ // RUN: 2>&1 | FileCheck %s --check-prefixes=COM,FLUSHD @@ -34,7 +34,7 @@ // RUN: %clang -### -target x86_64-linux-gnu \ // RUN: --cuda-gpu-arch=gfx803 \ // RUN: -fno-cuda-flush-denormals-to-zero \ -// RUN: --hip-device-lib-path=%S/Inputs/hip_dev_lib \ +// RUN: --rocm-path=%S/Inputs/rocm-device-libs \ // RUN: %S/Inputs/hip_multiple_inputs/b.hip \ // RUN: 2>&1 | FileCheck %s --check-prefixes=COM,NOFLUSHD @@ -43,7 +43,7 @@ // RUN: %clang -### -target x86_64-linux-gnu \ // RUN: --cuda-gpu-arch=gfx900 \ // RUN: -fno-cuda-flush-denormals-to-zero \ -// RUN: --hip-device-lib-path=%S/Inputs/hip_dev_lib \ +// RUN: --rocm-path=%S/Inputs/rocm-device-libs \ // RUN: %S/Inputs/hip_multiple_inputs/b.hip \ // RUN: 2>&1 | FileCheck %s --check-prefixes=COM,NOFLUSHD @@ -52,7 +52,7 @@ // RUN: %clang -### -target x86_64-linux-gnu \ // RUN: --cuda-gpu-arch=gfx803 \ // RUN: -fcuda-flush-denormals-to-zero \ -// RUN: --hip-device-lib-path=%S/Inputs/hip_dev_lib \ +// RUN: --rocm-path=%S/Inputs/rocm-device-libs \ // RUN: %S/Inputs/hip_multiple_inputs/b.hip \ // RUN: 2>&1 | FileCheck %s --check-prefixes=COM,FLUSHD @@ -61,7 +61,7 @@ // RUN: %clang -### -target x86_64-linux-gnu \ // RUN: --cuda-gpu-arch=gfx803 \ // RUN: -fcuda-flush-denormals-to-zero -fno-cuda-flush-denormals-to-zero \ -// RUN: --hip-device-lib-path=%S/Inputs/hip_dev_lib \ +// RUN: --rocm-path=%S/Inputs/rocm-device-libs \ // RUN: %S/Inputs/hip_multiple_inputs/b.hip \ // RUN: 2>&1 | FileCheck %s --check-prefixes=COM,NOFLUSHD @@ -69,7 +69,7 @@ // RUN: %clang -### -target x86_64-linux-gnu \ // RUN: --cuda-gpu-arch=gfx900 \ // RUN: -fcuda-flush-denormals-to-zero -fno-cuda-flush-denormals-to-zero \ -// RUN: --hip-device-lib-path=%S/Inputs/hip_dev_lib \ +// RUN: --rocm-path=%S/Inputs/rocm-device-libs \ // RUN: %S/Inputs/hip_multiple_inputs/b.hip \ // RUN: 2>&1 | FileCheck %s --check-prefixes=COM,NOFLUSHD @@ -77,7 +77,7 @@ // RUN: %clang -### -target x86_64-linux-gnu \ // RUN: --cuda-gpu-arch=gfx900 \ // RUN: -fno-cuda-flush-denormals-to-zero -fcuda-flush-denormals-to-zero \ -// RUN: --hip-device-lib-path=%S/Inputs/hip_dev_lib \ +// RUN: --rocm-path=%S/Inputs/rocm-device-libs \ // RUN: %S/Inputs/hip_multiple_inputs/b.hip \ // RUN: 2>&1 | FileCheck %s --check-prefixes=COM,FLUSHD @@ -85,22 +85,36 @@ // RUN: %clang -### -target x86_64-linux-gnu \ // RUN: --cuda-gpu-arch=gfx803 \ // RUN: -fno-cuda-flush-denormals-to-zero -fcuda-flush-denormals-to-zero \ -// RUN: --hip-device-lib-path=%S/Inputs/hip_dev_lib \ +// RUN: --rocm-path=%S/Inputs/rocm-device-libs \ // RUN: %S/Inputs/hip_multiple_inputs/b.hip \ // RUN: 2>&1 | FileCheck %s --check-prefixes=COM,FLUSHD -// Test environment variable HIP_DEVICE_LIB_PATH +// Test --hip-device-lib-path flag +// RUN: %clang -### -target x86_64-linux-gnu \ +// RUN: --cuda-gpu-arch=gfx803 \ +// RUN: --hip-device-lib-path=%S/Inputs/rocm-device-libs/amdgcn/bitcode \ +// RUN: %S/Inputs/hip_multiple_inputs/b.hip \ +// RUN: 2>&1 | FileCheck %s --check-prefixes=COM,FLUSHD -// RUN: env HIP_DEVICE_LIB_PATH=%S/Inputs/hip_dev_lib \ + +// Test environment variable HIP_DEVICE_LIB_PATH +// RUN: env HIP_DEVICE_LIB_PATH=%S/Inputs/rocm-device-libs/amdgcn/bitcode \ // RUN: %clang -### -target x86_64-linux-gnu \ // RUN: --cuda-gpu-arch=gfx900 \ // RUN: %S/Inputs/hip_multiple_inputs/b.hip \ // RUN: 2>&1 | FileCheck %s --check-prefixes=COM // COM: {{"[^"]*clang[^"]*"}} -// COM-SAME: "-mlink-builtin-bitcode" "{{.*}}hip.amdgcn.bc" -// COM-SAME: "-mlink-builtin-bitcode" "{{.*}}ocml.amdgcn.bc" -// COM-SAME: "-mlink-builtin-bitcode" "{{.*}}ockl.amdgcn.bc" -// FLUSHD-SAME: "-mlink-builtin-bitcode" "{{.*}}oclc_daz_opt_on.amdgcn.bc" -// NOFLUSHD-SAME: "-mlink-builtin-bitcode" "{{.*}}oclc_daz_opt_off.amdgcn.bc" +// COM-SAME: "-mlink-builtin-bitcode" "{{.*}}hip.bc" +// COM-SAME: "-mlink-builtin-bitcode" "{{.*}}ocml.bc" +// COM-SAME: "-mlink-builtin-bitcode" "{{.*}}ockl.bc" + +// FLUSHD-SAME: "-mlink-builtin-bitcode" "{{.*}}oclc_daz_opt_on.bc" +// NOFLUSHD-SAME: "-mlink-builtin-bitcode" "{{.*}}oclc_daz_opt_off.bc" + +// COM-SAME: "-mlink-builtin-bitcode" "{{.*}}oclc_unsafe_math_off.bc" +// COM-SAME: "-mlink-builtin-bitcode" "{{.*}}oclc_finite_only_off.bc" +// COM-SAME: "-mlink-builtin-bitcode" "{{.*}}oclc_correctly_rounded_sqrt_on.bc" +// COM-SAME: "-mlink-builtin-bitcode" "{{.*}}oclc_wavefrontsize64_on.bc" +// COM-SAME: "-mlink-builtin-bitcode" "{{.*}}oclc_isa_version_{{[0-9]+}}.bc" diff --git a/clang/test/Driver/rocm-device-libs.cl b/clang/test/Driver/rocm-device-libs.cl index 7878954491ac6..23cabd654391d 100644 --- a/clang/test/Driver/rocm-device-libs.cl +++ b/clang/test/Driver/rocm-device-libs.cl @@ -121,6 +121,21 @@ +// Test --hip-device-lib-path format +// RUN: %clang -### -target amdgcn-amd-amdhsa \ +// RUN: -x cl -mcpu=gfx900 \ +// RUN: --hip-device-lib-path=%S/Inputs/rocm-device-libs/amdgcn/bitcode \ +// RUN: %S/opencl.cl \ +// RUN: 2>&1 | FileCheck -dump-input-on-failure --check-prefixes=COMMON,COMMON-DEFAULT,GFX900-DEFAULT,GFX900,WAVE64 %s + +// Test environment variable HIP_DEVICE_LIB_PATH +// RUN: env HIP_DEVICE_LIB_PATH=%S/Inputs/rocm-device-libs/amdgcn/bitcode %clang -### -target amdgcn-amd-amdhsa \ +// RUN: -x cl -mcpu=gfx900 \ +// RUN: %S/opencl.cl \ +// RUN: 2>&1 | FileCheck -dump-input-on-failure --check-prefixes=COMMON,COMMON-DEFAULT,GFX900-DEFAULT,GFX900,WAVE64 %s + + + // COMMON: "-triple" "amdgcn-amd-amdhsa" // COMMON-SAME: "-mlink-builtin-bitcode" "{{.*}}/amdgcn/bitcode/opencl.bc" // COMMON-SAME: "-mlink-builtin-bitcode" "{{.*}}/amdgcn/bitcode/ocml.bc"