From 599cde6bd3fd0cbba3d589699170fd95ef10b630 Mon Sep 17 00:00:00 2001 From: Teresa Johnson Date: Mon, 16 Dec 2024 12:48:17 -0800 Subject: [PATCH 1/2] [ThinLTO] Skip opt pipeline and summary wrapper pass on empty modules Follow up to PR118508, to avoid unnecessary compile time for an empty combind regular LTO module if all modules end up being ThinLTO only. --- lld/test/ELF/lto/new-pass-manager.ll | 4 +++ llvm/lib/LTO/LTOBackend.cpp | 30 +++++++++++++++++++---- llvm/test/Feature/load_plugin_error.ll | 2 +- llvm/test/Other/X86/lto-hot-cold-split.ll | 4 +++ 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/lld/test/ELF/lto/new-pass-manager.ll b/lld/test/ELF/lto/new-pass-manager.ll index cc6ff34cd91ae..77a1d4ed3d27d 100644 --- a/lld/test/ELF/lto/new-pass-manager.ll +++ b/lld/test/ELF/lto/new-pass-manager.ll @@ -9,3 +9,7 @@ target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" + +define void @foo() { + ret void +} diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp index bdf4ff8960bc8..51bd7cc29c769 100644 --- a/llvm/lib/LTO/LTOBackend.cpp +++ b/llvm/lib/LTO/LTOBackend.cpp @@ -351,6 +351,13 @@ static void runNewPMPasses(const Config &Conf, Module &Mod, TargetMachine *TM, MPM.run(Mod, MAM); } +static bool isEmptyModule(const Module &Mod) { + // Module is empty if it has no functions, no globals, no inline asm and no + // named metadata (aliases and ifuncs require functions or globals so we + // don't need to check those explicitly). + return Mod.empty() && Mod.global_empty() && Mod.named_metadata_empty() && Mod.getModuleInlineAsm().empty(); +} + bool lto::opt(const Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod, bool IsThinLTO, ModuleSummaryIndex *ExportSummary, const ModuleSummaryIndex *ImportSummary, @@ -372,9 +379,16 @@ bool lto::opt(const Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod, /*EmbedBitcode*/ true, /*EmbedCmdline*/ true, /*Cmdline*/ CmdArgs); } - // FIXME: Plumb the combined index into the new pass manager. - runNewPMPasses(Conf, Mod, TM, Conf.OptLevel, IsThinLTO, ExportSummary, - ImportSummary); + // No need to run any opt passes if the module is empty. + // In theory these passes should take almost no time for an empty + // module, however, this guards against doing any unnecessary summary-based + // analysis in the case of a ThinLTO build where this might be an empty + // regular LTO combined module, with a large combined index from ThinLTO. + if (!isEmptyModule(Mod)) { + // FIXME: Plumb the combined index into the new pass manager. + runNewPMPasses(Conf, Mod, TM, Conf.OptLevel, IsThinLTO, ExportSummary, + ImportSummary); + } return !Conf.PostOptModuleHook || Conf.PostOptModuleHook(Task, Mod); } @@ -422,8 +436,14 @@ static void codegen(const Config &Conf, TargetMachine *TM, legacy::PassManager CodeGenPasses; TargetLibraryInfoImpl TLII(Triple(Mod.getTargetTriple())); CodeGenPasses.add(new TargetLibraryInfoWrapperPass(TLII)); - CodeGenPasses.add( - createImmutableModuleSummaryIndexWrapperPass(&CombinedIndex)); + // No need to make index available if the module is empty. + // In theory these passes should not use the index for an empty + // module, however, this guards against doing any unnecessary summary-based + // analysis in the case of a ThinLTO build where this might be an empty + // regular LTO combined module, with a large combined index from ThinLTO. + if (!isEmptyModule(Mod)) + CodeGenPasses.add( + createImmutableModuleSummaryIndexWrapperPass(&CombinedIndex)); if (Conf.PreCodeGenPassesHook) Conf.PreCodeGenPassesHook(CodeGenPasses); if (TM->addPassesToEmitFile(CodeGenPasses, *Stream->OS, diff --git a/llvm/test/Feature/load_plugin_error.ll b/llvm/test/Feature/load_plugin_error.ll index a112bfbb1cd19..b40dddff1205f 100644 --- a/llvm/test/Feature/load_plugin_error.ll +++ b/llvm/test/Feature/load_plugin_error.ll @@ -5,7 +5,7 @@ ; RUN: opt %s -o %t.o ; RUN: not llvm-lto2 run -load-pass-plugin=%t/nonexistent.so %t.o -o %t \ -; RUN: -r %t.o,test 2>&1 | \ +; RUN: -r %t.o,test,plx 2>&1 | \ ; RUN: FileCheck %s ; CHECK: Could not load library {{.*}}nonexistent.so diff --git a/llvm/test/Other/X86/lto-hot-cold-split.ll b/llvm/test/Other/X86/lto-hot-cold-split.ll index 22c79c7e06bba..24903f34ed074 100644 --- a/llvm/test/Other/X86/lto-hot-cold-split.ll +++ b/llvm/test/Other/X86/lto-hot-cold-split.ll @@ -10,3 +10,7 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" ; OLDPM-ANYLTO-POSTLINK-Os: HotColdSplittingPass + +define void @foo() { + ret void +} From e2cce1f07a28f6512ead14140db470d07f6d0f4e Mon Sep 17 00:00:00 2001 From: Teresa Johnson Date: Fri, 10 Jan 2025 14:01:54 -0800 Subject: [PATCH 2/2] Clang format --- llvm/lib/LTO/LTOBackend.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp index 51bd7cc29c769..8a2dddce4892c 100644 --- a/llvm/lib/LTO/LTOBackend.cpp +++ b/llvm/lib/LTO/LTOBackend.cpp @@ -355,7 +355,8 @@ static bool isEmptyModule(const Module &Mod) { // Module is empty if it has no functions, no globals, no inline asm and no // named metadata (aliases and ifuncs require functions or globals so we // don't need to check those explicitly). - return Mod.empty() && Mod.global_empty() && Mod.named_metadata_empty() && Mod.getModuleInlineAsm().empty(); + return Mod.empty() && Mod.global_empty() && Mod.named_metadata_empty() && + Mod.getModuleInlineAsm().empty(); } bool lto::opt(const Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod,