https://github.com/anchuraj created https://github.com/llvm/llvm-project/pull/164302
This PR enables module summary for LTO. Information in module summary is used in performing LTO especially in Thin LTO.
>From 8d5366a6e870dc40370ea4745bb27047fd52234f Mon Sep 17 00:00:00 2001
From: Anchu Rajendran <asudhaku at amd.com>
Date: Fri, 17 Oct 2025 17:37:12 -0500
Subject: [PATCH] [Flang][Driver] Emit module summary for LTO
---
flang/lib/Frontend/FrontendActions.cpp | 16 +++++++-----
flang/test/CMakeLists.txt | 1 +
flang/test/Driver/lto-bc.f90 | 36 ++++++++++++++++++--------
3 files changed, 36 insertions(+), 17 deletions(-)
diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index 0c630d2ba876d..0ff5ba17ca874 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -1019,11 +1019,15 @@ void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) {
// Create the pass manager.
llvm::ModulePassManager mpm;
+ // The module summary should be emitted by default for regular LTO
+ // except for ld64 targets.
+ bool emitSummary = (opts.PrepareForThinLTO || opts.PrepareForFullLTO) &&
+ (triple.getVendor() != llvm::Triple::Apple);
+
+ if (emitSummary && !opts.PrepareForThinLTO)
+ llvmModule->addModuleFlag(llvm::Module::Error, "ThinLTO", uint32_t(0));
+
if (opts.PrepareForFatLTO) {
- // The module summary should be emitted by default for regular LTO
- // except for ld64 targets.
- bool emitSummary = opts.PrepareForThinLTO || opts.PrepareForFullLTO ||
- triple.getVendor() != llvm::Triple::Apple;
mpm = pb.buildFatLTODefaultPipeline(level, opts.PrepareForThinLTO,
emitSummary);
} else if (opts.PrepareForFullLTO)
@@ -1034,9 +1038,9 @@ void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) {
mpm = pb.buildPerModuleDefaultPipeline(level);
if (action == BackendActionTy::Backend_EmitBC)
- mpm.addPass(llvm::BitcodeWriterPass(os));
+ mpm.addPass(llvm::BitcodeWriterPass(os, false, emitSummary));
else if (action == BackendActionTy::Backend_EmitLL)
- mpm.addPass(llvm::PrintModulePass(os));
+ mpm.addPass(llvm::PrintModulePass(os, "", false, emitSummary));
// FIXME: This should eventually be replaced by a first-class driver option.
// This should be done for both flang and clang simultaneously.
diff --git a/flang/test/CMakeLists.txt b/flang/test/CMakeLists.txt
index da557f9ec3443..8c8e92faa787a 100644
--- a/flang/test/CMakeLists.txt
+++ b/flang/test/CMakeLists.txt
@@ -72,6 +72,7 @@ if (NOT FLANG_STANDALONE_BUILD)
FileCheck
count
not
+ llvm-bcanalyzer
llvm-dis
llvm-objcopy
llvm-objdump
diff --git a/flang/test/Driver/lto-bc.f90 b/flang/test/Driver/lto-bc.f90
index 5e34cdb87c5b1..fbf964b849eb7 100644
--- a/flang/test/Driver/lto-bc.f90
+++ b/flang/test/Driver/lto-bc.f90
@@ -1,21 +1,35 @@
! Test that the output is LLVM bitcode for LTO and not a native objectfile by
-! disassembling it to LLVM IR.
-! Right now there is nothing special about it and it is similar to non-lto IR,
-! more work is needed to add things like module summaries.
+! disassembling it to LLVM IR. Also tests module summaries are emitted for LTO
! RUN: %flang %s -c -o - | not llvm-dis -o %t
! RUN: %flang_fc1 %s -emit-llvm-bc -o - | llvm-dis -o - | FileCheck %s
-
-! RUN: %flang -flto %s -c -o - | llvm-dis -o - | FileCheck %s
-! RUN: %flang -flto=thin %s -c -o - | llvm-dis -o - | FileCheck %s
-
! CHECK: define void @_QQmain()
! CHECK-NEXT: ret void
! CHECK-NEXT: }
+! CHECK-NOT: !{{.*}} = !{i32 1, !"ThinLTO", i32 0}
+! CHECK-NOT: ^{{.*}} = module:
+! CHECK-NOT: ^{{.*}} = gv: (name:
+! CHECK-NOT: ^{{.*}} = blockcount:
+
+! RUN: %flang -flto %s -c -o - | llvm-dis -o - | FileCheck %s --check-prefix=FULL
+! THIN: define void @_QQmain()
+! THIN-NEXT: ret void
+! THIN-NEXT: }
+! THIN-NOT: !{{.*}} = !{i32 1, !"ThinLTO", i32 0}
+! THIN: ^{{.*}} = module:
+! THIN: ^{{.*}} = gv: (name:
+! THIN: ^{{.*}} = blockcount:
-! CHECK-NOT: ^0 = module:
-! CHECK-NOT: ^1 = gv: (name:
-! CHECK-NOT: ^2 = flags:
-! CHECK-NOT: ^3 = blockcount:
+! RUN: %flang -flto=thin %s -c -o - | llvm-dis -o - | FileCheck %s --check-prefix=THIN
+! FULL: define void @_QQmain()
+! FULL-NEXT: ret void
+! FULL-NEXT: }
+! FULL: !{{.*}} = !{i32 1, !"ThinLTO", i32 0}
+! FULL: ^{{.*}} = module:
+! FULL: ^{{.*}} = gv: (name:
+! FULL: ^{{.*}} = blockcount:
+! RUN: %flang_fc1 -flto -emit-llvm-bc %s -o - | llvm-bcanalyzer -dump| FileCheck --check-prefix=MOD-SUMM %s
+! MOD-SUMM: FULL_LTO_GLOBALVAL_SUMMARY_BLOCK
+program main
end program