https://github.com/jhuber6 updated https://github.com/llvm/llvm-project/pull/201155
>From 315551340fd71979068d4339c6923f515fa6f2d6 Mon Sep 17 00:00:00 2001 From: Joseph Huber <[email protected]> Date: Tue, 2 Jun 2026 11:15:24 -0500 Subject: [PATCH 1/3] [Clang] Rework LTO mode selection to be a Toolchain property Summary: Currently, the LTO mode is a property of the Driver, which makes sense because it is used to set up phases. However, we currently have `-flto` and `-foffload-lto`, which is a split that doesn't fully work with the full context of a heterogenous compilation as it is 'all-or-nothing'. This PR seeks to be mostly NFC for now, just moving the queries to a per-toolchain interface rather than the static driver mode setting we have right now. The *single* use of this before ToolChains are created is for the Webassembly toolchain to set an include path. This is now just a direct check on the flag, which is consistent. In the future they could shift to fat LTO objects as well. The main goal for the PR is to allow the GPU / Offloading toolchains to specify their "real" LTO behavior. Right now SPIR-V and AMDGCN both default to LTO, but rather than re-use the LTO handling we hack through the driver phases to override it. Allowing this split would let us heavily simplify this logic. Co-authored-by: Cursor <[email protected]> --- clang/include/clang/Driver/Driver.h | 32 +---- clang/include/clang/Driver/ToolChain.h | 12 ++ clang/lib/Driver/Driver.cpp | 118 +++++++------------ clang/lib/Driver/SanitizerArgs.cpp | 2 +- clang/lib/Driver/ToolChain.cpp | 52 ++++++++ clang/lib/Driver/ToolChains/AIX.cpp | 5 +- clang/lib/Driver/ToolChains/AMDGPU.cpp | 6 +- clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp | 2 +- clang/lib/Driver/ToolChains/AVR.cpp | 5 +- clang/lib/Driver/ToolChains/BareMetal.cpp | 5 +- clang/lib/Driver/ToolChains/Clang.cpp | 24 ++-- clang/lib/Driver/ToolChains/Cuda.cpp | 8 +- clang/lib/Driver/ToolChains/Darwin.cpp | 7 +- clang/lib/Driver/ToolChains/Flang.cpp | 3 +- clang/lib/Driver/ToolChains/FreeBSD.cpp | 5 +- clang/lib/Driver/ToolChains/Fuchsia.cpp | 5 +- clang/lib/Driver/ToolChains/Gnu.cpp | 5 +- clang/lib/Driver/ToolChains/HIPAMD.cpp | 2 +- clang/lib/Driver/ToolChains/Haiku.cpp | 5 +- clang/lib/Driver/ToolChains/Hexagon.cpp | 10 +- clang/lib/Driver/ToolChains/MSVC.cpp | 4 +- clang/lib/Driver/ToolChains/MinGW.cpp | 5 +- clang/lib/Driver/ToolChains/OpenBSD.cpp | 5 +- clang/lib/Driver/ToolChains/PS4CPU.cpp | 8 +- clang/lib/Driver/ToolChains/SPIRV.cpp | 4 +- clang/lib/Driver/ToolChains/Serenity.cpp | 5 +- clang/lib/Driver/ToolChains/WebAssembly.cpp | 12 +- 27 files changed, 176 insertions(+), 180 deletions(-) diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h index 5490e06b6f3f3..7281e04ac323e 100644 --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -55,12 +55,7 @@ class JobAction; class ToolChain; /// Describes the kind of LTO mode selected via -f(no-)?lto(=.*)? options. -enum LTOKind { - LTOK_None, - LTOK_Full, - LTOK_Thin, - LTOK_Unknown -}; +enum LTOKind : int { LTOK_None, LTOK_Full, LTOK_Thin, LTOK_Unknown }; /// Whether headers used to construct C++20 module units should be looked /// up by the path supplied on the command line, or in the user or system @@ -135,12 +130,6 @@ class Driver { /// interpretation. bool ModulesModeCXX20; - /// LTO mode selected via -f(no-)?lto(=.*)? options. - LTOKind LTOMode; - - /// LTO mode selected via -f(no-offload-)?lto(=.*)? options. - LTOKind OffloadLTOMode; - /// Options for CUID CUIDOptions CUIDOpts; @@ -664,7 +653,8 @@ class Driver { Action *ConstructPhaseAction( Compilation &C, const llvm::opt::ArgList &Args, phases::ID Phase, Action *Input, - Action::OffloadKind TargetDeviceOffloadKind = Action::OFK_None) const; + Action::OffloadKind TargetDeviceOffloadKind = Action::OFK_None, + LTOKind TargetLTOMode = LTOK_None) const; /// BuildJobsForAction - Construct the jobs to perform for the action \p A and /// return an InputInfo for the result of running \p A. Will only construct @@ -740,18 +730,6 @@ class Driver { /// Get the mode for handling headers as set by fmodule-header{=}. ModuleHeaderMode getModuleHeaderMode() const { return CXX20HeaderType; } - /// Returns true if we are performing any kind of LTO. - bool isUsingLTO() const { return getLTOMode() != LTOK_None; } - - /// Get the specific kind of LTO being performed. - LTOKind getLTOMode() const { return LTOMode; } - - /// Returns true if we are performing any kind of offload LTO. - bool isUsingOffloadLTO() const { return getOffloadLTOMode() != LTOK_None; } - - /// Get the specific kind of offload LTO being performed. - LTOKind getOffloadLTOMode() const { return OffloadLTOMode; } - /// Get the CUID option. const CUIDOptions &getCUIDOpts() const { return CUIDOpts; } @@ -784,10 +762,6 @@ class Driver { /// option. void setDriverMode(StringRef DriverModeValue); - /// Parse the \p Args list for LTO options and record the type of LTO - /// compilation based on which -f(no-)?lto(=.*)? option occurs last. - void setLTOMode(const llvm::opt::ArgList &Args); - /// Retrieves a ToolChain for a particular \p Target triple. /// /// Will cache ToolChains for the life of the driver object, and create them diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h index 684ef52d8532b..d700457c68591 100644 --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -61,6 +61,8 @@ class SanitizerArgs; class Tool; class XRayArgs; +enum LTOKind : int; + /// Helper structure used to pass information extracted from clang executable /// name such as `i686-linux-android-g++`. struct ParsedClangName { @@ -462,6 +464,16 @@ class ToolChain { /// native LLVM support. virtual bool HasNativeLLVMSupport() const; + /// Returns the default LTO mode for this toolchain. + virtual LTOKind getDefaultLTOMode() const; + + /// Resolve the requested LTO mode for this toolchain. + LTOKind getLTOMode(const llvm::opt::ArgList &Args, + bool IsOffload = false) const; + + /// Returns true if LTO is active for this toolchain given the args. + bool isUsingLTO(const llvm::opt::ArgList &Args, bool IsOffload = false) const; + /// LookupTypeForExtension - Return the default language type to use for the /// given extension. virtual types::ID LookupTypeForExtension(StringRef Ext) const; diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 82e8977648b92..636a39b3690e7 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -181,10 +181,9 @@ Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple, : Diags(Diags), VFS(std::move(VFS)), Mode(GCCMode), SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), Offload(OffloadHostDevice), CXX20HeaderType(HeaderMode_None), - ModulesModeCXX20(false), LTOMode(LTOK_None), - ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT), - DriverTitle(Title), CCCPrintBindings(false), CCPrintOptions(false), - CCLogDiagnostics(false), CCGenDiagnostics(false), + ModulesModeCXX20(false), ClangExecutable(ClangExecutable), + SysRoot(DEFAULT_SYSROOT), DriverTitle(Title), CCCPrintBindings(false), + CCPrintOptions(false), CCLogDiagnostics(false), CCGenDiagnostics(false), CCPrintProcessStats(false), CCPrintInternalStats(false), TargetTriple(TargetTriple), Saver(Alloc), PrependArg(nullptr), PreferredLinker(CLANG_DEFAULT_LINKER), CheckInputsExist(true), @@ -840,50 +839,6 @@ static llvm::Triple computeTargetTriple(const Driver &D, return Target; } -// Parse the LTO options and record the type of LTO compilation -// based on which -f(no-)?lto(=.*)? or -f(no-)?offload-lto(=.*)? -// option occurs last. -static driver::LTOKind parseLTOMode(Driver &D, const llvm::opt::ArgList &Args, - OptSpecifier OptEq, OptSpecifier OptNeg) { - if (!Args.hasFlag(OptEq, OptNeg, false)) - return LTOK_None; - - const Arg *A = Args.getLastArg(OptEq); - StringRef LTOName = A->getValue(); - - driver::LTOKind LTOMode = llvm::StringSwitch<LTOKind>(LTOName) - .Case("full", LTOK_Full) - .Case("thin", LTOK_Thin) - .Default(LTOK_Unknown); - - if (LTOMode == LTOK_Unknown) { - D.Diag(diag::err_drv_unsupported_option_argument) - << A->getSpelling() << A->getValue(); - return LTOK_None; - } - return LTOMode; -} - -// Parse the LTO options. -void Driver::setLTOMode(const llvm::opt::ArgList &Args) { - LTOMode = - parseLTOMode(*this, Args, options::OPT_flto_EQ, options::OPT_fno_lto); - - OffloadLTOMode = parseLTOMode(*this, Args, options::OPT_foffload_lto_EQ, - options::OPT_fno_offload_lto); - - // Try to enable `-foffload-lto=full` if `-fopenmp-target-jit` is on. - if (Args.hasFlag(options::OPT_fopenmp_target_jit, - options::OPT_fno_openmp_target_jit, false)) { - if (Arg *A = Args.getLastArg(options::OPT_foffload_lto_EQ, - options::OPT_fno_offload_lto)) - if (OffloadLTOMode != LTOK_Full) - Diag(diag::err_drv_incompatible_options) - << A->getSpelling() << "-fopenmp-target-jit"; - OffloadLTOMode = LTOK_Full; - } -} - /// Compute the desired OpenMP runtime from the flags provided. Driver::OpenMPRuntimeKind Driver::getOpenMPRuntime(const ArgList &Args) const { StringRef RuntimeName(CLANG_DEFAULT_OPENMP_RUNTIME); @@ -1677,8 +1632,6 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { Offload = OffloadHostDevice; } - setLTOMode(Args); - // Process -fembed-bitcode= flags. if (Arg *A = Args.getLastArg(options::OPT_fembed_bitcode_EQ)) { StringRef Name = A->getValue(); @@ -3648,7 +3601,9 @@ class OffloadingActionBuilder final { break; CudaDeviceActions[I] = C.getDriver().ConstructPhaseAction( - C, Args, Ph, CudaDeviceActions[I], Action::OFK_Cuda); + C, Args, Ph, CudaDeviceActions[I], Action::OFK_Cuda, + ToolChains[I]->getLTOMode(Args, + /*IsOffload=*/true)); if (Ph == phases::Assemble) break; @@ -3799,7 +3754,8 @@ class OffloadingActionBuilder final { // a fat binary containing all the code objects for different GPU's. // The fat binary is then an input to the host action. for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) { - if (C.getDriver().isUsingOffloadLTO()) { + if (ToolChains[I]->isUsingLTO(Args, + /*IsOffload=*/true)) { // When LTO is enabled, skip the backend and assemble phases and // use lld to link the bitcode. ActionList AL; @@ -3824,10 +3780,12 @@ class OffloadingActionBuilder final { : types::TY_LLVM_BC; BackendAction = C.MakeAction<BackendJobAction>(CudaDeviceActions[I], Output); - } else + } else { + auto DevLTO = ToolChains[I]->getLTOMode(Args, /*IsOffload=*/true); BackendAction = C.getDriver().ConstructPhaseAction( C, Args, phases::Backend, CudaDeviceActions[I], - AssociatedOffloadKind); + AssociatedOffloadKind, DevLTO); + } auto AssembleAction = C.getDriver().ConstructPhaseAction( C, Args, phases::Assemble, BackendAction, AssociatedOffloadKind); @@ -3892,9 +3850,11 @@ class OffloadingActionBuilder final { } // By default, we produce an action for each device arch. - for (Action *&A : CudaDeviceActions) - A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A, - AssociatedOffloadKind); + for (unsigned I = 0, E = CudaDeviceActions.size(); I != E; ++I) + CudaDeviceActions[I] = C.getDriver().ConstructPhaseAction( + C, Args, CurPhase, CudaDeviceActions[I], AssociatedOffloadKind, + ToolChains[I]->getLTOMode(Args, + /*IsOffload=*/true)); if (CompileDeviceOnly && CurPhase == FinalPhase && BundleOutput && *BundleOutput) { @@ -4352,7 +4312,7 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args, !C.getDefaultToolChain().getTriple().isSPIRV()) Diag(clang::diag::err_drv_emit_llvm_link); if (C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment() && - LTOMode != LTOK_None && + C.getDefaultToolChain().isUsingLTO(Args) && !Args.getLastArgValue(options::OPT_fuse_ld_EQ) .starts_with_insensitive("lld")) Diag(clang::diag::err_drv_lto_without_lld); @@ -4445,8 +4405,10 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args, const types::ID HeaderType = lookupHeaderTypeForSourceType(InputType); // Build the pipeline for the pch file. Action *ClangClPch = C.MakeAction<InputAction>(*InputArg, HeaderType); + auto HostLTO = C.getDefaultToolChain().getLTOMode(Args); for (phases::ID Phase : types::getCompilationPhases(HeaderType)) - ClangClPch = ConstructPhaseAction(C, Args, Phase, ClangClPch); + ClangClPch = ConstructPhaseAction(C, Args, Phase, ClangClPch, + Action::OFK_None, HostLTO); assert(ClangClPch); Actions.push_back(ClangClPch); // The driver currently exits after the first failed command. This @@ -4586,7 +4548,9 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, // later actions in the same command line? // Otherwise construct the appropriate action. - Action *NewCurrent = ConstructPhaseAction(C, Args, Phase, Current); + Action *NewCurrent = + ConstructPhaseAction(C, Args, Phase, Current, Action::OFK_None, + C.getDefaultToolChain().getLTOMode(Args)); // We didn't create a new action, so we will just move to the next phase. if (NewCurrent == Current) @@ -5073,7 +5037,10 @@ Driver::BuildOffloadingActions(Compilation &C, llvm::opt::DerivedArgList &Args, // Propagate the ToolChain so we can use it in ConstructPhaseAction. A->propagateDeviceOffloadInfo(Kind, TCAndArch->second.data(), TCAndArch->first); - A = ConstructPhaseAction(C, Args, Phase, A, Kind); + A = ConstructPhaseAction( + C, Args, Phase, A, Kind, + TCAndArch->first->getLTOMode(Args, + /*IsOffload=*/true)); if (isa<CompileJobAction>(A) && isa<CompileJobAction>(HostAction) && Kind == Action::OFK_OpenMP && @@ -5226,7 +5193,7 @@ Driver::BuildOffloadingActions(Compilation &C, llvm::opt::DerivedArgList &Args, Action *Driver::ConstructPhaseAction( Compilation &C, const ArgList &Args, phases::ID Phase, Action *Input, - Action::OffloadKind TargetDeviceOffloadKind) const { + Action::OffloadKind TargetDeviceOffloadKind, LTOKind TargetLTOMode) const { llvm::PrettyStackTraceString CrashInfo("Constructing phase actions"); // Some types skip the assembler phase (e.g., llvm-bc), but we can't @@ -5350,18 +5317,19 @@ Action *Driver::ConstructPhaseAction( !(Args.hasArg(options::OPT_S) && !Args.hasArg(options::OPT_emit_llvm))) return Input; - if (isUsingLTO() && TargetDeviceOffloadKind == Action::OFK_None) { - types::ID Output; - if (Args.hasArg(options::OPT_ffat_lto_objects) && - !Args.hasArg(options::OPT_emit_llvm)) - Output = types::TY_PP_Asm; - else if (Args.hasArg(options::OPT_S)) - Output = types::TY_LTO_IR; - else - Output = types::TY_LTO_BC; - return C.MakeAction<BackendJobAction>(Input, Output); - } - if (isUsingOffloadLTO() && TargetDeviceOffloadKind != Action::OFK_None) { + if (TargetLTOMode != LTOK_None) { + bool IsDeviceOffload = TargetDeviceOffloadKind != Action::OFK_None; + if (!IsDeviceOffload) { + types::ID Output; + if (Args.hasArg(options::OPT_ffat_lto_objects) && + !Args.hasArg(options::OPT_emit_llvm)) + Output = types::TY_PP_Asm; + else if (Args.hasArg(options::OPT_S)) + Output = types::TY_LTO_IR; + else + Output = types::TY_LTO_BC; + return C.MakeAction<BackendJobAction>(Input, Output); + } types::ID Output = Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC; return C.MakeAction<BackendJobAction>(Input, Output); @@ -6203,7 +6171,7 @@ InputInfoList Driver::BuildJobsForActionNoCache( ActionList CollapsedOffloadActions; ToolSelector TS(JA, *TC, C, isSaveTempsEnabled(), - embedBitcodeInObject() && !isUsingLTO()); + embedBitcodeInObject() && !TC->isUsingLTO(C.getArgs())); const Tool *T = TS.getTool(Inputs, CollapsedOffloadActions); if (!T) diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 31660dd29407c..74ebd0bf375d3 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -771,7 +771,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, } // Check that LTO is enabled if we need it. - if ((Kinds & NeedsLTO) && !D.isUsingLTO() && DiagnoseErrors) { + if ((Kinds & NeedsLTO) && !TC.isUsingLTO(Args) && DiagnoseErrors) { D.Diag(diag::err_drv_argument_only_allowed_with) << lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto"; } diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 511eb3757456b..dd73c889570b9 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -1328,6 +1328,58 @@ bool ToolChain::HasNativeLLVMSupport() const { return false; } +LTOKind ToolChain::getDefaultLTOMode() const { return LTOK_None; } + +bool ToolChain::isUsingLTO(const llvm::opt::ArgList &Args, + bool IsOffload) const { + return getLTOMode(Args, IsOffload) != LTOK_None; +} + +static LTOKind parseLTOMode(const llvm::opt::ArgList &Args, + llvm::opt::OptSpecifier OptEq, + llvm::opt::OptSpecifier OptNeg) { + if (!Args.hasFlag(OptEq, OptNeg, false)) + return LTOK_None; + + const Arg *A = Args.getLastArg(OptEq); + StringRef LTOName = A->getValue(); + + return llvm::StringSwitch<LTOKind>(LTOName) + .Case("full", LTOK_Full) + .Case("thin", LTOK_Thin) + .Default(LTOK_Unknown); +} + +LTOKind ToolChain::getLTOMode(const llvm::opt::ArgList &Args, + bool IsOffload) const { + auto OptEq = IsOffload ? options::OPT_foffload_lto_EQ : options::OPT_flto_EQ; + auto OptNeg = IsOffload ? options::OPT_fno_offload_lto : options::OPT_fno_lto; + + // -fopenmp-target-jit implies -foffload-lto=full for device compilations, + // overriding any explicit -fno-offload-lto. + if (IsOffload && Args.hasFlag(options::OPT_fopenmp_target_jit, + options::OPT_fno_openmp_target_jit, false)) { + if (Arg *A = Args.getLastArg(OptEq, OptNeg)) + if (parseLTOMode(Args, OptEq, OptNeg) != LTOK_Full) + getDriver().Diag(diag::err_drv_incompatible_options) + << A->getSpelling() << "-fopenmp-target-jit"; + return LTOK_Full; + } + + if (!Args.hasArg(OptEq, OptNeg)) + return getDefaultLTOMode(); + + LTOKind Mode = parseLTOMode(Args, OptEq, OptNeg); + + if (Mode == LTOK_Unknown) { + const Arg *A = Args.getLastArg(OptEq); + getDriver().Diag(diag::err_drv_unsupported_option_argument) + << A->getSpelling() << A->getValue(); + return LTOK_None; + } + return Mode; +} + bool ToolChain::isCrossCompiling() const { llvm::Triple HostTriple(LLVM_HOST_TRIPLE); switch (HostTriple.getArch()) { diff --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp index 01b2c8ec18a35..b783e8596a872 100644 --- a/clang/lib/Driver/ToolChains/AIX.cpp +++ b/clang/lib/Driver/ToolChains/AIX.cpp @@ -243,9 +243,8 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA, // Specify linker input file(s). AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); - if (D.isUsingLTO()) - addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs, - D.getLTOMode() == LTOK_Thin); + if (auto LTO = ToolChain.getLTOMode(Args); LTO != LTOK_None) + addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs, LTO == LTOK_Thin); if (Args.hasArg(options::OPT_shared) && !hasExportListLinkerOpts(CmdArgs)) { diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp index 55c94823376b0..db671e9e59ca2 100644 --- a/clang/lib/Driver/ToolChains/AMDGPU.cpp +++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp @@ -609,9 +609,9 @@ void amdgpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-shared"); } - if (C.getDriver().isUsingLTO()) { - const bool ThinLTO = (C.getDriver().getLTOMode() == LTOK_Thin); - addLTOOptions(getToolChain(), Args, CmdArgs, Output, Inputs, ThinLTO); + if (auto LTO = getToolChain().getLTOMode(Args); LTO != LTOK_None) { + addLTOOptions(getToolChain(), Args, CmdArgs, Output, Inputs, + LTO == LTOK_Thin); } else if (Args.hasArg(options::OPT_mcpu_EQ)) { CmdArgs.push_back(Args.MakeArgString( "-plugin-opt=mcpu=" + diff --git a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp index aecec6c4c419b..a03ac8227a8c3 100644 --- a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp +++ b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp @@ -49,7 +49,7 @@ void AMDGPUOpenMPToolChain::addClangTargetOptions( } // Link the bitcode library late if we're using device LTO. - if (getDriver().isUsingOffloadLTO()) + if (isUsingLTO(DriverArgs, /*IsOffload=*/true)) return; } diff --git a/clang/lib/Driver/ToolChains/AVR.cpp b/clang/lib/Driver/ToolChains/AVR.cpp index 588255dc5a0cd..16bfa84d86dcf 100644 --- a/clang/lib/Driver/ToolChains/AVR.cpp +++ b/clang/lib/Driver/ToolChains/AVR.cpp @@ -587,9 +587,8 @@ void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA, } } - if (D.isUsingLTO()) - addLTOOptions(TC, Args, CmdArgs, Output, Inputs, - D.getLTOMode() == LTOK_Thin); + if (auto LTO = TC.getLTOMode(Args); LTO != LTOK_None) + addLTOOptions(TC, Args, CmdArgs, Output, Inputs, LTO == LTOK_Thin); // If the family name is known, we can link with the device-specific libgcc. // Without it, libgcc will simply not be linked. This matches avr-gcc diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp index 4293295f20541..1bd34f7777226 100644 --- a/clang/lib/Driver/ToolChains/BareMetal.cpp +++ b/clang/lib/Driver/ToolChains/BareMetal.cpp @@ -600,9 +600,8 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA, for (const auto &LibPath : TC.getLibraryPaths()) CmdArgs.push_back(Args.MakeArgString(llvm::Twine("-L", LibPath))); - if (D.isUsingLTO()) - addLTOOptions(TC, Args, CmdArgs, Output, Inputs, - D.getLTOMode() == LTOK_Thin); + if (auto LTO = TC.getLTOMode(Args); LTO != LTOK_None) + addLTOOptions(TC, Args, CmdArgs, Output, Inputs, LTO == LTOK_Thin); AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); TC.addProfileRTLibs(Args, CmdArgs); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 7657afb14f077..57348dbeeb32c 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5028,7 +5028,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, bool IsRDCMode = Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false); - auto LTOMode = IsDeviceOffloadAction ? D.getOffloadLTOMode() : D.getLTOMode(); + auto LTOMode = TC.getLTOMode(Args, IsDeviceOffloadAction); bool IsUsingLTO = LTOMode != LTOK_None; // Extract API doesn't have a main input file, so invent a fake one as a @@ -5405,8 +5405,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Twine("-flto=") + (LTOMode == LTOK_Thin ? "thin" : "full"))); // PS4 uses the legacy LTO API, which does not support some of the // features enabled by -flto-unit. - if (!RawTriple.isPS4() || - (D.getLTOMode() == LTOK_Full) || !UnifiedLTO) + if (!RawTriple.isPS4() || (LTOMode == LTOK_Full) || !UnifiedLTO) CmdArgs.push_back("-flto-unit"); } } @@ -8239,12 +8238,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Check if we are using PS4 in regular LTO mode. // Otherwise, issue an error. - auto OtherLTOMode = - IsDeviceOffloadAction ? D.getLTOMode() : D.getOffloadLTOMode(); + auto OtherLTOMode = TC.getLTOMode(Args, !IsDeviceOffloadAction); auto OtherIsUsingLTO = OtherLTOMode != LTOK_None; if ((!IsUsingLTO && !OtherIsUsingLTO) || - (IsPS4 && !UnifiedLTO && (D.getLTOMode() != LTOK_Full))) + (IsPS4 && !UnifiedLTO && + (TC.getLTOMode(Args, /*IsOffload=*/false) != LTOK_Full))) D.Diag(diag::err_drv_argument_only_allowed_with) << "-fwhole-program-vtables" << ((IsPS4 && !UnifiedLTO) ? "-flto=full" : "-flto"); @@ -9508,7 +9507,7 @@ void OffloadPackager::ConstructJob(Compilation &C, const JobAction &JA, "kind=" + Kind.str(), }; - if (TC->getDriver().isUsingOffloadLTO()) + if (TC->isUsingLTO(TCArgs, /*IsOffload=*/true)) for (StringRef Feature : FeatureArgs) Parts.emplace_back("feature=" + Feature.str()); @@ -9682,8 +9681,8 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, // flags. SYCL uses clang-sycl-linker instead of spirv-link, so skip it. if (TC->getTriple().isSPIRV() && TC->getTriple().getVendor() != llvm::Triple::VendorType::AMD && - Kind != Action::OFK_SYCL && !C.getDriver().isUsingLTO() && - !C.getDriver().isUsingOffloadLTO()) { + Kind != Action::OFK_SYCL && + !TC->isUsingLTO(ToolChainArgs, /*IsOffload=*/true)) { // For SPIR-V some functions will be defined by the runtime so allow // unresolved symbols in `spirv-link`. LinkerArgs.emplace_back("--allow-partial-linkage"); @@ -9699,11 +9698,12 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString( "--device-linker=" + TC->getTripleString() + "=" + Arg)); - // Forward the LTO mode relying on the Driver's parsing. - if (C.getDriver().getOffloadLTOMode() == LTOK_Full) + // Forward the LTO mode for this toolchain. + auto DeviceLTOMode = TC->getLTOMode(ToolChainArgs, /*IsOffload=*/true); + if (DeviceLTOMode == LTOK_Full) CmdArgs.push_back(Args.MakeArgString( "--device-compiler=" + TC->getTripleString() + "=-flto=full")); - else if (C.getDriver().getOffloadLTOMode() == LTOK_Thin) { + else if (DeviceLTOMode == LTOK_Thin) { CmdArgs.push_back(Args.MakeArgString( "--device-compiler=" + TC->getTripleString() + "=-flto=thin")); if (TC->getTriple().isAMDGPU()) { diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp index cddd96a7e762d..a25f00e96b2f1 100644 --- a/clang/lib/Driver/ToolChains/Cuda.cpp +++ b/clang/lib/Driver/ToolChains/Cuda.cpp @@ -603,7 +603,7 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-v"); StringRef GPUArch = Args.getLastArgValue(options::OPT_march_EQ); - if (GPUArch.empty() && !C.getDriver().isUsingLTO()) { + if (GPUArch.empty() && !getToolChain().isUsingLTO(Args)) { C.getDriver().Diag(diag::err_drv_offload_missing_gpu_arch) << getToolChain().getArchName() << getShortName(); return; @@ -633,9 +633,9 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA, getToolChain().AddFilePathLibArgs(Args, CmdArgs); AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); - if (C.getDriver().isUsingLTO()) + if (auto LTO = getToolChain().getLTOMode(Args); LTO != LTOK_None) addLTOOptions(getToolChain(), Args, CmdArgs, Output, Inputs, - C.getDriver().getLTOMode() == LTOK_Thin); + LTO == LTOK_Thin); // Forward the PTX features if the nvlink-wrapper needs it. std::vector<StringRef> Features; @@ -939,7 +939,7 @@ void CudaToolChain::addClangTargetOptions( } // Link the bitcode library late if we're using device LTO. - if (getDriver().isUsingOffloadLTO()) + if (isUsingLTO(DriverArgs, /*IsOffload=*/true)) return; addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, GpuArch.str(), diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index 103bc4ec7613f..3219b2f1fec45 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -250,16 +250,17 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args, options::OPT_fno_application_extension, false)) CmdArgs.push_back("-application_extension"); - if (D.isUsingLTO() && (Version >= VersionTuple(116) || LinkerIsLLD) && + if (auto LTO = getToolChain().getLTOMode(Args); + LTO != LTOK_None && (Version >= VersionTuple(116) || LinkerIsLLD) && NeedsTempPath(Inputs)) { std::string TmpPathName; - if (D.getLTOMode() == LTOK_Full) { + if (LTO == LTOK_Full) { // If we are using full LTO, then automatically create a temporary file // path for the linker to use, so that it's lifetime will extend past a // possible dsymutil step. TmpPathName = D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object)); - } else if (D.getLTOMode() == LTOK_Thin) + } else if (LTO == LTOK_Thin) // If we are using thin LTO, then create a directory instead. TmpPathName = D.GetTemporaryDirectory("thinlto"); diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index 892a455167205..b479ced418725 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -268,8 +268,7 @@ void Flang::addCodegenOptions(const ArgList &Args, void Flang::addLTOOptions(const ArgList &Args, ArgStringList &CmdArgs) const { const ToolChain &TC = getToolChain(); - const Driver &D = TC.getDriver(); - LTOKind LTOMode = D.getLTOMode(); + LTOKind LTOMode = TC.getLTOMode(Args); // LTO mode is parsed by the Clang driver library. assert(LTOMode != LTOK_Unknown && "Unknown LTO mode."); if (LTOMode == LTOK_Full) diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp index e3189d02eca21..1218868ac3bda 100644 --- a/clang/lib/Driver/ToolChains/FreeBSD.cpp +++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp @@ -272,9 +272,8 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s, options::OPT_t}); - if (D.isUsingLTO()) - addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs, - D.getLTOMode() == LTOK_Thin); + if (auto LTO = ToolChain.getLTOMode(Args); LTO != LTOK_None) + addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs, LTO == LTOK_Thin); bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs); bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp index e534cb4a99b29..e037e29eb7796 100644 --- a/clang/lib/Driver/ToolChains/Fuchsia.cpp +++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp @@ -139,9 +139,8 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, ToolChain.AddFilePathLibArgs(Args, CmdArgs); - if (D.isUsingLTO()) - addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs, - D.getLTOMode() == LTOK_Thin); + if (auto LTO = ToolChain.getLTOMode(Args); LTO != LTOK_None) + addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs, LTO == LTOK_Thin); addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index 131dd725c7289..9aa0ec38a1191 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -438,9 +438,8 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, ToolChain.AddFilePathLibArgs(Args, CmdArgs); - if (D.isUsingLTO()) - addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs, - D.getLTOMode() == LTOK_Thin); + if (auto LTO = ToolChain.getLTOMode(Args); LTO != LTOK_None) + addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs, LTO == LTOK_Thin); if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) CmdArgs.push_back("--no-demangle"); diff --git a/clang/lib/Driver/ToolChains/HIPAMD.cpp b/clang/lib/Driver/ToolChains/HIPAMD.cpp index 98be4861276f8..ea2efedd6251b 100644 --- a/clang/lib/Driver/ToolChains/HIPAMD.cpp +++ b/clang/lib/Driver/ToolChains/HIPAMD.cpp @@ -70,7 +70,7 @@ void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA, auto &TC = getToolChain(); auto &D = TC.getDriver(); - bool IsThinLTO = D.getOffloadLTOMode() == LTOK_Thin; + bool IsThinLTO = TC.getLTOMode(Args, /*IsOffload=*/true) == LTOK_Thin; addLTOOptions(TC, Args, LldArgs, Output, Inputs, IsThinLTO); // Extract all the -m options diff --git a/clang/lib/Driver/ToolChains/Haiku.cpp b/clang/lib/Driver/ToolChains/Haiku.cpp index 6feb632f64bdb..083769f2c7954 100644 --- a/clang/lib/Driver/ToolChains/Haiku.cpp +++ b/clang/lib/Driver/ToolChains/Haiku.cpp @@ -87,9 +87,8 @@ void haiku::Linker::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_s, options::OPT_t}); ToolChain.AddFilePathLibArgs(Args, CmdArgs); - if (D.isUsingLTO()) - addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs, - D.getLTOMode() == LTOK_Thin); + if (auto LTO = ToolChain.getLTOMode(Args); LTO != LTOK_None) + addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs, LTO == LTOK_Thin); bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs); addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs); diff --git a/clang/lib/Driver/ToolChains/Hexagon.cpp b/clang/lib/Driver/ToolChains/Hexagon.cpp index ce3fd5110953a..0e7055797a1f0 100644 --- a/clang/lib/Driver/ToolChains/Hexagon.cpp +++ b/clang/lib/Driver/ToolChains/Hexagon.cpp @@ -358,9 +358,8 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA, options::OPT_t, options::OPT_u_Group}); AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA); - if (D.isUsingLTO()) - addLTOOptions(HTC, Args, CmdArgs, Output, Inputs, - D.getLTOMode() == LTOK_Thin); + if (auto LTO = HTC.getLTOMode(Args); LTO != LTOK_None) + addLTOOptions(HTC, Args, CmdArgs, Output, Inputs, LTO == LTOK_Thin); ToolChain::UnwindLibType UNW = HTC.GetUnwindLibType(Args); @@ -456,9 +455,8 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA, AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA); - if (D.isUsingLTO()) - addLTOOptions(HTC, Args, CmdArgs, Output, Inputs, - D.getLTOMode() == LTOK_Thin); + if (auto LTO = HTC.getLTOMode(Args); LTO != LTOK_None) + addLTOOptions(HTC, Args, CmdArgs, Output, Inputs, LTO == LTOK_Thin); //---------------------------------------------------------------------------- // Libraries diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp index f0cb01058e9c9..6bc58699fb007 100644 --- a/clang/lib/Driver/ToolChains/MSVC.cpp +++ b/clang/lib/Driver/ToolChains/MSVC.cpp @@ -282,7 +282,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, } } - if (C.getDriver().isUsingLTO()) { + if (TC.isUsingLTO(Args)) { if (Arg *A = tools::getLastProfileSampleUseArg(Args)) CmdArgs.push_back(Args.MakeArgString(std::string("-lto-sample-profile:") + A->getValue())); @@ -357,7 +357,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back( Args.MakeArgString(std::string("/vfsoverlay:") + A->getValue())); - if (C.getDriver().isUsingLTO() && + if (TC.isUsingLTO(Args) && Args.hasFlag(options::OPT_gsplit_dwarf, options::OPT_gno_split_dwarf, false)) CmdArgs.push_back(Args.MakeArgString(Twine("/dwodir:") + diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp index 78b15feee37ef..e3f8cb8292fc8 100644 --- a/clang/lib/Driver/ToolChains/MinGW.cpp +++ b/clang/lib/Driver/ToolChains/MinGW.cpp @@ -263,9 +263,8 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); - if (D.isUsingLTO()) - addLTOOptions(TC, Args, CmdArgs, Output, Inputs, - D.getLTOMode() == LTOK_Thin); + if (auto LTO = TC.getLTOMode(Args); LTO != LTOK_None) + addLTOOptions(TC, Args, CmdArgs, Output, Inputs, LTO == LTOK_Thin); if (C.getDriver().IsFlangMode() && !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { diff --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp index 9c1e47f4b61fe..a8ac97ac5f1b9 100644 --- a/clang/lib/Driver/ToolChains/OpenBSD.cpp +++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp @@ -199,9 +199,8 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s, options::OPT_t}); - if (D.isUsingLTO()) - addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs, - D.getLTOMode() == LTOK_Thin); + if (auto LTO = ToolChain.getLTOMode(Args); LTO != LTOK_None) + addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs, LTO == LTOK_Thin); bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs); bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); diff --git a/clang/lib/Driver/ToolChains/PS4CPU.cpp b/clang/lib/Driver/ToolChains/PS4CPU.cpp index 8c281f60ae90a..e40127bc2baeb 100644 --- a/clang/lib/Driver/ToolChains/PS4CPU.cpp +++ b/clang/lib/Driver/ToolChains/PS4CPU.cpp @@ -167,8 +167,8 @@ void tools::PS4cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, // LTO indeed occurs. if (Args.hasFlag(options::OPT_funified_lto, options::OPT_fno_unified_lto, true)) - CmdArgs.push_back(D.getLTOMode() == LTOK_Thin ? "--lto=thin" - : "--lto=full"); + CmdArgs.push_back(TC.getLTOMode(Args) == LTOK_Thin ? "--lto=thin" + : "--lto=full"); if (UseJMC) AddLTOFlag("-enable-jmc-instrument"); @@ -348,8 +348,8 @@ void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasFlag(options::OPT_funified_lto, options::OPT_fno_unified_lto, true)) - CmdArgs.push_back(D.getLTOMode() == LTOK_Thin ? "--lto=thin" - : "--lto=full"); + CmdArgs.push_back(TC.getLTOMode(Args) == LTOK_Thin ? "--lto=thin" + : "--lto=full"); if (Args.hasFlag(options::OPT_ffat_lto_objects, options::OPT_fno_fat_lto_objects, false)) diff --git a/clang/lib/Driver/ToolChains/SPIRV.cpp b/clang/lib/Driver/ToolChains/SPIRV.cpp index 479696d523e90..5cc1eec74c1cc 100644 --- a/clang/lib/Driver/ToolChains/SPIRV.cpp +++ b/clang/lib/Driver/ToolChains/SPIRV.cpp @@ -167,7 +167,7 @@ void SPIRV::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Output.getFilename()); // TODO: Consider moving SPIR-V linking to a separate tool. - if (C.getDriver().isUsingLTO()) { + if (ToolChain.isUsingLTO(Args)) { // Implement limited LTO support through llvm-lto. if (Args.hasArg(options::OPT_sycl_link)) { // For unsupported cases, throw the same error as when LTO isn't supported @@ -201,7 +201,7 @@ SPIRVToolChain::SPIRVToolChain(const Driver &D, const llvm::Triple &Triple, : ToolChain(D, Triple, Args) { // TODO: Revisit need/use of --sycl-link option once SYCL toolchain is // available and SYCL linking support is moved there. - NativeLLVMSupport = Args.hasArg(options::OPT_sycl_link) || D.isUsingLTO(); + NativeLLVMSupport = Args.hasArg(options::OPT_sycl_link) || isUsingLTO(Args); // Lookup binaries into the driver directory. getProgramPaths().push_back(getDriver().Dir); diff --git a/clang/lib/Driver/ToolChains/Serenity.cpp b/clang/lib/Driver/ToolChains/Serenity.cpp index 001765e45f73d..60a966fac39e9 100644 --- a/clang/lib/Driver/ToolChains/Serenity.cpp +++ b/clang/lib/Driver/ToolChains/Serenity.cpp @@ -107,9 +107,8 @@ void tools::serenity::Linker::ConstructJob(Compilation &C, const JobAction &JA, TC.AddFilePathLibArgs(Args, CmdArgs); - if (D.isUsingLTO()) - addLTOOptions(TC, Args, CmdArgs, Output, Inputs, - D.getLTOMode() == LTOK_Thin); + if (auto LTO = TC.getLTOMode(Args); LTO != LTOK_None) + addLTOOptions(TC, Args, CmdArgs, Output, Inputs, LTO == LTOK_Thin); Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s, options::OPT_t, options::OPT_r}); diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp index 4c1cd937e81aa..b90f1ddf596fc 100644 --- a/clang/lib/Driver/ToolChains/WebAssembly.cpp +++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp @@ -248,10 +248,12 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA, } /// Append `Dir` to `Paths`, but also include the LTO directories before that if -/// LTO is eanbled. -static void AppendLibDirAndLTODir(ToolChain::path_list &Paths, const Driver &D, +/// LTO is enabled. +static void AppendLibDirAndLTODir(ToolChain::path_list &Paths, + const ToolChain &TC, + const llvm::opt::ArgList &Args, const std::string &Dir) { - if (D.isUsingLTO()) { + if (TC.isUsingLTO(Args)) { // The version allows the path to be keyed to the specific version of // LLVM in used, as the bitcode format is not stable. Paths.push_back(Dir + "/llvm-lto/" LLVM_VERSION_STRING); @@ -283,9 +285,9 @@ WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple, // sysroots that contain libraries that are capable of producing binaries // entirely without exception-handling instructions but also with if // exceptions are enabled, for example. - AppendLibDirAndLTODir(getFilePaths(), D, + AppendLibDirAndLTODir(getFilePaths(), *this, Args, TripleLibDir + "/" + GetCXXExceptionsDir(Args)); - AppendLibDirAndLTODir(getFilePaths(), D, TripleLibDir); + AppendLibDirAndLTODir(getFilePaths(), *this, Args, TripleLibDir); } if (getTriple().getOS() == llvm::Triple::WASI) { >From 9f0f05e18af7cbc38eddec613dbe8eeab2700e6a Mon Sep 17 00:00:00 2001 From: Joseph Huber <[email protected]> Date: Tue, 2 Jun 2026 14:02:39 -0500 Subject: [PATCH 2/3] Comments --- clang/include/clang/Driver/ToolChain.h | 3 ++- clang/lib/Driver/Driver.cpp | 3 +-- clang/lib/Driver/ToolChain.cpp | 4 ++-- clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp | 2 +- clang/lib/Driver/ToolChains/Clang.cpp | 5 ++--- clang/lib/Driver/ToolChains/Cuda.cpp | 2 +- 6 files changed, 9 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h index d700457c68591..2ce3f38ebe6f3 100644 --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -472,7 +472,8 @@ class ToolChain { bool IsOffload = false) const; /// Returns true if LTO is active for this toolchain given the args. - bool isUsingLTO(const llvm::opt::ArgList &Args, bool IsOffload = false) const; + bool isUsingLTO(const llvm::opt::ArgList &Args, + Action::OffloadKind Kind = Action::OFK_None) const; /// LookupTypeForExtension - Return the default language type to use for the /// given extension. diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 636a39b3690e7..f40183fc9317b 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -3754,8 +3754,7 @@ class OffloadingActionBuilder final { // a fat binary containing all the code objects for different GPU's. // The fat binary is then an input to the host action. for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) { - if (ToolChains[I]->isUsingLTO(Args, - /*IsOffload=*/true)) { + if (ToolChains[I]->isUsingLTO(Args, AssociatedOffloadKind)) { // When LTO is enabled, skip the backend and assemble phases and // use lld to link the bitcode. ActionList AL; diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index dd73c889570b9..032b3bbaa0483 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -1331,8 +1331,8 @@ bool ToolChain::HasNativeLLVMSupport() const { LTOKind ToolChain::getDefaultLTOMode() const { return LTOK_None; } bool ToolChain::isUsingLTO(const llvm::opt::ArgList &Args, - bool IsOffload) const { - return getLTOMode(Args, IsOffload) != LTOK_None; + Action::OffloadKind Kind) const { + return getLTOMode(Args, Kind != Action::OFK_None) != LTOK_None; } static LTOKind parseLTOMode(const llvm::opt::ArgList &Args, diff --git a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp index a03ac8227a8c3..40c85bae0b9db 100644 --- a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp +++ b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp @@ -49,7 +49,7 @@ void AMDGPUOpenMPToolChain::addClangTargetOptions( } // Link the bitcode library late if we're using device LTO. - if (isUsingLTO(DriverArgs, /*IsOffload=*/true)) + if (isUsingLTO(DriverArgs, DeviceOffloadingKind)) return; } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 57348dbeeb32c..8117058e1a228 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -9507,7 +9507,7 @@ void OffloadPackager::ConstructJob(Compilation &C, const JobAction &JA, "kind=" + Kind.str(), }; - if (TC->isUsingLTO(TCArgs, /*IsOffload=*/true)) + if (TC->isUsingLTO(TCArgs, OffloadAction->getOffloadingDeviceKind())) for (StringRef Feature : FeatureArgs) Parts.emplace_back("feature=" + Feature.str()); @@ -9681,8 +9681,7 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, // flags. SYCL uses clang-sycl-linker instead of spirv-link, so skip it. if (TC->getTriple().isSPIRV() && TC->getTriple().getVendor() != llvm::Triple::VendorType::AMD && - Kind != Action::OFK_SYCL && - !TC->isUsingLTO(ToolChainArgs, /*IsOffload=*/true)) { + Kind != Action::OFK_SYCL && !TC->isUsingLTO(ToolChainArgs, Kind)) { // For SPIR-V some functions will be defined by the runtime so allow // unresolved symbols in `spirv-link`. LinkerArgs.emplace_back("--allow-partial-linkage"); diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp index a25f00e96b2f1..2e47d3e33ed50 100644 --- a/clang/lib/Driver/ToolChains/Cuda.cpp +++ b/clang/lib/Driver/ToolChains/Cuda.cpp @@ -939,7 +939,7 @@ void CudaToolChain::addClangTargetOptions( } // Link the bitcode library late if we're using device LTO. - if (isUsingLTO(DriverArgs, /*IsOffload=*/true)) + if (isUsingLTO(DriverArgs, DeviceOffloadingKind)) return; addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, GpuArch.str(), >From 26b84fe9eca84f5d62c9781898d9bdc0a4c02e89 Mon Sep 17 00:00:00 2001 From: Joseph Huber <[email protected]> Date: Tue, 2 Jun 2026 14:38:04 -0500 Subject: [PATCH 3/3] comments 2 --- clang/include/clang/Driver/ToolChain.h | 2 +- clang/lib/Driver/Driver.cpp | 15 ++++++--------- clang/lib/Driver/ToolChain.cpp | 5 +++-- clang/lib/Driver/ToolChains/Clang.cpp | 12 +++++++----- clang/lib/Driver/ToolChains/HIPAMD.cpp | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h index 2ce3f38ebe6f3..c9051d17850ad 100644 --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -469,7 +469,7 @@ class ToolChain { /// Resolve the requested LTO mode for this toolchain. LTOKind getLTOMode(const llvm::opt::ArgList &Args, - bool IsOffload = false) const; + Action::OffloadKind Kind = Action::OFK_None) const; /// Returns true if LTO is active for this toolchain given the args. bool isUsingLTO(const llvm::opt::ArgList &Args, diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index f40183fc9317b..d1170400f58c2 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -3602,8 +3602,7 @@ class OffloadingActionBuilder final { CudaDeviceActions[I] = C.getDriver().ConstructPhaseAction( C, Args, Ph, CudaDeviceActions[I], Action::OFK_Cuda, - ToolChains[I]->getLTOMode(Args, - /*IsOffload=*/true)); + ToolChains[I]->getLTOMode(Args, Action::OFK_Cuda)); if (Ph == phases::Assemble) break; @@ -3780,7 +3779,8 @@ class OffloadingActionBuilder final { BackendAction = C.MakeAction<BackendJobAction>(CudaDeviceActions[I], Output); } else { - auto DevLTO = ToolChains[I]->getLTOMode(Args, /*IsOffload=*/true); + auto DevLTO = + ToolChains[I]->getLTOMode(Args, AssociatedOffloadKind); BackendAction = C.getDriver().ConstructPhaseAction( C, Args, phases::Backend, CudaDeviceActions[I], AssociatedOffloadKind, DevLTO); @@ -3852,8 +3852,7 @@ class OffloadingActionBuilder final { for (unsigned I = 0, E = CudaDeviceActions.size(); I != E; ++I) CudaDeviceActions[I] = C.getDriver().ConstructPhaseAction( C, Args, CurPhase, CudaDeviceActions[I], AssociatedOffloadKind, - ToolChains[I]->getLTOMode(Args, - /*IsOffload=*/true)); + ToolChains[I]->getLTOMode(Args, AssociatedOffloadKind)); if (CompileDeviceOnly && CurPhase == FinalPhase && BundleOutput && *BundleOutput) { @@ -5036,10 +5035,8 @@ Driver::BuildOffloadingActions(Compilation &C, llvm::opt::DerivedArgList &Args, // Propagate the ToolChain so we can use it in ConstructPhaseAction. A->propagateDeviceOffloadInfo(Kind, TCAndArch->second.data(), TCAndArch->first); - A = ConstructPhaseAction( - C, Args, Phase, A, Kind, - TCAndArch->first->getLTOMode(Args, - /*IsOffload=*/true)); + A = ConstructPhaseAction(C, Args, Phase, A, Kind, + TCAndArch->first->getLTOMode(Args, Kind)); if (isa<CompileJobAction>(A) && isa<CompileJobAction>(HostAction) && Kind == Action::OFK_OpenMP && diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 032b3bbaa0483..82c4a7a34e47f 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -1332,7 +1332,7 @@ LTOKind ToolChain::getDefaultLTOMode() const { return LTOK_None; } bool ToolChain::isUsingLTO(const llvm::opt::ArgList &Args, Action::OffloadKind Kind) const { - return getLTOMode(Args, Kind != Action::OFK_None) != LTOK_None; + return getLTOMode(Args, Kind) != LTOK_None; } static LTOKind parseLTOMode(const llvm::opt::ArgList &Args, @@ -1351,7 +1351,8 @@ static LTOKind parseLTOMode(const llvm::opt::ArgList &Args, } LTOKind ToolChain::getLTOMode(const llvm::opt::ArgList &Args, - bool IsOffload) const { + Action::OffloadKind Kind) const { + bool IsOffload = Kind != Action::OFK_None; auto OptEq = IsOffload ? options::OPT_foffload_lto_EQ : options::OPT_flto_EQ; auto OptNeg = IsOffload ? options::OPT_fno_offload_lto : options::OPT_fno_lto; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 8117058e1a228..8ffd7d56ae97c 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5028,7 +5028,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, bool IsRDCMode = Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false); - auto LTOMode = TC.getLTOMode(Args, IsDeviceOffloadAction); + auto LTOMode = TC.getLTOMode(Args, JA.getOffloadingDeviceKind()); bool IsUsingLTO = LTOMode != LTOK_None; // Extract API doesn't have a main input file, so invent a fake one as a @@ -8238,12 +8238,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Check if we are using PS4 in regular LTO mode. // Otherwise, issue an error. - auto OtherLTOMode = TC.getLTOMode(Args, !IsDeviceOffloadAction); + auto OtherLTOMode = TC.getLTOMode( + Args, IsDeviceOffloadAction ? Action::OFK_None + : static_cast<Action::OffloadKind>( + C.getActiveOffloadKinds())); auto OtherIsUsingLTO = OtherLTOMode != LTOK_None; if ((!IsUsingLTO && !OtherIsUsingLTO) || - (IsPS4 && !UnifiedLTO && - (TC.getLTOMode(Args, /*IsOffload=*/false) != LTOK_Full))) + (IsPS4 && !UnifiedLTO && (TC.getLTOMode(Args) != LTOK_Full))) D.Diag(diag::err_drv_argument_only_allowed_with) << "-fwhole-program-vtables" << ((IsPS4 && !UnifiedLTO) ? "-flto=full" : "-flto"); @@ -9698,7 +9700,7 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, "--device-linker=" + TC->getTripleString() + "=" + Arg)); // Forward the LTO mode for this toolchain. - auto DeviceLTOMode = TC->getLTOMode(ToolChainArgs, /*IsOffload=*/true); + auto DeviceLTOMode = TC->getLTOMode(ToolChainArgs, Kind); if (DeviceLTOMode == LTOK_Full) CmdArgs.push_back(Args.MakeArgString( "--device-compiler=" + TC->getTripleString() + "=-flto=full")); diff --git a/clang/lib/Driver/ToolChains/HIPAMD.cpp b/clang/lib/Driver/ToolChains/HIPAMD.cpp index ea2efedd6251b..5b88398c747d1 100644 --- a/clang/lib/Driver/ToolChains/HIPAMD.cpp +++ b/clang/lib/Driver/ToolChains/HIPAMD.cpp @@ -70,7 +70,7 @@ void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA, auto &TC = getToolChain(); auto &D = TC.getDriver(); - bool IsThinLTO = TC.getLTOMode(Args, /*IsOffload=*/true) == LTOK_Thin; + bool IsThinLTO = TC.getLTOMode(Args, Action::OFK_HIP) == LTOK_Thin; addLTOOptions(TC, Args, LldArgs, Output, Inputs, IsThinLTO); // Extract all the -m options _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
