[llvm] [GlobalMerge] Convert GlobalMerge to a ModulePass (PR #160703)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 25 06:10:54 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-powerpc

Author: Alex Bradbury (asb)

<details>
<summary>Changes</summary>

GlobalMerge is written as a FunctionPass, yet does all of its work in initialisation. This might technically mean that it doesn't break the invariant that function passes shouldn't add/remove globals, but it's very surprising and means that attempts in e.g. the AArch64 backend to schedule global merging after a constant promotion pass doesn't actually work as expected. This issue was previously noted in <https://github.com/llvm/llvm-project/pull/89708#issuecomment-2076954661>.

Going through commit history I was unable to find a justification for why it is written this way, so I will flag to reviewers that it's possible I'm missing something.

---
Full diff: https://github.com/llvm/llvm-project/pull/160703.diff


6 Files Affected:

- (modified) llvm/lib/CodeGen/GlobalMerge.cpp (+4-6) 
- (modified) llvm/test/CodeGen/AArch64/O3-pipeline.ll (+1-1) 
- (modified) llvm/test/CodeGen/ARM/O3-pipeline.ll (+6-4) 
- (modified) llvm/test/CodeGen/PowerPC/O3-pipeline.ll (+3-1) 
- (modified) llvm/test/CodeGen/PowerPC/mergeable-string-pool-exceptions.ll (+3-2) 
- (modified) llvm/test/CodeGen/RISCV/O3-pipeline.ll (+1-1) 


``````````diff
diff --git a/llvm/lib/CodeGen/GlobalMerge.cpp b/llvm/lib/CodeGen/GlobalMerge.cpp
index e58d7e344c28b..251bbcb90089f 100644
--- a/llvm/lib/CodeGen/GlobalMerge.cpp
+++ b/llvm/lib/CodeGen/GlobalMerge.cpp
@@ -189,14 +189,14 @@ class GlobalMergeImpl {
   bool run(Module &M);
 };
 
-class GlobalMerge : public FunctionPass {
+class GlobalMerge : public ModulePass {
   const TargetMachine *TM = nullptr;
   GlobalMergeOptions Opt;
 
 public:
   static char ID; // Pass identification, replacement for typeid.
 
-  explicit GlobalMerge() : FunctionPass(ID) {
+  explicit GlobalMerge() : ModulePass(ID) {
     Opt.MaxOffset = GlobalMergeMaxOffset;
     Opt.MergeConstantGlobals = EnableGlobalMergeOnConst;
     Opt.MergeConstAggressive = GlobalMergeAllConst;
@@ -206,7 +206,7 @@ class GlobalMerge : public FunctionPass {
   explicit GlobalMerge(const TargetMachine *TM, unsigned MaximalOffset,
                        bool OnlyOptimizeForSize, bool MergeExternalGlobals,
                        bool MergeConstantGlobals, bool MergeConstAggressive)
-      : FunctionPass(ID), TM(TM) {
+      : ModulePass(ID), TM(TM) {
     Opt.MaxOffset = MaximalOffset;
     Opt.SizeOnly = OnlyOptimizeForSize;
     Opt.MergeExternal = MergeExternalGlobals;
@@ -215,7 +215,7 @@ class GlobalMerge : public FunctionPass {
     initializeGlobalMergePass(*PassRegistry::getPassRegistry());
   }
 
-  bool doInitialization(Module &M) override {
+  bool runOnModule(Module &M) override {
     auto GetSmallDataLimit = [](Module &M) -> std::optional<uint64_t> {
       Metadata *SDL = M.getModuleFlag("SmallDataLimit");
       if (!SDL)
@@ -232,13 +232,11 @@ class GlobalMerge : public FunctionPass {
     GlobalMergeImpl P(TM, Opt);
     return P.run(M);
   }
-  bool runOnFunction(Function &F) override { return false; }
 
   StringRef getPassName() const override { return "Merge internal globals"; }
 
   void getAnalysisUsage(AnalysisUsage &AU) const override {
     AU.setPreservesCFG();
-    FunctionPass::getAnalysisUsage(AU);
   }
 };
 
diff --git a/llvm/test/CodeGen/AArch64/O3-pipeline.ll b/llvm/test/CodeGen/AArch64/O3-pipeline.ll
index e1481667a4ab7..9353fdfb8d09b 100644
--- a/llvm/test/CodeGen/AArch64/O3-pipeline.ll
+++ b/llvm/test/CodeGen/AArch64/O3-pipeline.ll
@@ -105,8 +105,8 @@
 ; CHECK-NEXT:     AArch64 Promote Constant
 ; CHECK-NEXT:       FunctionPass Manager
 ; CHECK-NEXT:         Dominator Tree Construction
+; CHECK-NEXT:     Merge internal globals
 ; CHECK-NEXT:     FunctionPass Manager
-; CHECK-NEXT:       Merge internal globals
 ; CHECK-NEXT:       Dominator Tree Construction
 ; CHECK-NEXT:       Basic Alias Analysis (stateless AA impl)
 ; CHECK-NEXT:       Function Alias Analysis Results
diff --git a/llvm/test/CodeGen/ARM/O3-pipeline.ll b/llvm/test/CodeGen/ARM/O3-pipeline.ll
index 9601a2e4e3d12..b7d47c6320a55 100644
--- a/llvm/test/CodeGen/ARM/O3-pipeline.ll
+++ b/llvm/test/CodeGen/ARM/O3-pipeline.ll
@@ -55,7 +55,9 @@
 ; CHECK-NEXT:      CodeGen Prepare
 ; CHECK-NEXT:      Dominator Tree Construction
 ; CHECK-NEXT:      Exception handling preparation
-; CHECK-NEXT:      Merge internal globals
+; CHECK-NEXT:    Merge internal globals
+; CHECK-NEXT:    FunctionPass Manager
+; CHECK-NEXT:      Dominator Tree Construction
 ; CHECK-NEXT:      Natural Loop Information
 ; CHECK-NEXT:      Scalar Evolution Analysis
 ; CHECK-NEXT:      Lazy Branch Probability Analysis
@@ -64,8 +66,8 @@
 ; CHECK-NEXT:      Hardware Loop Insertion
 ; CHECK-NEXT:      Loop Pass Manager
 ; CHECK-NEXT:        Transform predicated vector loops to use MVE tail predication
-; CHECK-NEXT:      A No-Op Barrier Pass
-; CHECK-NEXT:      FunctionPass Manager
+; CHECK-NEXT:    A No-Op Barrier Pass
+; CHECK-NEXT:    FunctionPass Manager
 ; CHECK-NEXT:      Dominator Tree Construction
 ; CHECK-NEXT:      Basic Alias Analysis (stateless AA impl)
 ; CHECK-NEXT:      Function Alias Analysis Results
@@ -111,7 +113,7 @@
 ; CHECK-NEXT:      Modulo Software Pipelining
 ; CHECK-NEXT:      MachineDominator Tree Construction
 ; CHECK-NEXT:      Machine Natural Loop Construction
-; CHECK-NEXT:      MVE TailPred and VPT Optimisation Pass
+; CHECK-NEXT:      ARM MVE TailPred and VPT Optimisation Pass
 ; CHECK-NEXT:      ARM MLA / MLS expansion pass
 ; CHECK-NEXT:      MachineDominator Tree Construction
 ; CHECK-NEXT:      ARM pre- register allocation load / store optimization pass
diff --git a/llvm/test/CodeGen/PowerPC/O3-pipeline.ll b/llvm/test/CodeGen/PowerPC/O3-pipeline.ll
index 7cbb1a1c98873..be044daa1fe2e 100644
--- a/llvm/test/CodeGen/PowerPC/O3-pipeline.ll
+++ b/llvm/test/CodeGen/PowerPC/O3-pipeline.ll
@@ -72,7 +72,9 @@
 ; CHECK-NEXT:       CodeGen Prepare
 ; CHECK-NEXT:       Dominator Tree Construction
 ; CHECK-NEXT:       Exception handling preparation
-; CHECK-NEXT:       Merge internal globals
+; CHECK-NEXT:     Merge internal globals
+; CHECK-NEXT:     FunctionPass Manager
+; CHECK-NEXT:       Dominator Tree Construction
 ; CHECK-NEXT:       Natural Loop Information
 ; CHECK-NEXT:       Scalar Evolution Analysis
 ; CHECK-NEXT:       Prepare loop for ppc preferred instruction forms
diff --git a/llvm/test/CodeGen/PowerPC/mergeable-string-pool-exceptions.ll b/llvm/test/CodeGen/PowerPC/mergeable-string-pool-exceptions.ll
index 10179bba136f9..ea8e75ca46dd7 100644
--- a/llvm/test/CodeGen/PowerPC/mergeable-string-pool-exceptions.ll
+++ b/llvm/test/CodeGen/PowerPC/mergeable-string-pool-exceptions.ll
@@ -15,8 +15,9 @@ define ptr @test1() personality ptr @__gnu_objc_personality_v0 {
 ; CHECK-NEXT:    std 0, 48(1)
 ; CHECK-NEXT:    .cfi_def_cfa_offset 32
 ; CHECK-NEXT:    .cfi_offset lr, 16
-; CHECK-NEXT:    addis 3, 2, .Ldummy at toc@ha
-; CHECK-NEXT:    addi 3, 3, .Ldummy at toc@l
+; CHECK-NEXT:    addis 3, 2, .L_MergedGlobals at toc@ha
+; CHECK-NEXT:    addi 3, 3, .L_MergedGlobals at toc@l
+; CHECK-NEXT:    addi 3, 3, 4
 ; CHECK-NEXT:    bl foo
 ; CHECK-NEXT:    nop
   invoke void @foo(ptr @dummy)
diff --git a/llvm/test/CodeGen/RISCV/O3-pipeline.ll b/llvm/test/CodeGen/RISCV/O3-pipeline.ll
index ea08061221fd4..0e42ad319b8dd 100644
--- a/llvm/test/CodeGen/RISCV/O3-pipeline.ll
+++ b/llvm/test/CodeGen/RISCV/O3-pipeline.ll
@@ -76,8 +76,8 @@
 ; CHECK-NEXT:       Dominator Tree Construction
 ; CHECK-NEXT:       Exception handling preparation
 ; CHECK-NEXT:     A No-Op Barrier Pass
+; CHECK-NEXT:     Merge internal globals
 ; CHECK-NEXT:     FunctionPass Manager
-; CHECK-NEXT:       Merge internal globals
 ; CHECK-NEXT:       Dominator Tree Construction
 ; CHECK-NEXT:       Basic Alias Analysis (stateless AA impl)
 ; CHECK-NEXT:       Function Alias Analysis Results

``````````

</details>


https://github.com/llvm/llvm-project/pull/160703


More information about the llvm-commits mailing list