diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -67,7 +67,7 @@ "libdevice">; def err_drv_no_rocm_device_lib : Error< - "cannot find ROCm device library%select{| for %1}0; provide its path via " + "cannot find ROCm device library%select{| for %1|for ABI version %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< diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3440,8 +3440,8 @@ NegFlag>, Group; def mcode_object_version_EQ : Joined<["-"], "mcode-object-version=">, Group, - HelpText<"Specify code object ABI version. Defaults to 3. (AMDGPU only)">, - MetaVarName<"">, Values<"2,3,4">; + HelpText<"Specify code object ABI version. Defaults to 4. (AMDGPU only)">, + MetaVarName<"">, Values<"2,3,4,5">; defm code_object_v3_legacy : SimpleMFlag<"code-object-v3", "Legacy option to specify code object ABI V3", diff --git a/clang/lib/Driver/ToolChains/AMDGPU.h b/clang/lib/Driver/ToolChains/AMDGPU.h --- a/clang/lib/Driver/ToolChains/AMDGPU.h +++ b/clang/lib/Driver/ToolChains/AMDGPU.h @@ -142,7 +142,8 @@ // Returns a list of device library names shared by different languages llvm::SmallVector getCommonDeviceLibNames(const llvm::opt::ArgList &DriverArgs, - const std::string &GPUArch) const; + const std::string &GPUArch, + bool isOpenMP = false) const; }; } // end namespace toolchains diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp --- a/clang/lib/Driver/ToolChains/AMDGPU.cpp +++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp @@ -91,6 +91,7 @@ else if (FileName.endswith(Suffix)) BaseName = FileName.drop_back(Suffix.size()); + const StringRef ABIVersionPrefix = "abi_version_"; if (BaseName == "ocml") { OCML = FilePath; } else if (BaseName == "ockl") { @@ -121,6 +122,12 @@ WavefrontSize64.On = FilePath; } else if (BaseName == "oclc_wavefrontsize64_off") { WavefrontSize64.Off = FilePath; + } else if (BaseName.startswith(ABIVersionPrefix)) { + unsigned ABIVersionNumber; + if (BaseName.drop_front(ABIVersionPrefix.size()) + .getAsInteger(/*Redex=*/0, ABIVersionNumber)) + continue; + ABIVersionMap[ABIVersionNumber] = FilePath.str(); } else { // Process all bitcode filenames that look like // ocl_isa_version_XXX.amdgcn.bc @@ -822,20 +829,16 @@ if (DriverArgs.hasArg(options::OPT_nogpulib)) return; - if (!RocmInstallation.hasDeviceLibrary()) { - getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 0; - return; - } - // Get the device name and canonicalize it const StringRef GpuArch = getGPUArch(DriverArgs); auto Kind = llvm::AMDGPU::parseArchAMDGCN(GpuArch); 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) << 1 << GpuArch; + auto ABIVer = DeviceLibABIVersion::fromCodeObjectVersion( + getAMDGPUCodeObjectVersion(getDriver(), DriverArgs)); + if (!RocmInstallation.checkCommonBitcodeLibs(CanonArch, LibDeviceFile, + ABIVer)) return; - } bool Wave64 = isWave64(DriverArgs, Kind); @@ -858,7 +861,7 @@ // Add the generic set of libraries. BCLibs.append(RocmInstallation.getCommonBitcodeLibs( DriverArgs, LibDeviceFile, Wave64, DAZ, FiniteOnly, UnsafeMathOpt, - FastRelaxedMath, CorrectSqrt)); + FastRelaxedMath, CorrectSqrt, ABIVer, false)); llvm::for_each(BCLibs, [&](StringRef BCFile) { CC1Args.push_back("-mlink-builtin-bitcode"); @@ -866,12 +869,29 @@ }); } +bool RocmInstallationDetector::checkCommonBitcodeLibs( + StringRef GPUArch, StringRef LibDeviceFile, + DeviceLibABIVersion ABIVer) const { + if (!hasDeviceLibrary()) { + D.Diag(diag::err_drv_no_rocm_device_lib) << 0; + return false; + } + if (LibDeviceFile.empty()) { + D.Diag(diag::err_drv_no_rocm_device_lib) << 1 << GPUArch; + return false; + } + if (ABIVer.requiresLibrary() && getABIVersionPath(ABIVer).empty()) { + D.Diag(diag::err_drv_no_rocm_device_lib) << 2 << ABIVer.toString(); + return false; + } + return true; +} + llvm::SmallVector RocmInstallationDetector::getCommonBitcodeLibs( const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile, bool Wave64, bool DAZ, bool FiniteOnly, bool UnsafeMathOpt, bool FastRelaxedMath, - bool CorrectSqrt) const { - + bool CorrectSqrt, DeviceLibABIVersion ABIVer, bool isOpenMP = false) const { llvm::SmallVector BCLibs; auto AddBCLib = [&](StringRef BCFile) { BCLibs.push_back(BCFile.str()); }; @@ -884,6 +904,9 @@ AddBCLib(getCorrectlyRoundedSqrtPath(CorrectSqrt)); AddBCLib(getWavefrontSize64Path(Wave64)); AddBCLib(LibDeviceFile); + auto ABIVerPath = getABIVersionPath(ABIVer); + if (!ABIVerPath.empty()) + AddBCLib(ABIVerPath); return BCLibs; } @@ -897,15 +920,17 @@ llvm::SmallVector ROCMToolChain::getCommonDeviceLibNames(const llvm::opt::ArgList &DriverArgs, - const std::string &GPUArch) const { + const std::string &GPUArch, + bool isOpenMP) const { auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch); 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) << 1 << GPUArch; + auto ABIVer = DeviceLibABIVersion::fromCodeObjectVersion( + getAMDGPUCodeObjectVersion(getDriver(), DriverArgs)); + if (!RocmInstallation.checkCommonBitcodeLibs(CanonArch, LibDeviceFile, + 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 @@ -927,5 +952,5 @@ return RocmInstallation.getCommonBitcodeLibs( DriverArgs, LibDeviceFile, Wave64, DAZ, FiniteOnly, UnsafeMathOpt, - FastRelaxedMath, CorrectSqrt); + FastRelaxedMath, CorrectSqrt, ABIVer, isOpenMP); } diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1910,7 +1910,7 @@ void tools::checkAMDGPUCodeObjectVersion(const Driver &D, const llvm::opt::ArgList &Args) { const unsigned MinCodeObjVer = 2; - const unsigned MaxCodeObjVer = 4; + const unsigned MaxCodeObjVer = 5; // Emit warnings for legacy options even if they are overridden. if (Args.hasArg(options::OPT_mno_code_object_v3_legacy)) diff --git a/clang/lib/Driver/ToolChains/ROCm.h b/clang/lib/Driver/ToolChains/ROCm.h --- a/clang/lib/Driver/ToolChains/ROCm.h +++ b/clang/lib/Driver/ToolChains/ROCm.h @@ -22,6 +22,26 @@ namespace clang { namespace driver { +/// ABI version of device library. +struct DeviceLibABIVersion { + unsigned ABIVersion = 0; + DeviceLibABIVersion(unsigned V) : ABIVersion(V) {} + static DeviceLibABIVersion fromCodeObjectVersion(unsigned CodeObjectVersion) { + if (CodeObjectVersion < 4) + CodeObjectVersion = 4; + return DeviceLibABIVersion(CodeObjectVersion * 100); + } + /// Whether ABI version bc file is requested. + /// ABIVersion is code object version multiplied by 100. Code object v4 + /// and below works with ROCm 5.0 and below which does not have + /// abi_version_*.bc. Code object v5 requires abi_version_500.bc. + bool requiresLibrary() { return ABIVersion >= 500; } + std::string toString() { + assert(ABIVersion % 100 == 0 && "Not supported"); + return Twine(ABIVersion / 100).str(); + } +}; + /// A class to find a viable ROCM installation /// TODO: Generalize to handle libclc. class RocmInstallationDetector { @@ -107,6 +127,10 @@ ConditionalLibrary DenormalsAreZero; ConditionalLibrary CorrectlyRoundedSqrt; + // Maps ABI version to library path. The version number is in the format of + // three digits as used in the ABI version library name. + std::map ABIVersionMap; + // Cache ROCm installation search paths. SmallVector ROCmSearchDirs; bool PrintROCmSearchDirs; @@ -142,7 +166,12 @@ getCommonBitcodeLibs(const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile, bool Wave64, bool DAZ, bool FiniteOnly, bool UnsafeMathOpt, - bool FastRelaxedMath, bool CorrectSqrt) const; + bool FastRelaxedMath, bool CorrectSqrt, + DeviceLibABIVersion ABIVer, bool isOpenMP) 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, + DeviceLibABIVersion ABIVer) const; /// Check whether we detected a valid HIP runtime. bool hasHIPRuntime() const { return HasHIPRuntime; } @@ -214,6 +243,13 @@ return CorrectlyRoundedSqrt.get(Enabled); } + StringRef getABIVersionPath(DeviceLibABIVersion ABIVer) const { + auto Loc = ABIVersionMap.find(ABIVer.ABIVersion); + if (Loc == ABIVersionMap.end()) + return StringRef(); + return Loc->second; + } + /// Get libdevice file for given architecture std::string getLibDeviceFile(StringRef Gpu) const { return LibDeviceMap.lookup(Gpu); diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/asanrtl.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/asanrtl.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/hip.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/hip.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/ockl.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/ockl.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_correctly_rounded_sqrt_off.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_correctly_rounded_sqrt_off.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_correctly_rounded_sqrt_on.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_correctly_rounded_sqrt_on.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_daz_opt_off.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_daz_opt_off.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_daz_opt_on.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_daz_opt_on.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_finite_only_off.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_finite_only_off.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_finite_only_on.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_finite_only_on.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_1010.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_1010.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_1011.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_1011.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_1012.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_1012.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_803.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_803.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_900.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_900.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_908.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_908.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_unsafe_math_off.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_unsafe_math_off.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_unsafe_math_on.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_unsafe_math_on.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_wavefrontsize64_off.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_wavefrontsize64_off.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_wavefrontsize64_on.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_wavefrontsize64_on.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/ocml.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/ocml.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/opencl.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/opencl.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode/abi_version_400.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode/abi_version_400.bc new file mode 100644 diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode/abi_version_500.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode/abi_version_500.bc new file mode 100644 diff --git a/clang/test/Driver/hip-code-object-version.hip b/clang/test/Driver/hip-code-object-version.hip --- a/clang/test/Driver/hip-code-object-version.hip +++ b/clang/test/Driver/hip-code-object-version.hip @@ -47,6 +47,16 @@ // V4: "-mllvm" "--amdhsa-code-object-version=4" // V4: "-targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx906" +// Check bundle ID for code object version 5. + +// RUN: %clang -### -target x86_64-linux-gnu \ +// RUN: -mcode-object-version=5 \ +// RUN: --offload-arch=gfx906 -nogpulib \ +// RUN: %s 2>&1 | FileCheck -check-prefix=V5 %s + +// V5: "-mllvm" "--amdhsa-code-object-version=5" +// V5: "-targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx906" + // Check bundle ID for code object version default // RUN: %clang -### -target x86_64-linux-gnu \ diff --git a/clang/test/Driver/hip-device-libs.hip b/clang/test/Driver/hip-device-libs.hip --- a/clang/test/Driver/hip-device-libs.hip +++ b/clang/test/Driver/hip-device-libs.hip @@ -137,6 +137,49 @@ // RUN: --rocm-path=%S/Inputs/rocm %S/Inputs/hip_multiple_inputs/b.hip \ // RUN: 2>&1 | FileCheck %s --check-prefixes=DIVSQRT +// Test default code object version. +// RUN: %clang -### -target x86_64-linux-gnu --offload-arch=gfx900 \ +// RUN: --rocm-path=%S/Inputs/rocm %S/Inputs/hip_multiple_inputs/b.hip \ +// RUN: 2>&1 | FileCheck %s --check-prefixes=ABI4 + +// Test default code object version with old device library without abi_version_400.bc +// RUN: %clang -### -target x86_64-linux-gnu --offload-arch=gfx900 \ +// RUN: --hip-device-lib-path=%S/Inputs/rocm/amdgcn/bitcode-no-abi-ver \ +// RUN: --rocm-path=%S/Inputs/rocm %S/Inputs/hip_multiple_inputs/b.hip \ +// RUN: 2>&1 | FileCheck %s --check-prefixes=NOABI4 + +// Test -mcode-object-version=3 +// RUN: %clang -### -target x86_64-linux-gnu --offload-arch=gfx900 \ +// RUN: -mcode-object-version=3 \ +// RUN: --rocm-path=%S/Inputs/rocm %S/Inputs/hip_multiple_inputs/b.hip \ +// RUN: 2>&1 | FileCheck %s --check-prefixes=ABI4 + +// Test -mcode-object-version=4 +// RUN: %clang -### -target x86_64-linux-gnu --offload-arch=gfx900 \ +// RUN: -mcode-object-version=4 \ +// RUN: --rocm-path=%S/Inputs/rocm %S/Inputs/hip_multiple_inputs/b.hip \ +// RUN: 2>&1 | FileCheck %s --check-prefixes=ABI4 + +// Test -mcode-object-version=4 with old device library without abi_version_400.bc +// RUN: %clang -### -target x86_64-linux-gnu --offload-arch=gfx900 \ +// RUN: -mcode-object-version=4 \ +// RUN: --hip-device-lib-path=%S/Inputs/rocm/amdgcn/bitcode-no-abi-ver \ +// RUN: --rocm-path=%S/Inputs/rocm %S/Inputs/hip_multiple_inputs/b.hip \ +// RUN: 2>&1 | FileCheck %s --check-prefixes=NOABI4 + +// Test -mcode-object-version=5 +// RUN: %clang -### -target x86_64-linux-gnu --offload-arch=gfx900 \ +// RUN: -mcode-object-version=5 \ +// RUN: --rocm-path=%S/Inputs/rocm %S/Inputs/hip_multiple_inputs/b.hip \ +// RUN: 2>&1 | FileCheck %s --check-prefixes=ABI5 + +// Test -mcode-object-version=5 with old device library without abi_version_400.bc +// RUN: %clang -### -target x86_64-linux-gnu --offload-arch=gfx900 \ +// RUN: -mcode-object-version=5 \ +// RUN: --hip-device-lib-path=%S/Inputs/rocm/amdgcn/bitcode-no-abi-ver \ +// RUN: --rocm-path=%S/Inputs/rocm %S/Inputs/hip_multiple_inputs/b.hip \ +// RUN: 2>&1 | FileCheck %s --check-prefixes=NOABI5 + // ALL-NOT: error: // ALL: {{"[^"]*clang[^"]*"}} // ALL-SAME: "-mlink-builtin-bitcode" "{{.*}}hip.bc" @@ -172,3 +215,12 @@ // DIVSQRT-SAME: "-mlink-builtin-bitcode" "{{.*}}oclc_unsafe_math_off.bc" // DIVSQRT-SAME: "-mlink-builtin-bitcode" "{{.*}}oclc_finite_only_off.bc" // DIVSQRT-SAME: "-mlink-builtin-bitcode" "{{.*}}oclc_correctly_rounded_sqrt_off.bc" + +// ABI4-NOT: error: +// ABI4: "-mlink-builtin-bitcode" "{{.*}}abi_version_400.bc" +// ABI5-NOT: error: +// ABI5: "-mlink-builtin-bitcode" "{{.*}}abi_version_500.bc" +// NOABI4-NOT: error: +// NOABI4-NOT: "-mlink-builtin-bitcode" "{{.*}}abi_version_400.bc" +// NOABI4-NOT: "-mlink-builtin-bitcode" "{{.*}}abi_version_500.bc" +// NOABI5: error: cannot find ROCm device libraryfor ABI version 5; provide its path via '--rocm-path' or '--rocm-device-lib-path', or pass '-nogpulib' to build without ROCm device library