# cat 00-D69582.patch --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -247,6 +247,9 @@ /// stored in it, and will clean them up when torn down. mutable llvm::StringMap> ToolChains; + /// Number of parallel jobs. + unsigned NumParallelJobs; + private: /// TranslateInputArgs - Create a new derived argument list from the input /// arguments, after applying the standard argument translations. @@ -549,6 +552,12 @@ /// Get the specific kind of LTO being performed. LTOKind getLTOMode() const { return LTOMode; } + /// Get the number of parallel jobs. + unsigned getNumberOfParallelJobs() const { return NumParallelJobs; } + + /// Set the number of parallel jobs. + void setNumberOfParallelJobs(unsigned N) { NumParallelJobs = N; } + private: /// Tries to load options from configuration file. --- a/clang/include/clang/Driver/Job.h +++ b/clang/include/clang/Driver/Job.h @@ -73,6 +73,9 @@ /// See Command::setEnvironment std::vector Environment; + /// Dependent actions + llvm::SmallVector DependentActions; + /// When a response file is needed, we try to put most arguments in an /// exclusive file, while others remains as regular command line arguments. /// This functions fills a vector with the regular command line arguments, @@ -227,6 +227,10 @@ return ProcStat; } + const llvm::SmallVector &getDependentActions() const { + return DependentActions; + } + protected: /// Optionally print the filenames to be compiled void PrintFileNames() const; --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -726,6 +726,8 @@ def P : Flag<["-"], "P">, Flags<[CC1Option,FlangOption,FC1Option]>, Group, HelpText<"Disable linemarker output in -E mode">, MarshallingInfoNegativeFlag>; +def parallel_jobs_EQ : Joined<["-"], "parallel-jobs=">, Flags<[NoXarchOption]>, + HelpText<"Number of parallel jobs">; def Qy : Flag<["-"], "Qy">, Flags<[CC1Option]>, HelpText<"Emit metadata containing compiler name and version">; def Qn : Flag<["-"], "Qn">, Flags<[CC1Option]>, --- a/clang/lib/Driver/Compilation.cpp +++ b/clang/lib/Driver/Compilation.cpp @@ -15,6 +15,7 @@ #include "clang/Driver/Options.h" #include "clang/Driver/ToolChain.h" #include "clang/Driver/Util.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/None.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" @@ -25,8 +26,11 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/raw_ostream.h" #include +#include +#include #include #include +#include #include using namespace clang; @@ -220,22 +224,134 @@ return !ActionFailed(&C.getSource(), FailingCommands); } +namespace { +class JobScheduler { +public: + enum JobState { JS_WAIT, JS_RUN, JS_DONE, JS_FAIL }; + JobScheduler(const JobList &Jobs, size_t NJobs = 1) + : Jobs(Jobs), NumJobs(NJobs) { +#if !LLVM_ENABLE_THREADS + NumJobs = 1; +#endif + for (auto &Job : Jobs) { + JState[&Job] = JS_WAIT; + for (const auto *AI : Job.getDependentActions()) { + for (const auto *CI : ActToCmds[AI]) { + DependentCmds[&Job].push_back(CI); + } + } + for (const auto *CI : ActToCmds[&Job.getSource()]) { + DependentCmds[&Job].push_back(CI); + } + ActToCmds[&Job.getSource()].push_back(&Job); + } + } + /// \return true if all jobs are done. Otherwise, \p Next contains the + /// the next job ready to be executed if it is not null pointer. Otherwise + /// all jobs are running or waiting. + bool IsDone(const Command *&Next) { + std::lock_guard lock(Mutex); + Next = nullptr; + unsigned Done = 0; + unsigned Running = 0; + for (auto &Cmd : Jobs) { + switch (JState[&Cmd]) { + case JS_RUN: + ++Running; + break; + case JS_DONE: + case JS_FAIL: + ++Done; + break; + case JS_WAIT: { + bool InputsReady = true; + for (const auto *CI : DependentCmds[&Cmd]) { + if (JState[CI] == JS_FAIL) { + JState[&Cmd] = JS_FAIL; + ++Done; + InputsReady = false; + break; + } + if (JState[CI] != JS_DONE) { + InputsReady = false; + break; + } + } + if (!Next && InputsReady) { + Next = &Cmd; + } + break; + } + } + } + if (Running >= NumJobs) + Next = nullptr; + return Done == Jobs.size(); + } + + void setJobState(const Command *Cmd, JobState JS) { + std::lock_guard lock(Mutex); + JState[Cmd] = JS; + } + + void launch(std::function Work) { +#if LLVM_ENABLE_THREADS + if (NumJobs == 1) { + Work(); + return; + } + std::thread Th(Work); + Th.detach(); +#else + Work(); +#endif + } + +private: + std::mutex Mutex; + const JobList &Jobs; + llvm::DenseMap JState; + llvm::DenseMap> + ActToCmds; + llvm::DenseMap> + DependentCmds; + size_t NumJobs; // Number of parallel jobs to run +}; +} // namespace void Compilation::ExecuteJobs(const JobList &Jobs, FailingCommandList &FailingCommands) const { // According to UNIX standard, driver need to continue compiling all the // inputs on the command line even one of them failed. // In all but CLMode, execute all the jobs unless the necessary inputs for the // job is missing due to previous failures. - for (const auto &Job : Jobs) { - if (!InputsOk(Job, FailingCommands)) + JobScheduler JS(Jobs, getDriver().getNumberOfParallelJobs()); + + const Command *Next = nullptr; + while (!JS.IsDone(Next)) { + if (!Next) { + std::this_thread::yield(); continue; - const Command *FailingCommand = nullptr; - if (int Res = ExecuteCommand(Job, FailingCommand)) { - FailingCommands.push_back(std::make_pair(Res, FailingCommand)); + } + + if (!InputsOk(*Next, FailingCommands)) { + JS.setJobState(Next, JobScheduler::JS_FAIL); // Bail as soon as one command fails in cl driver mode. if (TheDriver.IsCLMode()) return; + continue; } + + JS.setJobState(Next, JobScheduler::JS_RUN); + auto Work = [&, Next]() { + const Command *FailingCommand = nullptr; + if (int Res = ExecuteCommand(*Next, FailingCommand)) { + JS.setJobState(Next, JobScheduler::JS_FAIL); + FailingCommands.push_back(std::make_pair(Res, FailingCommand)); + } else { + JS.setJobState(Next, JobScheduler::JS_DONE); + } + }; + JS.launch(Work); } } --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -51,6 +51,7 @@ #include "ToolChains/XCore.h" #include "ToolChains/ZOS.h" #include "clang/Basic/TargetID.h" +#include "clang/Driver/OptionUtils.h" #include "clang/Basic/Version.h" #include "clang/Config/config.h" #include "clang/Driver/Action.h" @@ -63,6 +64,7 @@ #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include "clang/Driver/Types.h" +#include "clang/Driver/Util.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallSet.h" @@ -194,7 +196,7 @@ CCPrintHeaders(false), CCLogDiagnostics(false), CCGenDiagnostics(false), CCPrintProcessStats(false), TargetTriple(TargetTriple), Saver(Alloc), CheckInputsExist(true), GenReproducer(false), - SuppressMissingInputWarning(false) { + SuppressMissingInputWarning(false), NumParallelJobs(1) { // Provide a sane fallback if no VFS is specified. if (!this->VFS) this->VFS = llvm::vfs::getRealFileSystem(); @@ -1103,6 +1105,9 @@ BitcodeEmbed = static_cast(Model); } + setNumberOfParallelJobs( + getLastArgIntValue(Args, options::OPT_parallel_jobs_EQ, 1, Diags)); + std::unique_ptr UArgs = std::make_unique(std::move(Args)); --- a/clang/lib/Driver/Job.cpp +++ b/clang/lib/Driver/Job.cpp @@ -44,9 +44,11 @@ for (const auto &II : Inputs) if (II.isFilename()) InputInfoList.push_back(II); - for (const auto &II : Outputs) + for (const auto &II : Outputs) { if (II.isFilename()) OutputFilenames.push_back(II.getFilename()); + DependentActions.push_back(II.getAction()); + } } /// Check if the compiler flag in question should be skipped when --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -8026,7 +8026,7 @@ C.addCommand(std::make_unique( JA, *this, ResponseFileSupport::None(), TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())), - CmdArgs, None, Output)); + CmdArgs, Inputs, Output)); } void OffloadBundler::ConstructJobMultipleOutputs( @@ -8110,7 +8110,7 @@ C.addCommand(std::make_unique( JA, *this, ResponseFileSupport::None(), TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())), - CmdArgs, None, Outputs)); + CmdArgs, Inputs, Outputs)); } void OffloadWrapper::ConstructJob(Compilation &C, const JobAction &JA, # cat 01-D118949.patch From d4e4ef2e81e03246e29e9b6eaa2929ebd4e77784 Mon Sep 17 00:00:00 2001 From: "Yaxun (Sam) Liu" Date: Thu, 3 Feb 2022 14:07:45 -0500 Subject: [PATCH] [HIP] Support code object v5 New device library supporting v4 and v5 has abi_version_400.bc and abi version_500.bc. For v5, abi_version_500.bc is linked. For v2-4, abi_version_400.bc is linked. For old device library, for v2-4, none of the above is linked. For v5, error is emitted about unsupported ABI version. Reviewed by: Artem Belevich Differential Revision: https://reviews.llvm.org/D118949 Fixes: SWDEV-321313 --- .../clang/Basic/DiagnosticDriverKinds.td | 2 +- clang/include/clang/Driver/Options.td | 4 +- clang/lib/Driver/ToolChains/AMDGPU.cpp | 57 +++++++++++++------ clang/lib/Driver/ToolChains/AMDGPU.h | 3 +- clang/lib/Driver/ToolChains/CommonArgs.cpp | 2 +- clang/lib/Driver/ToolChains/ROCm.h | 38 ++++++++++++- .../rocm/amdgcn/bitcode-no-abi-ver/asanrtl.bc | 0 .../rocm/amdgcn/bitcode-no-abi-ver/hip.bc | 0 .../rocm/amdgcn/bitcode-no-abi-ver/ockl.bc | 0 .../oclc_correctly_rounded_sqrt_off.bc | 0 .../oclc_correctly_rounded_sqrt_on.bc | 0 .../bitcode-no-abi-ver/oclc_daz_opt_off.bc | 0 .../bitcode-no-abi-ver/oclc_daz_opt_on.bc | 0 .../oclc_finite_only_off.bc | 0 .../bitcode-no-abi-ver/oclc_finite_only_on.bc | 0 .../oclc_isa_version_1010.bc | 0 .../oclc_isa_version_1011.bc | 0 .../oclc_isa_version_1012.bc | 0 .../oclc_isa_version_803.bc | 0 .../oclc_isa_version_900.bc | 0 .../oclc_isa_version_908.bc | 0 .../oclc_unsafe_math_off.bc | 0 .../bitcode-no-abi-ver/oclc_unsafe_math_on.bc | 0 .../oclc_wavefrontsize64_off.bc | 0 .../oclc_wavefrontsize64_on.bc | 0 .../rocm/amdgcn/bitcode-no-abi-ver/ocml.bc | 0 .../rocm/amdgcn/bitcode-no-abi-ver/opencl.bc | 0 .../rocm/amdgcn/bitcode/abi_version_400.bc | 0 .../rocm/amdgcn/bitcode/abi_version_500.bc | 0 clang/test/Driver/hip-code-object-version.hip | 10 ++++ clang/test/Driver/hip-device-libs.hip | 52 +++++++++++++++++ 31 files changed, 146 insertions(+), 22 deletions(-) create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/asanrtl.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/hip.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/ockl.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_correctly_rounded_sqrt_off.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_correctly_rounded_sqrt_on.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_daz_opt_off.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_daz_opt_on.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_finite_only_off.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_finite_only_on.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_1010.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_1011.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_1012.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_803.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_900.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_isa_version_908.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_unsafe_math_off.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_unsafe_math_on.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_wavefrontsize64_off.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/oclc_wavefrontsize64_on.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/ocml.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode-no-abi-ver/opencl.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode/abi_version_400.bc create mode 100644 clang/test/Driver/Inputs/rocm/amdgcn/bitcode/abi_version_500.bc diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 3efedbe0f6428..51a10ab54953c 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -67,7 +67,7 @@ def err_drv_no_cuda_libdevice : Error< "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 index 5aa1e851c2585..c57d9cde094de 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3440,8 +3440,8 @@ defm amdgpu_ieee : BoolOption<"m", "amdgpu-ieee", 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.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp index 43ce33750ebac..7d2b9e3b46c2f 100644 --- a/clang/lib/Driver/ToolChains/AMDGPU.cpp +++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp @@ -91,6 +91,7 @@ void RocmInstallationDetector::scanLibDevicePath(llvm::StringRef Path) { 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 @@ void RocmInstallationDetector::scanLibDevicePath(llvm::StringRef Path) { 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 @@ void ROCMToolChain::addClangTargetOptions( 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 @@ void ROCMToolChain::addClangTargetOptions( // 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 @@ void ROCMToolChain::addClangTargetOptions( }); } +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 @@ RocmInstallationDetector::getCommonBitcodeLibs( AddBCLib(getCorrectlyRoundedSqrtPath(CorrectSqrt)); AddBCLib(getWavefrontSize64Path(Wave64)); AddBCLib(LibDeviceFile); + auto ABIVerPath = getABIVersionPath(ABIVer); + if (!ABIVerPath.empty()) + AddBCLib(ABIVerPath); return BCLibs; } @@ -897,15 +920,17 @@ bool AMDGPUToolChain::shouldSkipArgument(const llvm::opt::Arg *A) const { 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 @@ ROCMToolChain::getCommonDeviceLibNames(const llvm::opt::ArgList &DriverArgs, return RocmInstallation.getCommonBitcodeLibs( DriverArgs, LibDeviceFile, Wave64, DAZ, FiniteOnly, UnsafeMathOpt, - FastRelaxedMath, CorrectSqrt); + FastRelaxedMath, CorrectSqrt, ABIVer, isOpenMP); } diff --git a/clang/lib/Driver/ToolChains/AMDGPU.h b/clang/lib/Driver/ToolChains/AMDGPU.h index 156bfd1fbdb2a..ddcc124b25bac 100644 --- a/clang/lib/Driver/ToolChains/AMDGPU.h +++ b/clang/lib/Driver/ToolChains/AMDGPU.h @@ -142,7 +142,8 @@ class LLVM_LIBRARY_VISIBILITY ROCMToolChain : public AMDGPUToolChain { // 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/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index aa6e852efd503..a6a4997f71297 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1910,7 +1910,7 @@ getAMDGPUCodeObjectArgument(const Driver &D, const llvm::opt::ArgList &Args) { 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 index bb482be68260d..33baaa887043e 100644 --- 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 @@ class RocmInstallationDetector { 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 @@ class RocmInstallationDetector { 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 @@ class RocmInstallationDetector { 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d 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 index 0000000000000..e69de29bb2d1d diff --git a/clang/test/Driver/hip-code-object-version.hip b/clang/test/Driver/hip-code-object-version.hip index 34cb4f2cfd631..61a54ebfc12ef 100644 --- 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 index 1f95fc2e3c353..59e4226ad84aa 100644 --- 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 # cat 02-D119939.patch diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp --- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -6176,7 +6176,7 @@ // The register may be specified by name or using a numeric code HwReg.Loc = getLoc(); if (isToken(AsmToken::Identifier) && - (HwReg.Id = getHwregId(getTokenStr())) >= 0) { + (HwReg.Id = getHwregId(getTokenStr(), getSTI())) >= 0) { HwReg.IsSymbolic = true; lex(); // skip register name } else if (!parseExpr(HwReg.Id, "a register name")) { diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h @@ -601,7 +601,7 @@ namespace Hwreg { LLVM_READONLY -int64_t getHwregId(const StringRef Name); +int64_t getHwregId(const StringRef Name, const MCSubtargetInfo &STI); LLVM_READNONE bool isValidHwreg(int64_t Id, const MCSubtargetInfo &STI); diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp @@ -1026,7 +1026,9 @@ namespace Hwreg { -int64_t getHwregId(const StringRef Name) { +int64_t getHwregId(const StringRef Name, const MCSubtargetInfo &STI) { + if (isGFX10(STI) && Name == "HW_REG_HW_ID") // An alias + return ID_HW_ID1; for (int Id = ID_SYMBOLIC_FIRST_; Id < ID_SYMBOLIC_LAST_; ++Id) { if (IdSymbolic[Id] && Name == IdSymbolic[Id]) return Id; diff --git a/llvm/test/MC/AMDGPU/sopk.s b/llvm/test/MC/AMDGPU/sopk.s --- a/llvm/test/MC/AMDGPU/sopk.s +++ b/llvm/test/MC/AMDGPU/sopk.s @@ -230,7 +230,7 @@ s_setreg_b32 hwreg(HW_REG_HW_ID), s2 // SICI: s_setreg_b32 hwreg(HW_REG_HW_ID), s2 ; encoding: [0x04,0xf8,0x82,0xb9] // VI9: s_setreg_b32 hwreg(HW_REG_HW_ID), s2 ; encoding: [0x04,0xf8,0x02,0xb9] -// NOGFX10: error: specified hardware register is not supported on this GPU +// GFX10: s_setreg_b32 hwreg(HW_REG_HW_ID1), s2 ; encoding: [0x17,0xf8,0x82,0xb9] s_setreg_b32 hwreg(HW_REG_HW_ID1), s2 // NOSICIVI: error: specified hardware register is not supported on this GPU # cat 03-D120557.patch From 092f15ac40ce35d077e0225a4462bc4dfa379391 Mon Sep 17 00:00:00 2001 From: "Yaxun (Sam) Liu" Date: Fri, 25 Feb 2022 00:03:36 -0500 Subject: [PATCH] [HIP] File device library ABI version file name It should be oclc_abi_version* instead of abi_version*. Reviewed by: Artem Belevich Differential Revision: https://reviews.llvm.org/D120557 --- clang/lib/Driver/ToolChains/AMDGPU.cpp | 2 +- .../{abi_version_400.bc => oclc_abi_version_400.bc} | 0 .../{abi_version_500.bc => oclc_abi_version_500.bc} | 0 clang/test/Driver/hip-device-libs.hip | 8 ++++---- 4 files changed, 5 insertions(+), 5 deletions(-) rename clang/test/Driver/Inputs/rocm/amdgcn/bitcode/{abi_version_400.bc => oclc_abi_version_400.bc} (100%) rename clang/test/Driver/Inputs/rocm/amdgcn/bitcode/{abi_version_500.bc => oclc_abi_version_500.bc} (100%) diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp index 7d2b9e3b46c2f..596fe5b2a2029 100644 --- a/clang/lib/Driver/ToolChains/AMDGPU.cpp +++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp @@ -91,7 +91,7 @@ void RocmInstallationDetector::scanLibDevicePath(llvm::StringRef Path) { else if (FileName.endswith(Suffix)) BaseName = FileName.drop_back(Suffix.size()); - const StringRef ABIVersionPrefix = "abi_version_"; + const StringRef ABIVersionPrefix = "oclc_abi_version_"; if (BaseName == "ocml") { OCML = FilePath; } else if (BaseName == "ockl") { diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode/abi_version_400.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_abi_version_400.bc similarity index 100% rename from clang/test/Driver/Inputs/rocm/amdgcn/bitcode/abi_version_400.bc rename to clang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_abi_version_400.bc diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode/abi_version_500.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_abi_version_500.bc similarity index 100% rename from clang/test/Driver/Inputs/rocm/amdgcn/bitcode/abi_version_500.bc rename to clang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_abi_version_500.bc diff --git a/clang/test/Driver/hip-device-libs.hip b/clang/test/Driver/hip-device-libs.hip index 59e4226ad84aa..29077ee1ecf25 100644 --- a/clang/test/Driver/hip-device-libs.hip +++ b/clang/test/Driver/hip-device-libs.hip @@ -217,10 +217,10 @@ // DIVSQRT-SAME: "-mlink-builtin-bitcode" "{{.*}}oclc_correctly_rounded_sqrt_off.bc" // ABI4-NOT: error: -// ABI4: "-mlink-builtin-bitcode" "{{.*}}abi_version_400.bc" +// ABI4: "-mlink-builtin-bitcode" "{{.*}}oclc_abi_version_400.bc" // ABI5-NOT: error: -// ABI5: "-mlink-builtin-bitcode" "{{.*}}abi_version_500.bc" +// ABI5: "-mlink-builtin-bitcode" "{{.*}}oclc_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" +// NOABI4-NOT: "-mlink-builtin-bitcode" "{{.*}}oclc_abi_version_400.bc" +// NOABI4-NOT: "-mlink-builtin-bitcode" "{{.*}}oclc_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 # cat 04-clang-declbase.patch --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -146,7 +146,9 @@ // are invalid too. if (auto *DD = dyn_cast(this)) { for (auto *Binding : DD->bindings()) { - Binding->setInvalidDecl(); + if (Binding) { + Binding->setInvalidDecl(); + } } } }