https://github.com/tianleliu created 
https://github.com/llvm/llvm-project/pull/175696


Only if module's name contains a string in -filter-print-modules, will its 
temps BC files be dumped. If -filter-print-modules= not set, all modules' BC 
files will be dumped. This feature is more useful for ThinLto when huge numbers 
of modules are built separately. Using -filter-print-modules= can reduce build 
time and size of generated files, even avoid crash if some other unrelated 
files have issues during BC files dumping.

>From 212ae9590c14555c6a9329e8eec45216924063e8 Mon Sep 17 00:00:00 2001
From: tianleli <[email protected]>
Date: Tue, 13 Jan 2026 09:28:03 +0800
Subject: [PATCH] [LTOBackend] Add -filter-print-modules= for save-temps to
 only dump specific modules' temps BC files.

Only if module's name contains a string in -filter-print-modules, will its 
temps BC files be dumped.
If -filter-print-modules= not set, all modules' BC files will be dumped.
This feature is more useful for ThinLto when huge numbers of modules are built 
separately.
Using -filter-print-modules= can reduce build time and size of generated files,
even avoid crash if some other unrelated files have issues during BC files 
dumping.
---
 clang/test/CodeGen/thinlto-savetemps-mod.ll | 47 +++++++++++++++++++++
 llvm/lib/LTO/LTOBackend.cpp                 | 22 ++++++++++
 2 files changed, 69 insertions(+)
 create mode 100644 clang/test/CodeGen/thinlto-savetemps-mod.ll

diff --git a/clang/test/CodeGen/thinlto-savetemps-mod.ll 
b/clang/test/CodeGen/thinlto-savetemps-mod.ll
new file mode 100644
index 0000000000000..cb5a4c2374822
--- /dev/null
+++ b/clang/test/CodeGen/thinlto-savetemps-mod.ll
@@ -0,0 +1,47 @@
+# RUN: rm -rf %t.dir
+# RUN: split-file %s %t.dir && cd %t.dir
+# RUN: %clang -c -flto=thin -O2  mymul.cpp  -o mymul.o
+# RUN: %clang -c -flto=thin -O2  myfoo.cpp  -o myfoo.o
+# RUN: %clang  -shared -O2 -flto=thin mymul.o myfoo.o   -o libmy.so 
-Wl,-plugin-opt=save-temps -Wl,-plugin-opt=-filter-print-modules=mymul
+# RUN: ls -tr | FileCheck %s --check-prefix=MUL
+# RUN: rm *.bc
+# RUN: %clang  -shared  -O2 -flto=thin mymul.o myfoo.o  -o libmy.so 
-Wl,-plugin-opt=save-temps -Wl,-plugin-opt=-filter-print-modules=mymul 
-Wl,-plugin-opt=-filter-print-modules=myfoo
+# RUN: ls -tr | FileCheck %s --check-prefix=MUL_FOO
+# RUN: rm *.bc
+# RUN: %clang  -shared  -O2 -flto=thin mymul.o myfoo.o  -o libmy.so 
-Wl,-plugin-opt=save-temps
+# RUN: ls -tr | FileCheck %s --check-prefix=ALL
+
+# MUL-NOT: myfoo.o.{{[0-5]+}}{{.*}}.bc
+# MUL-DAG: mymul.o.0.preopt.bc
+# MUL-DAG: mymul.o.1.promote.bc
+# MUL-DAG: mymul.o.2.internalize.bc
+# MUL-DAG: mymul.o.3.import.bc
+# MUL-DAG: mymul.o.4.opt.bc
+# MUL-DAG: mymul.o.5.precodegen.bc
+# MUL-NOT: myfoo.o.{{[0-5]+}}{{.*}}.bc
+
+# MUL_FOO-DAG: mymul.o.{{[0-5]+}}{{.*}}.bc
+# MUL_FOO-DAG: myfoo.o.{{[0-5]+}}{{.*}}.bc
+
+# ALL-DAG: mymul.o.{{[0-5]+}}{{.*}}.bc
+# ALL-DAG: myfoo.o.{{[0-5]+}}{{.*}}.bc
+
+#--- myfoo.h
+__attribute__((visibility("default"))) long foo(long n);
+
+#--- myfoo.cpp
+#include "myfoo.h"
+#include "mymul.h"
+__attribute__((visibility("default"))) long foo(long n) {
+  return mul(n,n+1);
+}
+
+#--- mymul.h
+long mul(int a, int b);
+
+#--- mymul.cpp
+#include "mymul.h"
+long mul(int a, int b) {
+   return a*a;
+}
+
diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index e998ac961e24a..a05e9f0d9038f 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -74,6 +74,12 @@ static cl::opt<bool> ThinLTOAssumeMerged(
     cl::desc("Assume the input has already undergone ThinLTO function "
              "importing and the other pre-optimization pipeline changes."));
 
+static cl::list<std::string>
+    PrintModulesList("filter-print-modules", cl::value_desc("module names"),
+                     cl::desc("Only print IR for module whose name "
+                              "includes this for -save-temps options"),
+                     cl::CommaSeparated, cl::Hidden);
+
 namespace llvm {
 extern cl::opt<bool> NoPGOWarnMismatch;
 }
@@ -103,6 +109,22 @@ Error Config::addSaveTemps(std::string OutputFileName, 
bool UseInputModulePath,
     // Keep track of the hook provided by the linker, which also needs to run.
     ModuleHookFn LinkerHook = Hook;
     Hook = [=](unsigned Task, const Module &M) {
+      // Check if specific modules (its name contains substring in
+      // PrintModulesList) here to dump save-temps only.
+      llvm::StringMap<bool> PrintModNamesMap;
+      for (const auto &name : PrintModulesList) {
+        PrintModNamesMap[name] = true;
+      }
+      bool ModNameMatch = false;
+      for (auto &entry : PrintModNamesMap) {
+        if (M.getName().contains(entry.first())) {
+          ModNameMatch = true;
+          LLVM_DEBUG(dbgs() << "Match " << M.getName() << "\n");
+          break;
+        }
+      }
+      if (!PrintModNamesMap.empty() && !ModNameMatch)
+        return false;
       // If the linker's hook returned false, we need to pass that result
       // through.
       if (LinkerHook && !LinkerHook(Task, M))

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to