[llvm] [NewPM] Port x86-global-base-reg (PR #180119)

Kyungtak Woo via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 5 21:09:01 PST 2026


https://github.com/kevinwkt created https://github.com/llvm/llvm-project/pull/180119

Had to move X86GlobalBaseRegPass to its own file like in https://github.com/llvm/llvm-project/pull/179864

No test coverage added for now as there are no MIR->MIR tests exercising this pass and we do not have enough ported to run any end to end tests.

This is a redo of https://github.com/llvm/llvm-project/pull/180070

>From 284ff88145139bc37d19a9454a0ee96f32cc0919 Mon Sep 17 00:00:00 2001
From: Kyungtak Woo <kevinwkt at google.com>
Date: Fri, 6 Feb 2026 05:06:21 +0000
Subject: [PATCH] Create refactor and port for x86-global-base-reg

---
 llvm/lib/Target/X86/CMakeLists.txt            |   1 +
 llvm/lib/Target/X86/X86.h                     |   8 +-
 llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp |   3 +-
 llvm/lib/Target/X86/X86GlobalBaseReg.cpp      | 145 ++++++++++++++++++
 llvm/lib/Target/X86/X86InstrInfo.cpp          | 103 -------------
 llvm/lib/Target/X86/X86PassRegistry.def       |   2 +-
 llvm/lib/Target/X86/X86TargetMachine.cpp      |   4 +-
 llvm/test/CodeGen/X86/llc-pipeline-npm.ll     |   4 +
 8 files changed, 161 insertions(+), 109 deletions(-)
 create mode 100644 llvm/lib/Target/X86/X86GlobalBaseReg.cpp

diff --git a/llvm/lib/Target/X86/CMakeLists.txt b/llvm/lib/Target/X86/CMakeLists.txt
index 5cffe98e8dc81..086dd6963286d 100644
--- a/llvm/lib/Target/X86/CMakeLists.txt
+++ b/llvm/lib/Target/X86/CMakeLists.txt
@@ -35,6 +35,7 @@ set(sources
   X86CmovConversion.cpp
   X86CodeGenPassBuilder.cpp
   X86DomainReassignment.cpp
+  X86GlobalBaseReg.cpp
   X86LowerTileCopy.cpp
   X86LowerAMXType.cpp
   X86LowerAMXIntrinsics.cpp
diff --git a/llvm/lib/Target/X86/X86.h b/llvm/lib/Target/X86/X86.h
index 355f0959b4c7d..97d0852cad2e7 100644
--- a/llvm/lib/Target/X86/X86.h
+++ b/llvm/lib/Target/X86/X86.h
@@ -35,7 +35,13 @@ class X86TargetMachine;
 FunctionPass *createX86ISelDag(X86TargetMachine &TM, CodeGenOptLevel OptLevel);
 
 /// This pass initializes a global base register for PIC on x86-32.
-FunctionPass *createX86GlobalBaseRegPass();
+class X86GlobalBaseRegPass : public PassInfoMixin<X86GlobalBaseRegPass> {
+public:
+  PreservedAnalyses run(MachineFunction &MF,
+                        MachineFunctionAnalysisManager &MFAM);
+};
+
+FunctionPass *createX86GlobalBaseRegLegacyPass();
 
 /// This pass combines multiple accesses to local-dynamic TLS variables so that
 /// the TLS base address for the module is only fetched once per execution path
diff --git a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
index d7c9932dd3f0d..9551db2be735d 100644
--- a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
+++ b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
@@ -108,8 +108,7 @@ Error X86CodeGenPassBuilder::addInstSelector(PassManagerWrapper &PMW) const {
     addMachineFunctionPass(X86CleanupLocalDynamicTLSPass(), PMW);
   }
 
-  // TODO(boomanaiden154): Add X86GlobalPassRegPass here once it has been
-  // ported.
+  addMachineFunctionPass(X86GlobalBaseRegPass(), PMW);
   addMachineFunctionPass(X86ArgumentStackSlotPass(), PMW);
   return Error::success();
 }
diff --git a/llvm/lib/Target/X86/X86GlobalBaseReg.cpp b/llvm/lib/Target/X86/X86GlobalBaseReg.cpp
new file mode 100644
index 0000000000000..f758e785e5231
--- /dev/null
+++ b/llvm/lib/Target/X86/X86GlobalBaseReg.cpp
@@ -0,0 +1,145 @@
+//===- X86GlobalBaseReg.cpp - PIC Global Base Register Initialization -----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the pass that initializes the PIC global base register
+// for x86-32.
+//
+//===----------------------------------------------------------------------===//
+
+#include "X86.h"
+#include "X86InstrInfo.h"
+#include "X86MachineFunctionInfo.h"
+#include "X86Subtarget.h"
+#include "X86TargetMachine.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/InitializePasses.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "x86-global-base-reg"
+
+namespace {
+class X86GlobalBaseRegLegacy : public MachineFunctionPass {
+public:
+  static char ID;
+  X86GlobalBaseRegLegacy() : MachineFunctionPass(ID) {}
+
+  bool runOnMachineFunction(MachineFunction &MF) override;
+
+  StringRef getPassName() const override {
+    return "X86 PIC Global Base Reg Initialization";
+  }
+
+  void getAnalysisUsage(AnalysisUsage &AU) const override {
+    AU.setPreservesCFG();
+    MachineFunctionPass::getAnalysisUsage(AU);
+  }
+};
+} // end anonymous namespace
+
+char X86GlobalBaseRegLegacy::ID = 0;
+
+FunctionPass *llvm::createX86GlobalBaseRegLegacyPass() {
+  return new X86GlobalBaseRegLegacy();
+}
+
+static bool initGlobalBaseReg(MachineFunction &MF) {
+  const X86TargetMachine *TM =
+      static_cast<const X86TargetMachine *>(&MF.getTarget());
+  const X86Subtarget &STI = MF.getSubtarget<X86Subtarget>();
+
+  // Only emit a global base reg in PIC mode.
+  if (!TM->isPositionIndependent())
+    return false;
+
+  X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
+  Register GlobalBaseReg = X86FI->getGlobalBaseReg();
+
+  // If we didn't need a GlobalBaseReg, don't insert code.
+  if (GlobalBaseReg == 0)
+    return false;
+
+  // Insert the set of GlobalBaseReg into the first MBB of the function
+  MachineBasicBlock &FirstMBB = MF.front();
+  MachineBasicBlock::iterator MBBI = FirstMBB.begin();
+  DebugLoc DL = FirstMBB.findDebugLoc(MBBI);
+  MachineRegisterInfo &RegInfo = MF.getRegInfo();
+  const X86InstrInfo *TII = STI.getInstrInfo();
+
+  Register PC;
+  if (STI.isPICStyleGOT())
+    PC = RegInfo.createVirtualRegister(&X86::GR32RegClass);
+  else
+    PC = GlobalBaseReg;
+
+  if (STI.is64Bit()) {
+    if (TM->getCodeModel() == CodeModel::Large) {
+      // In the large code model, we are aiming for this code, though the
+      // register allocation may vary:
+      //   leaq .LN$pb(%rip), %rax
+      //   movq $_GLOBAL_OFFSET_TABLE_ - .LN$pb, %rcx
+      //   addq %rcx, %rax
+      // RAX now holds address of _GLOBAL_OFFSET_TABLE_.
+      Register PBReg = RegInfo.createVirtualRegister(&X86::GR64RegClass);
+      Register GOTReg = RegInfo.createVirtualRegister(&X86::GR64RegClass);
+      BuildMI(FirstMBB, MBBI, DL, TII->get(X86::LEA64r), PBReg)
+          .addReg(X86::RIP)
+          .addImm(0)
+          .addReg(0)
+          .addSym(MF.getPICBaseSymbol())
+          .addReg(0);
+      std::prev(MBBI)->setPreInstrSymbol(MF, MF.getPICBaseSymbol());
+      BuildMI(FirstMBB, MBBI, DL, TII->get(X86::MOV64ri), GOTReg)
+          .addExternalSymbol("_GLOBAL_OFFSET_TABLE_",
+                             X86II::MO_PIC_BASE_OFFSET);
+      BuildMI(FirstMBB, MBBI, DL, TII->get(X86::ADD64rr), PC)
+          .addReg(PBReg, RegState::Kill)
+          .addReg(GOTReg, RegState::Kill);
+    } else {
+      // In other code models, use a RIP-relative LEA to materialize the
+      // GOT.
+      BuildMI(FirstMBB, MBBI, DL, TII->get(X86::LEA64r), PC)
+          .addReg(X86::RIP)
+          .addImm(0)
+          .addReg(0)
+          .addExternalSymbol("_GLOBAL_OFFSET_TABLE_")
+          .addReg(0);
+    }
+  } else {
+    // Operand of MovePCtoStack is completely ignored by asm printer. It's
+    // only used in JIT code emission as displacement to pc.
+    BuildMI(FirstMBB, MBBI, DL, TII->get(X86::MOVPC32r), PC).addImm(0);
+
+    // If we're using vanilla 'GOT' PIC style, we should use relative
+    // addressing not to pc, but to _GLOBAL_OFFSET_TABLE_ external.
+    if (STI.isPICStyleGOT()) {
+      // Generate addl $__GLOBAL_OFFSET_TABLE_ + [.-piclabel],
+      // %some_register
+      BuildMI(FirstMBB, MBBI, DL, TII->get(X86::ADD32ri), GlobalBaseReg)
+          .addReg(PC)
+          .addExternalSymbol("_GLOBAL_OFFSET_TABLE_",
+                             X86II::MO_GOT_ABSOLUTE_ADDRESS);
+    }
+  }
+
+  return true;
+}
+
+bool X86GlobalBaseRegLegacy::runOnMachineFunction(MachineFunction &MF) {
+  return initGlobalBaseReg(MF);
+}
+
+PreservedAnalyses
+X86GlobalBaseRegPass::run(MachineFunction &MF,
+                          MachineFunctionAnalysisManager &MFAM) {
+  return initGlobalBaseReg(MF) ? getMachineFunctionPassPreservedAnalyses()
+                                     .preserveSet<CFGAnalyses>()
+                               : PreservedAnalyses::all();
+}
diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp
index d85d9b600c2d6..2479a8dccfb00 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.cpp
+++ b/llvm/lib/Target/X86/X86InstrInfo.cpp
@@ -10404,109 +10404,6 @@ X86InstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
   return ArrayRef(TargetFlags);
 }
 
-namespace {
-/// Create Global Base Reg pass. This initializes the PIC
-/// global base register for x86-32.
-struct CGBR : public MachineFunctionPass {
-  static char ID;
-  CGBR() : MachineFunctionPass(ID) {}
-
-  bool runOnMachineFunction(MachineFunction &MF) override {
-    const X86TargetMachine *TM =
-        static_cast<const X86TargetMachine *>(&MF.getTarget());
-    const X86Subtarget &STI = MF.getSubtarget<X86Subtarget>();
-
-    // Only emit a global base reg in PIC mode.
-    if (!TM->isPositionIndependent())
-      return false;
-
-    X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
-    Register GlobalBaseReg = X86FI->getGlobalBaseReg();
-
-    // If we didn't need a GlobalBaseReg, don't insert code.
-    if (GlobalBaseReg == 0)
-      return false;
-
-    // Insert the set of GlobalBaseReg into the first MBB of the function
-    MachineBasicBlock &FirstMBB = MF.front();
-    MachineBasicBlock::iterator MBBI = FirstMBB.begin();
-    DebugLoc DL = FirstMBB.findDebugLoc(MBBI);
-    MachineRegisterInfo &RegInfo = MF.getRegInfo();
-    const X86InstrInfo *TII = STI.getInstrInfo();
-
-    Register PC;
-    if (STI.isPICStyleGOT())
-      PC = RegInfo.createVirtualRegister(&X86::GR32RegClass);
-    else
-      PC = GlobalBaseReg;
-
-    if (STI.is64Bit()) {
-      if (TM->getCodeModel() == CodeModel::Large) {
-        // In the large code model, we are aiming for this code, though the
-        // register allocation may vary:
-        //   leaq .LN$pb(%rip), %rax
-        //   movq $_GLOBAL_OFFSET_TABLE_ - .LN$pb, %rcx
-        //   addq %rcx, %rax
-        // RAX now holds address of _GLOBAL_OFFSET_TABLE_.
-        Register PBReg = RegInfo.createVirtualRegister(&X86::GR64RegClass);
-        Register GOTReg = RegInfo.createVirtualRegister(&X86::GR64RegClass);
-        BuildMI(FirstMBB, MBBI, DL, TII->get(X86::LEA64r), PBReg)
-            .addReg(X86::RIP)
-            .addImm(0)
-            .addReg(0)
-            .addSym(MF.getPICBaseSymbol())
-            .addReg(0);
-        std::prev(MBBI)->setPreInstrSymbol(MF, MF.getPICBaseSymbol());
-        BuildMI(FirstMBB, MBBI, DL, TII->get(X86::MOV64ri), GOTReg)
-            .addExternalSymbol("_GLOBAL_OFFSET_TABLE_",
-                               X86II::MO_PIC_BASE_OFFSET);
-        BuildMI(FirstMBB, MBBI, DL, TII->get(X86::ADD64rr), PC)
-            .addReg(PBReg, RegState::Kill)
-            .addReg(GOTReg, RegState::Kill);
-      } else {
-        // In other code models, use a RIP-relative LEA to materialize the
-        // GOT.
-        BuildMI(FirstMBB, MBBI, DL, TII->get(X86::LEA64r), PC)
-            .addReg(X86::RIP)
-            .addImm(0)
-            .addReg(0)
-            .addExternalSymbol("_GLOBAL_OFFSET_TABLE_")
-            .addReg(0);
-      }
-    } else {
-      // Operand of MovePCtoStack is completely ignored by asm printer. It's
-      // only used in JIT code emission as displacement to pc.
-      BuildMI(FirstMBB, MBBI, DL, TII->get(X86::MOVPC32r), PC).addImm(0);
-
-      // If we're using vanilla 'GOT' PIC style, we should use relative
-      // addressing not to pc, but to _GLOBAL_OFFSET_TABLE_ external.
-      if (STI.isPICStyleGOT()) {
-        // Generate addl $__GLOBAL_OFFSET_TABLE_ + [.-piclabel],
-        // %some_register
-        BuildMI(FirstMBB, MBBI, DL, TII->get(X86::ADD32ri), GlobalBaseReg)
-            .addReg(PC)
-            .addExternalSymbol("_GLOBAL_OFFSET_TABLE_",
-                               X86II::MO_GOT_ABSOLUTE_ADDRESS);
-      }
-    }
-
-    return true;
-  }
-
-  StringRef getPassName() const override {
-    return "X86 PIC Global Base Reg Initialization";
-  }
-
-  void getAnalysisUsage(AnalysisUsage &AU) const override {
-    AU.setPreservesCFG();
-    MachineFunctionPass::getAnalysisUsage(AU);
-  }
-};
-} // namespace
-
-char CGBR::ID = 0;
-FunctionPass *llvm::createX86GlobalBaseRegPass() { return new CGBR(); }
-
 /// Constants defining how certain sequences should be outlined.
 ///
 /// \p MachineOutlinerDefault implies that the function is called with a call
diff --git a/llvm/lib/Target/X86/X86PassRegistry.def b/llvm/lib/Target/X86/X86PassRegistry.def
index 2f9b880249465..7fbb0771fac0e 100644
--- a/llvm/lib/Target/X86/X86PassRegistry.def
+++ b/llvm/lib/Target/X86/X86PassRegistry.def
@@ -48,6 +48,7 @@ MACHINE_FUNCTION_PASS("x86-fixup-setcc", X86FixupSetCCPass())
 MACHINE_FUNCTION_PASS("x86-fixup-vector-constants", X86FixupVectorConstantsPass())
 MACHINE_FUNCTION_PASS("x86-flags-copy-lowering", X86FlagsCopyLoweringPass())
 MACHINE_FUNCTION_PASS("x86-fp-stackifier", X86FPStackifierPass())
+MACHINE_FUNCTION_PASS("x86-global-base-reg", X86GlobalBaseRegPass())
 MACHINE_FUNCTION_PASS("x86-isel", X86ISelDAGToDAGPass(*this))
 MACHINE_FUNCTION_PASS("x86-lower-tile-copy", X86LowerTileCopyPass())
 MACHINE_FUNCTION_PASS("x86-lvi-load", X86LoadValueInjectionLoadHardeningPass())
@@ -66,7 +67,6 @@ MACHINE_FUNCTION_PASS("x86-wineh-unwindv2", X86WinEHUnwindV2Pass())
 #define DUMMY_MACHINE_FUNCTION_PASS(NAME, PASS_NAME)
 #endif
 DUMMY_MACHINE_FUNCTION_PASS("x86-execution-domain-fix", X86ExecutionDomainFix())
-DUMMY_MACHINE_FUNCTION_PASS("x86-global-base-reg", X86GlobalBaseRegPass())
 DUMMY_MACHINE_FUNCTION_PASS("x86-indirect-branch-tracking", X86IndirectBranchTrackingPass())
 DUMMY_MACHINE_FUNCTION_PASS("x86-indirect-thunks", X86IndirectThunks())
 DUMMY_MACHINE_FUNCTION_PASS("x86-insert-x87-wait", X86InsertX87WaitPass())
diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp
index 48fc38a1f11f5..64b305ccd4469 100644
--- a/llvm/lib/Target/X86/X86TargetMachine.cpp
+++ b/llvm/lib/Target/X86/X86TargetMachine.cpp
@@ -462,7 +462,7 @@ bool X86PassConfig::addInstSelector() {
       getOptLevel() != CodeGenOptLevel::None)
     addPass(createCleanupLocalDynamicTLSLegacyPass());
 
-  addPass(createX86GlobalBaseRegPass());
+  addPass(createX86GlobalBaseRegLegacyPass());
   addPass(createX86ArgumentStackSlotLegacyPass());
   return false;
 }
@@ -492,7 +492,7 @@ bool X86PassConfig::addGlobalInstructionSelect() {
   addPass(new InstructionSelect(getOptLevel()));
   // Add GlobalBaseReg in case there is no SelectionDAG passes afterwards
   if (isGlobalISelAbortEnabled())
-    addPass(createX86GlobalBaseRegPass());
+    addPass(createX86GlobalBaseRegLegacyPass());
   return false;
 }
 
