From 330989345ab5acfd6854a0ac196dec82a0a582a6 Mon Sep 17 00:00:00 2001 From: Anchu Rajendran Date: Fri, 17 Oct 2025 17:37:12 -0500 Subject: [PATCH 1/5] [Flang][Driver] Emit module summary for LTO --- flang/lib/Frontend/FrontendActions.cpp | 18 ++++++++----- flang/test/CMakeLists.txt | 1 + flang/test/Driver/lto-bc.f90 | 36 ++++++++++++++++++-------- 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index 0c630d2ba876d..c773a96bcd2a8 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,11 @@ 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, /*ShouldPreserveUseListOrder=*/false, emitSummary)); else if (action == BackendActionTy::Backend_EmitLL) - mpm.addPass(llvm::PrintModulePass(os)); + mpm.addPass(llvm::PrintModulePass( + os, /*Banner=*/"", /*ShouldPreserveUseListOrder=*/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 From 1ecbeb9e5900b485fb199739721516b1b1850dfd Mon Sep 17 00:00:00 2001 From: Anchu Rajendran Date: Tue, 21 Oct 2025 12:18:58 -0500 Subject: [PATCH 2/5] R2: Addressing review comments --- flang/lib/Frontend/FrontendActions.cpp | 4 ++-- flang/test/Driver/lto-bc.f90 | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index c773a96bcd2a8..54353310aac6e 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -1027,10 +1027,10 @@ void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) { if (emitSummary && !opts.PrepareForThinLTO) llvmModule->addModuleFlag(llvm::Module::Error, "ThinLTO", uint32_t(0)); - if (opts.PrepareForFatLTO) { + if (opts.PrepareForFatLTO) mpm = pb.buildFatLTODefaultPipeline(level, opts.PrepareForThinLTO, emitSummary); - } else if (opts.PrepareForFullLTO) + else if (opts.PrepareForFullLTO) mpm = pb.buildLTOPreLinkDefaultPipeline(level); else if (opts.PrepareForThinLTO) mpm = pb.buildThinLTOPreLinkDefaultPipeline(level); diff --git a/flang/test/Driver/lto-bc.f90 b/flang/test/Driver/lto-bc.f90 index fbf964b849eb7..57b81aa8d2809 100644 --- a/flang/test/Driver/lto-bc.f90 +++ b/flang/test/Driver/lto-bc.f90 @@ -1,5 +1,5 @@ ! Test that the output is LLVM bitcode for LTO and not a native objectfile by -! disassembling it to LLVM IR. Also tests module summaries are emitted for LTO +! disassembling it to LLVM IR. Also tests that 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 @@ -11,7 +11,7 @@ ! CHECK-NOT: ^{{.*}} = gv: (name: ! CHECK-NOT: ^{{.*}} = blockcount: -! RUN: %flang -flto %s -c -o - | llvm-dis -o - | FileCheck %s --check-prefix=FULL +! RUN: %flang -flto=thin %s -c -o - | llvm-dis -o - | FileCheck %s --check-prefix=THIN ! THIN: define void @_QQmain() ! THIN-NEXT: ret void ! THIN-NEXT: } @@ -20,7 +20,7 @@ ! THIN: ^{{.*}} = gv: (name: ! THIN: ^{{.*}} = blockcount: -! RUN: %flang -flto=thin %s -c -o - | llvm-dis -o - | FileCheck %s --check-prefix=THIN +! RUN: %flang -flto %s -c -o - | llvm-dis -o - | FileCheck %s --check-prefix=FULL ! FULL: define void @_QQmain() ! FULL-NEXT: ret void ! FULL-NEXT: } From 51e02c1bb88a4cb39635ffd09e09f76e9f01b7ab Mon Sep 17 00:00:00 2001 From: Anchu Rajendran Date: Tue, 21 Oct 2025 13:50:52 -0500 Subject: [PATCH 3/5] Removing the changes from ThinLTO --- flang/lib/Frontend/FrontendActions.cpp | 30 +++++++++++++++++--------- flang/test/Driver/lto-bc.f90 | 6 ------ 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index 54353310aac6e..c691577c634d3 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -1023,10 +1023,6 @@ void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) { // 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) mpm = pb.buildFatLTODefaultPipeline(level, opts.PrepareForThinLTO, emitSummary); @@ -1037,12 +1033,26 @@ void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) { else mpm = pb.buildPerModuleDefaultPipeline(level); - if (action == BackendActionTy::Backend_EmitBC) - mpm.addPass(llvm::BitcodeWriterPass( - os, /*ShouldPreserveUseListOrder=*/false, emitSummary)); - else if (action == BackendActionTy::Backend_EmitLL) - mpm.addPass(llvm::PrintModulePass( - os, /*Banner=*/"", /*ShouldPreserveUseListOrder=*/false, emitSummary)); + if (action == BackendActionTy::Backend_EmitBC || + action == BackendActionTy::Backend_EmitLL || opts.PrepareForFatLTO) { + if (opts.PrepareForThinLTO) { + // TODO: ThinLTO module summary support is yet to be enabled. + if (action == BackendActionTy::Backend_EmitBC) + mpm.addPass(llvm::BitcodeWriterPass(os)); + else if (action == BackendActionTy::Backend_EmitLL) + mpm.addPass(llvm::PrintModulePass(os)); + } else { + if (emitSummary && !llvmModule->getModuleFlag("ThinLTO")) + llvmModule->addModuleFlag(llvm::Module::Error, "ThinLTO", uint32_t(0)); + if (action == BackendActionTy::Backend_EmitBC) + mpm.addPass(llvm::BitcodeWriterPass( + os, /*ShouldPreserveUseListOrder=*/false, emitSummary)); + else if (action == BackendActionTy::Backend_EmitLL) + mpm.addPass(llvm::PrintModulePass(os, /*Banner=*/"", + /*ShouldPreserveUseListOrder=*/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/Driver/lto-bc.f90 b/flang/test/Driver/lto-bc.f90 index 57b81aa8d2809..b85021331902c 100644 --- a/flang/test/Driver/lto-bc.f90 +++ b/flang/test/Driver/lto-bc.f90 @@ -12,13 +12,7 @@ ! CHECK-NOT: ^{{.*}} = blockcount: ! RUN: %flang -flto=thin %s -c -o - | llvm-dis -o - | FileCheck %s --check-prefix=THIN -! THIN: define void @_QQmain() -! THIN-NEXT: ret void -! THIN-NEXT: } ! THIN-NOT: !{{.*}} = !{i32 1, !"ThinLTO", i32 0} -! THIN: ^{{.*}} = module: -! THIN: ^{{.*}} = gv: (name: -! THIN: ^{{.*}} = blockcount: ! RUN: %flang -flto %s -c -o - | llvm-dis -o - | FileCheck %s --check-prefix=FULL ! FULL: define void @_QQmain() From c050671c5f9c8c96c0bb452e2079b6a5e375ef3b Mon Sep 17 00:00:00 2001 From: Anchu Rajendran Date: Wed, 22 Oct 2025 12:20:41 -0500 Subject: [PATCH 4/5] R3: Addressing review comments --- flang/lib/Frontend/FrontendActions.cpp | 3 +-- flang/test/Driver/lto-bc.f90 | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index c691577c634d3..5dbdc799f1611 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -1021,8 +1021,7 @@ void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) { 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); + bool emitSummary = opts.PrepareForFullLTO && (triple.getVendor() != llvm::Triple::Apple); if (opts.PrepareForFatLTO) mpm = pb.buildFatLTODefaultPipeline(level, opts.PrepareForThinLTO, emitSummary); diff --git a/flang/test/Driver/lto-bc.f90 b/flang/test/Driver/lto-bc.f90 index b85021331902c..01fdcacb6d783 100644 --- a/flang/test/Driver/lto-bc.f90 +++ b/flang/test/Driver/lto-bc.f90 @@ -13,6 +13,9 @@ ! RUN: %flang -flto=thin %s -c -o - | llvm-dis -o - | FileCheck %s --check-prefix=THIN ! THIN-NOT: !{{.*}} = !{i32 1, !"ThinLTO", i32 0} +! THIN-NOT: ^{{.*}} = module: +! THIN-NOT: ^{{.*}} = gv: (name: +! THIN-NOT: ^{{.*}} = blockcount: ! RUN: %flang -flto %s -c -o - | llvm-dis -o - | FileCheck %s --check-prefix=FULL ! FULL: define void @_QQmain() From ee40244de2484c9deddd6e9feb8db9dfcd8590c2 Mon Sep 17 00:00:00 2001 From: Anchu Rajendran Date: Wed, 22 Oct 2025 12:34:49 -0500 Subject: [PATCH 5/5] R4: Addressing review comments --- flang/lib/Frontend/FrontendActions.cpp | 3 ++- flang/test/Driver/lto-bc.f90 | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index 5dbdc799f1611..159d08a2797b3 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -1021,7 +1021,8 @@ void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) { llvm::ModulePassManager mpm; // The module summary should be emitted by default for regular LTO // except for ld64 targets. - bool emitSummary = opts.PrepareForFullLTO && (triple.getVendor() != llvm::Triple::Apple); + bool emitSummary = + opts.PrepareForFullLTO && (triple.getVendor() != llvm::Triple::Apple); if (opts.PrepareForFatLTO) mpm = pb.buildFatLTODefaultPipeline(level, opts.PrepareForThinLTO, emitSummary); diff --git a/flang/test/Driver/lto-bc.f90 b/flang/test/Driver/lto-bc.f90 index 01fdcacb6d783..5705fe0cbb929 100644 --- a/flang/test/Driver/lto-bc.f90 +++ b/flang/test/Driver/lto-bc.f90 @@ -12,6 +12,9 @@ ! CHECK-NOT: ^{{.*}} = blockcount: ! RUN: %flang -flto=thin %s -c -o - | llvm-dis -o - | FileCheck %s --check-prefix=THIN +! THIN: define void @_QQmain() +! THIN-NEXT: ret void +! THIN-NEXT: } ! THIN-NOT: !{{.*}} = !{i32 1, !"ThinLTO", i32 0} ! THIN-NOT: ^{{.*}} = module: ! THIN-NOT: ^{{.*}} = gv: (name: