[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