diff --git a/llvm/test/CodeGen/X86/llc-pipeline-npm.ll b/llvm/test/CodeGen/X86/llc-pipeline-npm.ll
index a8d29b1affbbd..aab5203627a49 100644
--- a/llvm/test/CodeGen/X86/llc-pipeline-npm.ll
+++ b/llvm/test/CodeGen/X86/llc-pipeline-npm.ll
@@ -34,6 +34,7 @@
 ; O0-NEXT: stack-protector
 ; O0-NEXT: verify)
 ; O0-NEXT: function(machine-function(x86-isel
+; O0-NEXT: x86-global-base-reg
 ; O0-NEXT: x86-argument-stack-slot
 ; O0-NEXT: finalize-isel
 ; O0-NEXT: localstackalloc
@@ -104,6 +105,7 @@
 ; O2-NEXT: verify)
 ; O2-NEXT: function(machine-function(x86-isel
 ; O2-NEXT: x86-cleanup-local-dynamic-tls
+; O2-NEXT: x86-global-base-reg
 ; O2-NEXT: x86-argument-stack-slot
 ; O2-NEXT: finalize-isel
 ; O2-NEXT: early-tailduplication
@@ -207,6 +209,7 @@
 ; O0-WINDOWS-NEXT: stack-protector
 ; O0-WINDOWS-NEXT: verify)
 ; O0-WINDOWS-NEXT: function(machine-function(x86-isel
+; O0-WINDOWS-NEXT: x86-global-base-reg
 ; O0-WINDOWS-NEXT: x86-argument-stack-slot
 ; O0-WINDOWS-NEXT: finalize-isel
 ; O0-WINDOWS-NEXT: localstackalloc
@@ -280,6 +283,7 @@
 ; O3-WINDOWS-NEXT: stack-protector
 ; O3-WINDOWS-NEXT: verify)
 ; O3-WINDOWS-NEXT: function(machine-function(x86-isel
+; O3-WINDOWS-NEXT: x86-global-base-reg
 ; O3-WINDOWS-NEXT: x86-argument-stack-slot
 ; O3-WINDOWS-NEXT: finalize-isel
 ; O3-WINDOWS-NEXT: early-tailduplication



More information about the llvm-commits mailing list