[llvm] [X86][GlobalISel] Support globals in pic mode (PR #170038)

Evgenii Kudriashov via llvm-commits llvm-commits at lists.llvm.org
Fri May 8 01:53:17 PDT 2026


https://github.com/e-kud updated https://github.com/llvm/llvm-project/pull/170038

>From ecf08961e61d5aabbfe0493318f1123c2db8cb27 Mon Sep 17 00:00:00 2001
From: Evgenii Kudriashov <evgenii.kudriashov at intel.com>
Date: Sun, 30 Nov 2025 06:32:56 -0800
Subject: [PATCH 01/10] [X86][GlobalISel] Support globals in pic mode

Introduce G_TARGET_GLOBAL_VALUE. It is similar to TargetGlobalAddress in
SDAG. Essentially it is required to make legalization possible when a
load from stub is required to obtain a poitner to the global value.

It makes possible to use GlobalISel as a solo selector with simple
programs on X86.

Also added a missing check on X86SelectAddress failure.
---
 llvm/docs/GlobalISel/GenericOpcode.rst        | 10 +++
 .../CodeGen/GlobalISel/MachineIRBuilder.h     | 14 +++
 llvm/include/llvm/Support/TargetOpcodes.def   |  5 ++
 llvm/include/llvm/Target/GenericOpcodes.td    |  6 ++
 .../CodeGen/GlobalISel/MachineIRBuilder.cpp   | 14 +++
 .../X86/GISel/X86InstructionSelector.cpp      | 13 ++-
 .../lib/Target/X86/GISel/X86LegalizerInfo.cpp | 29 ++++++-
 llvm/lib/Target/X86/GISel/X86LegalizerInfo.h  |  3 +
 .../Inputs/reference_x86_vocab_print.txt      |  1 +
 .../reference_x86_vocab_wo=0.5_print.txt      |  1 +
 llvm/test/CodeGen/X86/GlobalISel/GV.ll        | 85 ++++++++++++++-----
 .../X86/GlobalISel/x86_64-legalize-GV.mir     |  6 +-
 .../match-table-cxx.td                        |  2 +-
 .../GlobalISelEmitter/GlobalISelEmitter.td    |  2 +-
 14 files changed, 160 insertions(+), 31 deletions(-)

diff --git a/llvm/docs/GlobalISel/GenericOpcode.rst b/llvm/docs/GlobalISel/GenericOpcode.rst
index 329d9d13ebddd..9c0654897703d 100644
--- a/llvm/docs/GlobalISel/GenericOpcode.rst
+++ b/llvm/docs/GlobalISel/GenericOpcode.rst
@@ -60,6 +60,16 @@ The address of a global value.
 
   %0(p0) = G_GLOBAL_VALUE @var_local
 
+G_TARGET_GLOBAL_VALUE
+^^^^^^^^^^^^^^^^^^^^^
+
+Like G_GLOBAL_VALUE, but GlobalISel does no folding or anything else with this
+node, and this is valid in the target-specific selection.
+
+.. code-block:: none
+
+  %0(p0) = G_TARGET_GLOBAL_VALUE @var_global
+
 G_PTRAUTH_GLOBAL_VALUE
 ^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index 5f3f1d386569c..59a1ee4bf8210 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -496,6 +496,20 @@ class LLVM_ABI MachineIRBuilder {
   /// \return a MachineInstrBuilder for the newly created instruction.
   MachineInstrBuilder buildGlobalValue(const DstOp &Res, const GlobalValue *GV);
 
+  /// Build and insert \p Res = G_TARGET_GLOBAL_VALUE \p GV
+  ///
+  /// G_TARGET_GLOBAL_VALUE materializes the address of the specified global
+  /// into \p Res. It is a version of G_GLOBAL_VALUE for target specific
+  /// legalization of global addresses.
+  ///
+  /// \pre setBasicBlock or setMI must have been called.
+  /// \pre \p Res must be a generic virtual register with pointer type
+  ///      in the same address space as \p GV.
+  ///
+  /// \return a MachineInstrBuilder for the newly created instruction.
+  MachineInstrBuilder buildTargetGlobalValue(const DstOp &Res,
+                                             const GlobalValue *GV);
+
   /// Build and insert \p Res = G_CONSTANT_POOL \p Idx
   ///
   /// G_CONSTANT_POOL materializes the address of an object in the constant
diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def
index 341fc5e50b33c..c7afd1bdd1024 100644
--- a/llvm/include/llvm/Support/TargetOpcodes.def
+++ b/llvm/include/llvm/Support/TargetOpcodes.def
@@ -322,6 +322,11 @@ HANDLE_TARGET_OPCODE(G_FRAME_INDEX)
 /// Generic reference to global value.
 HANDLE_TARGET_OPCODE(G_GLOBAL_VALUE)
 
+/// Generic target specific reference to a global value (typically for
+/// distinguishing already legalized and not yet legalized refrence to a global
+/// value).
+HANDLE_TARGET_OPCODE(G_TARGET_GLOBAL_VALUE)
+
 /// Generic ptrauth-signed reference to global value.
 HANDLE_TARGET_OPCODE(G_PTRAUTH_GLOBAL_VALUE)
 
diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td
index 1b65b8b73527d..08df4e48ec6e8 100644
--- a/llvm/include/llvm/Target/GenericOpcodes.td
+++ b/llvm/include/llvm/Target/GenericOpcodes.td
@@ -131,6 +131,12 @@ def G_GLOBAL_VALUE : GenericInstruction {
   let hasSideEffects = false;
 }
 
+def G_TARGET_GLOBAL_VALUE : GenericInstruction {
+  let OutOperandList = (outs ptype0:$dst);
+  let InOperandList = (ins unknown:$src);
+  let hasSideEffects = false;
+}
+
 def G_PTRAUTH_GLOBAL_VALUE : GenericInstruction {
   let OutOperandList = (outs type0:$dst);
   let InOperandList = (ins unknown:$addr, i32imm:$key, type1:$addrdisc, i64imm:$disc);
diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index 3906b311addf0..08bda5fbce223 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -170,6 +170,20 @@ MachineInstrBuilder MachineIRBuilder::buildGlobalValue(const DstOp &Res,
   return MIB;
 }
 
+MachineInstrBuilder
+MachineIRBuilder::buildTargetGlobalValue(const DstOp &Res,
+                                         const GlobalValue *GV) {
+  assert(Res.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
+  assert(Res.getLLTTy(*getMRI()).getAddressSpace() ==
+             GV->getType()->getAddressSpace() &&
+         "address space mismatch");
+
+  auto MIB = buildInstr(TargetOpcode::G_TARGET_GLOBAL_VALUE);
+  Res.addDefToMIB(*getMRI(), MIB);
+  MIB.addGlobalAddress(GV);
+  return MIB;
+}
+
 MachineInstrBuilder MachineIRBuilder::buildConstantPool(const DstOp &Res,
                                                         unsigned Idx) {
   assert(Res.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
diff --git a/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp b/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
index f499e6f9d0799..675284cc58f52 100644
--- a/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
+++ b/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
@@ -627,7 +627,8 @@ static bool X86SelectAddress(MachineInstr &I, const X86TargetMachine &TM,
     }
     break;
   }
-  case TargetOpcode::G_GLOBAL_VALUE: {
+  case TargetOpcode::G_GLOBAL_VALUE:
+  case TargetOpcode::G_TARGET_GLOBAL_VALUE: {
     auto GV = I.getOperand(1).getGlobal();
     if (GV->isThreadLocal()) {
       return false; // TODO: we don't support TLS yet.
@@ -638,15 +639,12 @@ static bool X86SelectAddress(MachineInstr &I, const X86TargetMachine &TM,
     AM.GV = GV;
     AM.GVOpFlags = STI.classifyGlobalReference(GV);
 
-    // TODO: The ABI requires an extra load. not supported yet.
-    if (isGlobalStubReference(AM.GVOpFlags))
-      return false;
-
     // TODO: This reference is relative to the pic base. not supported yet.
     if (isGlobalRelativeToPICBase(AM.GVOpFlags))
       return false;
 
-    if (STI.isPICStyleRIPRel()) {
+    if (STI.isPICStyleRIPRel() || AM.GVOpFlags == X86II::MO_GOTPCREL ||
+        AM.GVOpFlags == X86II::MO_GOTPCREL_NORELAX) {
       // Use rip-relative addressing.
       assert(AM.Base.Reg == 0 && AM.IndexReg == 0 &&
              "RIP-relative addresses can't have additional register operands");
@@ -1972,7 +1970,8 @@ X86InstructionSelector::selectAddr(MachineOperand &Root) const {
   MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
   MachineInstr *Ptr = MRI.getVRegDef(Root.getReg());
   X86AddressMode AM;
-  X86SelectAddress(*Ptr, TM, MRI, STI, AM);
+  if (!X86SelectAddress(*Ptr, TM, MRI, STI, AM))
+    return std::nullopt;
 
   if (AM.IndexReg)
     return std::nullopt;
diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
index e792b1bce3c5c..dea0c70ec7b41 100644
--- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
+++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
@@ -330,7 +330,10 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
       .widenScalarToNextPow2(1, /*Min*/ 32)
       .clampScalar(1, s32, sMaxScalar);
 
-  getActionDefinitionsBuilder({G_FRAME_INDEX, G_GLOBAL_VALUE}).legalFor({p0});
+  getActionDefinitionsBuilder({G_FRAME_INDEX, G_TARGET_GLOBAL_VALUE})
+      .legalFor({p0});
+
+  getActionDefinitionsBuilder(G_GLOBAL_VALUE).customFor({p0});
 
   // load/store: add more corner cases
   for (unsigned Op : {G_LOAD, G_STORE}) {
@@ -623,6 +626,8 @@ bool X86LegalizerInfo::legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI,
     return legalizeGETROUNDING(MI, MRI, Helper);
   case TargetOpcode::G_SET_ROUNDING:
     return legalizeSETROUNDING(MI, MRI, Helper);
+  case TargetOpcode::G_GLOBAL_VALUE:
+    return legalizeGLOBAL_VALUE(MI, MRI, Helper);
   }
   llvm_unreachable("expected switch to return");
 }
@@ -993,6 +998,28 @@ bool X86LegalizerInfo::legalizeSETROUNDING(MachineInstr &MI,
   return true;
 }
 
+bool X86LegalizerInfo::legalizeGLOBAL_VALUE(MachineInstr &MI,
+                                            MachineRegisterInfo &MRI,
+                                            LegalizerHelper &Helper) const {
+  auto GV = MI.getOperand(1).getGlobal();
+  Register Dst = MI.getOperand(0).getReg();
+  LLT DstTy = MRI.getType(Dst);
+  auto GVOpFlags = Subtarget.classifyGlobalReference(GV);
+
+  if (isGlobalStubReference(GVOpFlags)) {
+    MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
+    MachineFunction &MF = MIRBuilder.getMF();
+
+    auto StubAddr = MIRBuilder.buildTargetGlobalValue(DstTy, GV);
+    auto MMO = MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF),
+                                       MachineMemOperand::MOLoad, DstTy,
+                                       Align(DstTy.getSizeInBytes()));
+    MIRBuilder.buildLoad(Dst, StubAddr, *MMO);
+    MI.eraseFromParent();
+  }
+  return true;
+}
+
 bool X86LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
                                          MachineInstr &MI) const {
   return true;
diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
index 09c727c8e8685..58be7bb7d02b8 100644
--- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
+++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
@@ -60,6 +60,9 @@ class X86LegalizerInfo : public LegalizerInfo {
 
   bool legalizeSETROUNDING(MachineInstr &MI, MachineRegisterInfo &MRI,
                            LegalizerHelper &Helper) const;
+
+  bool legalizeGLOBAL_VALUE(MachineInstr &MI, MachineRegisterInfo &MRI,
+                            LegalizerHelper &Helper) const;
 };
 } // namespace llvm
 #endif
diff --git a/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_print.txt b/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_print.txt
index 74ef1e608d4ba..6d8d0f3ce89ce 100644
--- a/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_print.txt
+++ b/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_print.txt
@@ -533,6 +533,7 @@ Key: G_STRICT_FREM:  [ 0.00  0.00 ]
 Key: G_STRICT_FSQRT:  [ 0.00  0.00 ]
 Key: G_STRICT_FSUB:  [ 0.00  0.00 ]
 Key: G_SUB:  [ 0.00  0.00 ]
+Key: G_TARGET_GLOBAL_VALUE:  [ 0.00  0.00 ]
 Key: G_TRAP:  [ 0.00  0.00 ]
 Key: G_TRUNC:  [ 0.00  0.00 ]
 Key: G_TRUNC_SSAT_S:  [ 0.00  0.00 ]
diff --git a/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_wo=0.5_print.txt b/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_wo=0.5_print.txt
index 1ba4f13e69c92..69b7c4926bc79 100644
--- a/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_wo=0.5_print.txt
+++ b/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_wo=0.5_print.txt
@@ -533,6 +533,7 @@ Key: G_STRICT_FREM:  [ 0.00  0.00 ]
 Key: G_STRICT_FSQRT:  [ 0.00  0.00 ]
 Key: G_STRICT_FSUB:  [ 0.00  0.00 ]
 Key: G_SUB:  [ 0.00  0.00 ]
+Key: G_TARGET_GLOBAL_VALUE:  [ 0.00  0.00 ]
 Key: G_TRAP:  [ 0.00  0.00 ]
 Key: G_TRUNC:  [ 0.00  0.00 ]
 Key: G_TRUNC_SSAT_S:  [ 0.00  0.00 ]
diff --git a/llvm/test/CodeGen/X86/GlobalISel/GV.ll b/llvm/test/CodeGen/X86/GlobalISel/GV.ll
index c161a32fd6b95..aa64126edc4af 100644
--- a/llvm/test/CodeGen/X86/GlobalISel/GV.ll
+++ b/llvm/test/CodeGen/X86/GlobalISel/GV.ll
@@ -1,13 +1,13 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc -mtriple=x86_64-linux-gnu    -global-isel -verify-machineinstrs                       < %s -o - | FileCheck %s --check-prefix=X64
 ; RUN: llc -mtriple=x86_64-apple-darwin -global-isel -verify-machineinstrs -relocation-model=pic < %s -o - | FileCheck %s --check-prefix=X64_DARWIN_PIC
-; RUN: llc -mtriple=i386-linux-gnu      -global-isel -verify-machineinstrs                       < %s -o - | FileCheck %s --check-prefix=X32
-; RUN: llc -mtriple=x86_64-linux-gnux32 -global-isel -verify-machineinstrs                       < %s -o - | FileCheck %s --check-prefix=X32ABI
+; RUN: llc -mtriple=i386-linux-gnu      -global-isel -verify-machineinstrs                       < %s -o - | FileCheck %s --check-prefix=X86
+; RUN: llc -mtriple=x86_64-linux-gnux32 -global-isel -verify-machineinstrs                       < %s -o - | FileCheck %s --check-prefix=X32
 
 @g_int = dso_local global i32 0, align 4
+ at g_int_stub = global i32 0, align 4
 
-; Function Attrs: noinline nounwind optnone uwtable
-define dso_local ptr @test_global_ptrv() #3 {
+define dso_local ptr @test_global_ptrv() {
 ; X64-LABEL: test_global_ptrv:
 ; X64:       # %bb.0: # %entry
 ; X64-NEXT:    leaq g_int, %rax
@@ -18,22 +18,21 @@ define dso_local ptr @test_global_ptrv() #3 {
 ; X64_DARWIN_PIC-NEXT:    leaq _g_int(%rip), %rax
 ; X64_DARWIN_PIC-NEXT:    retq
 ;
+; X86-LABEL: test_global_ptrv:
+; X86:       # %bb.0: # %entry
+; X86-NEXT:    leal g_int, %eax
+; X86-NEXT:    retl
+;
 ; X32-LABEL: test_global_ptrv:
 ; X32:       # %bb.0: # %entry
 ; X32-NEXT:    leal g_int, %eax
-; X32-NEXT:    retl
-;
-; X32ABI-LABEL: test_global_ptrv:
-; X32ABI:       # %bb.0: # %entry
-; X32ABI-NEXT:    leal g_int, %eax
-; X32ABI-NEXT:    movl %eax, %eax
-; X32ABI-NEXT:    retq
+; X32-NEXT:    movl %eax, %eax
+; X32-NEXT:    retq
 entry:
   ret ptr @g_int
 }
 
-; Function Attrs: noinline nounwind optnone uwtable
-define dso_local i32 @test_global_valv() #3 {
+define dso_local i32 @test_global_valv() {
 ; X64-LABEL: test_global_valv:
 ; X64:       # %bb.0: # %entry
 ; X64-NEXT:    movl g_int, %eax
@@ -44,17 +43,65 @@ define dso_local i32 @test_global_valv() #3 {
 ; X64_DARWIN_PIC-NEXT:    movl _g_int(%rip), %eax
 ; X64_DARWIN_PIC-NEXT:    retq
 ;
+; X86-LABEL: test_global_valv:
+; X86:       # %bb.0: # %entry
+; X86-NEXT:    movl g_int, %eax
+; X86-NEXT:    retl
+;
 ; X32-LABEL: test_global_valv:
 ; X32:       # %bb.0: # %entry
 ; X32-NEXT:    movl g_int, %eax
-; X32-NEXT:    retl
-;
-; X32ABI-LABEL: test_global_valv:
-; X32ABI:       # %bb.0: # %entry
-; X32ABI-NEXT:    movl g_int, %eax
-; X32ABI-NEXT:    retq
+; X32-NEXT:    retq
 entry:
   %0 = load i32, ptr @g_int, align 4
   ret i32 %0
 }
 
+define dso_local ptr @test_global_stub_ptrv() {
+; X64-LABEL: test_global_stub_ptrv:
+; X64:       # %bb.0:
+; X64-NEXT:    movq g_int_stub at GOTPCREL(%rip), %rax
+; X64-NEXT:    retq
+;
+; X64_DARWIN_PIC-LABEL: test_global_stub_ptrv:
+; X64_DARWIN_PIC:       ## %bb.0:
+; X64_DARWIN_PIC-NEXT:    leaq _g_int_stub(%rip), %rax
+; X64_DARWIN_PIC-NEXT:    retq
+;
+; X86-LABEL: test_global_stub_ptrv:
+; X86:       # %bb.0:
+; X86-NEXT:    leal g_int_stub, %eax
+; X86-NEXT:    retl
+;
+; X32-LABEL: test_global_stub_ptrv:
+; X32:       # %bb.0:
+; X32-NEXT:    movl g_int_stub at GOTPCREL(%rip), %eax
+; X32-NEXT:    retq
+  ret ptr @g_int_stub
+}
+
+define dso_local i32 @test_global_stub_valv() {
+; X64-LABEL: test_global_stub_valv:
+; X64:       # %bb.0:
+; X64-NEXT:    movq g_int_stub at GOTPCREL(%rip), %rax
+; X64-NEXT:    movl (%rax), %eax
+; X64-NEXT:    retq
+;
+; X64_DARWIN_PIC-LABEL: test_global_stub_valv:
+; X64_DARWIN_PIC:       ## %bb.0:
+; X64_DARWIN_PIC-NEXT:    movl _g_int_stub(%rip), %eax
+; X64_DARWIN_PIC-NEXT:    retq
+;
+; X86-LABEL: test_global_stub_valv:
+; X86:       # %bb.0:
+; X86-NEXT:    movl g_int_stub, %eax
+; X86-NEXT:    retl
+;
+; X32-LABEL: test_global_stub_valv:
+; X32:       # %bb.0:
+; X32-NEXT:    movl g_int_stub at GOTPCREL(%rip), %eax
+; X32-NEXT:    movl (%eax), %eax
+; X32-NEXT:    retq
+  %val = load i32, ptr @g_int_stub, align 4
+  ret i32 %val
+}
diff --git a/llvm/test/CodeGen/X86/GlobalISel/x86_64-legalize-GV.mir b/llvm/test/CodeGen/X86/GlobalISel/x86_64-legalize-GV.mir
index e7c5d9b367941..e964a47547c0c 100644
--- a/llvm/test/CodeGen/X86/GlobalISel/x86_64-legalize-GV.mir
+++ b/llvm/test/CodeGen/X86/GlobalISel/x86_64-legalize-GV.mir
@@ -15,10 +15,12 @@ alignment:       16
 legalized:       false
 regBankSelected: false
 # CHECK:      registers:
-# CHECK-NEXT:   - { id: 0, class: _, preferred-register: '', flags: [   ] }
+# CHECK-NEXT:   - { id: 0, class: _, preferred-register: '', flags: [ ] }
+# CHECK-NEXT:   - { id: 1, class: _, preferred-register: '', flags: [ ] }
 registers:
   - { id: 0, class: _, preferred-register: '' }
-# CHECK:          %0:_(p0) = G_GLOBAL_VALUE @g_int
+# CHECK:          %1:_(p0) = G_TARGET_GLOBAL_VALUE @g_int
+# CHECK-NEXT:     %0:_(p0) = G_LOAD %1(p0) :: (load (p0) from got)
 # CHECK-NEXT:     $rax = COPY %0(p0)
 # CHECK-NEXT:     RET 0, implicit $rax
 body:             |
diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td
index a8488ca3b8e6a..28017700a0448 100644
--- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td
+++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td
@@ -96,7 +96,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 
 // CHECK:      const uint8_t *GenMyCombiner::getMatchTable() const {
 // CHECK-NEXT:   constexpr static uint8_t MatchTable0[] = {
-// CHECK-NEXT:      /*   0 */ GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(104), GIMT_Encode2(216), /*)*//*default:*//*Label 5*/ GIMT_Encode4(524),
+// CHECK-NEXT:      /*   0 */ GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(105), GIMT_Encode2(217), /*)*//*default:*//*Label 5*/ GIMT_Encode4(524),
 // CHECK-NEXT:      /* 10 */ /*TargetOpcode::G_STORE*//*Label 0*/ GIMT_Encode4(458), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0),
 // CHECK-NEXT:      /* 182 */ /*TargetOpcode::G_SEXT*//*Label 1*/ GIMT_Encode4(476), GIMT_Encode4(0),
 // CHECK-NEXT:      /* 190 */ /*TargetOpcode::G_ZEXT*//*Label 2*/ GIMT_Encode4(488), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0),
diff --git a/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td b/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
index 64ca63da3b6f0..9809a43fcdddd 100644
--- a/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
+++ b/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
@@ -535,7 +535,7 @@ def : Pat<(frag GPR32:$src1, complex:$src2, complex:$src3),
 // R00O-NEXT:  GIM_Reject,
 // R00O:       // Label [[DEFAULT_NUM]]: @[[DEFAULT]]
 // R00O-NEXT:  GIM_Reject,
-// R00O-NEXT:  }; // Size: 1918 bytes
+// R00O-NEXT:  }; // Size: 1922 bytes
 
 def INSNBOB : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3, GPR32:$src4),
                  [(set GPR32:$dst,

>From 964ea11d742ef712eea867a1b382346798bbdc27 Mon Sep 17 00:00:00 2001
From: Evgenii Kudriashov <evgenii.kudriashov at intel.com>
Date: Tue, 17 Feb 2026 04:18:41 -0800
Subject: [PATCH 02/10] riscv and aarch64 legalizer info test update

---
 .../CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir | 5 ++++-
 .../CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir   | 5 ++++-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
index 655e793f55c59..7d505a55690a9 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
@@ -1,4 +1,3 @@
-# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
 # RUN: llc -mtriple=aarch64-- -run-pass=legalizer %s \
 # RUN:     -mcpu=cortex-a75 -o - 2>&1 | FileCheck %s --check-prefixes=CHECK
 
@@ -115,6 +114,10 @@
 # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
 #
+# DEBUG-NEXT: G_TARGET_GLOBAL_VALUE (opcode {{[0-9]+}}): 1 type index, 0 imm indices
+# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
+#
 # DEBUG-NEXT: G_PTRAUTH_GLOBAL_VALUE (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
 # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
index 43ef36da6a11a..23ccdf6244d08 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
@@ -1,4 +1,3 @@
-# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
 # RUN: llc -mtriple=riscv32-- -run-pass=legalizer %s \
 # RUN:     -mattr=+m,+zbb,+zfh,+v -o - 2>&1 | FileCheck %s --check-prefixes=CHECK
 # RUN: llc -mtriple=riscv64-- -run-pass=legalizer %s \
@@ -113,6 +112,10 @@
 # DEBUG-NEXT: .. the first uncovered type index: 1, OK
 # DEBUG-NEXT: .. the first uncovered imm index: 0, OK
 #
+# DEBUG-NEXT: G_TARGET_GLOBAL_VALUE (opcode {{[0-9]+}}): 1 type index, 0 imm indices
+# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
+#
 # DEBUG-NEXT: G_PTRAUTH_GLOBAL_VALUE (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
 # DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined

>From 307a3a10a7484f1d21fbc1b4381d4e06e23a1d1d Mon Sep 17 00:00:00 2001
From: Evgenii Kudriashov <evgenii.kudriashov at intel.com>
Date: Tue, 7 Apr 2026 01:25:49 -0700
Subject: [PATCH 03/10] Move to G_WRAPPER_RIP

---
 llvm/docs/GlobalISel/GenericOpcode.rst             | 10 ----------
 .../llvm/CodeGen/GlobalISel/MachineIRBuilder.h     | 14 --------------
 llvm/include/llvm/Support/TargetOpcodes.def        |  5 -----
 llvm/include/llvm/Target/GenericOpcodes.td         |  6 ------
 llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp   | 14 --------------
 .../Target/X86/GISel/X86InstructionSelector.cpp    |  2 +-
 llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp     | 10 +++++++---
 llvm/lib/Target/X86/X86InstrGISel.td               |  8 ++++++++
 .../CodeGen/X86/GlobalISel/x86_64-legalize-GV.mir  |  2 +-
 .../GlobalISelCombinerEmitter/match-table-cxx.td   |  2 +-
 .../GlobalISelEmitter/GlobalISelEmitter.td         |  2 +-
 11 files changed, 19 insertions(+), 56 deletions(-)

diff --git a/llvm/docs/GlobalISel/GenericOpcode.rst b/llvm/docs/GlobalISel/GenericOpcode.rst
index 047d7f8ebf681..11fa36becaad4 100644
--- a/llvm/docs/GlobalISel/GenericOpcode.rst
+++ b/llvm/docs/GlobalISel/GenericOpcode.rst
@@ -60,16 +60,6 @@ The address of a global value.
 
   %0(p0) = G_GLOBAL_VALUE @var_local
 
-G_TARGET_GLOBAL_VALUE
-^^^^^^^^^^^^^^^^^^^^^
-
-Like G_GLOBAL_VALUE, but GlobalISel does no folding or anything else with this
-node, and this is valid in the target-specific selection.
-
-.. code-block:: none
-
-  %0(p0) = G_TARGET_GLOBAL_VALUE @var_global
-
 G_PTRAUTH_GLOBAL_VALUE
 ^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index 011bfcce9508b..bc80a8b756464 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -496,20 +496,6 @@ class LLVM_ABI MachineIRBuilder {
   /// \return a MachineInstrBuilder for the newly created instruction.
   MachineInstrBuilder buildGlobalValue(const DstOp &Res, const GlobalValue *GV);
 
-  /// Build and insert \p Res = G_TARGET_GLOBAL_VALUE \p GV
-  ///
-  /// G_TARGET_GLOBAL_VALUE materializes the address of the specified global
-  /// into \p Res. It is a version of G_GLOBAL_VALUE for target specific
-  /// legalization of global addresses.
-  ///
-  /// \pre setBasicBlock or setMI must have been called.
-  /// \pre \p Res must be a generic virtual register with pointer type
-  ///      in the same address space as \p GV.
-  ///
-  /// \return a MachineInstrBuilder for the newly created instruction.
-  MachineInstrBuilder buildTargetGlobalValue(const DstOp &Res,
-                                             const GlobalValue *GV);
-
   /// Build and insert \p Res = G_CONSTANT_POOL \p Idx
   ///
   /// G_CONSTANT_POOL materializes the address of an object in the constant
diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def
index 3175797983011..6bfda3122141f 100644
--- a/llvm/include/llvm/Support/TargetOpcodes.def
+++ b/llvm/include/llvm/Support/TargetOpcodes.def
@@ -328,11 +328,6 @@ HANDLE_TARGET_OPCODE(G_FRAME_INDEX)
 /// Generic reference to global value.
 HANDLE_TARGET_OPCODE(G_GLOBAL_VALUE)
 
-/// Generic target specific reference to a global value (typically for
-/// distinguishing already legalized and not yet legalized refrence to a global
-/// value).
-HANDLE_TARGET_OPCODE(G_TARGET_GLOBAL_VALUE)
-
 /// Generic ptrauth-signed reference to global value.
 HANDLE_TARGET_OPCODE(G_PTRAUTH_GLOBAL_VALUE)
 
diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td
index f2f0b925480c7..1ff6d0de3d8c4 100644
--- a/llvm/include/llvm/Target/GenericOpcodes.td
+++ b/llvm/include/llvm/Target/GenericOpcodes.td
@@ -131,12 +131,6 @@ def G_GLOBAL_VALUE : GenericInstruction {
   let hasSideEffects = false;
 }
 
-def G_TARGET_GLOBAL_VALUE : GenericInstruction {
-  let OutOperandList = (outs ptype0:$dst);
-  let InOperandList = (ins unknown:$src);
-  let hasSideEffects = false;
-}
-
 def G_PTRAUTH_GLOBAL_VALUE : GenericInstruction {
   let OutOperandList = (outs type0:$dst);
   let InOperandList = (ins unknown:$addr, i32imm:$key, type1:$addrdisc, i64imm:$disc);
diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index 98774f0aea7b0..63c9ada9b059d 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -170,20 +170,6 @@ MachineInstrBuilder MachineIRBuilder::buildGlobalValue(const DstOp &Res,
   return MIB;
 }
 
-MachineInstrBuilder
-MachineIRBuilder::buildTargetGlobalValue(const DstOp &Res,
-                                         const GlobalValue *GV) {
-  assert(Res.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
-  assert(Res.getLLTTy(*getMRI()).getAddressSpace() ==
-             GV->getType()->getAddressSpace() &&
-         "address space mismatch");
-
-  auto MIB = buildInstr(TargetOpcode::G_TARGET_GLOBAL_VALUE);
-  Res.addDefToMIB(*getMRI(), MIB);
-  MIB.addGlobalAddress(GV);
-  return MIB;
-}
-
 MachineInstrBuilder MachineIRBuilder::buildConstantPool(const DstOp &Res,
                                                         unsigned Idx) {
   assert(Res.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
diff --git a/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp b/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
index a49d5bf8e624d..a77049fba133e 100644
--- a/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
+++ b/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
@@ -626,7 +626,7 @@ static bool X86SelectAddress(MachineInstr &I, const X86TargetMachine &TM,
     break;
   }
   case TargetOpcode::G_GLOBAL_VALUE:
-  case TargetOpcode::G_TARGET_GLOBAL_VALUE: {
+  case X86::G_WRAPPER_RIP: {
     auto GV = I.getOperand(1).getGlobal();
     if (GV->isThreadLocal()) {
       return false; // TODO: we don't support TLS yet.
diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
index 4b4c2a26fac77..5e98706ba52b0 100644
--- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
+++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
@@ -329,8 +329,7 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
       .widenScalarToNextPow2(1, /*Min*/ 32)
       .clampScalar(1, s32, sMaxScalar);
 
-  getActionDefinitionsBuilder({G_FRAME_INDEX, G_TARGET_GLOBAL_VALUE})
-      .legalFor({p0});
+  getActionDefinitionsBuilder(G_FRAME_INDEX).legalFor({p0});
 
   getActionDefinitionsBuilder(G_GLOBAL_VALUE).customFor({p0});
 
@@ -1010,11 +1009,16 @@ bool X86LegalizerInfo::legalizeGLOBAL_VALUE(MachineInstr &MI,
   LLT DstTy = MRI.getType(Dst);
   auto GVOpFlags = Subtarget.classifyGlobalReference(GV);
 
+  // For stub references (GOT/PLT), we need G_WRAPPER_RIP + load
   if (isGlobalStubReference(GVOpFlags)) {
     MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
     MachineFunction &MF = MIRBuilder.getMF();
 
-    auto StubAddr = MIRBuilder.buildTargetGlobalValue(DstTy, GV);
+    auto StubAddr = MRI.createGenericVirtualRegister(DstTy);
+    MIRBuilder.buildInstr(X86::G_WRAPPER_RIP)
+        .addDef(StubAddr)
+        .addGlobalAddress(GV);
+
     auto MMO = MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF),
                                        MachineMemOperand::MOLoad, DstTy,
                                        Align(DstTy.getSizeInBytes()));
diff --git a/llvm/lib/Target/X86/X86InstrGISel.td b/llvm/lib/Target/X86/X86InstrGISel.td
index b0c6bb6f61ad8..982aaae7de676 100644
--- a/llvm/lib/Target/X86/X86InstrGISel.td
+++ b/llvm/lib/Target/X86/X86InstrGISel.td
@@ -41,6 +41,14 @@ def G_FLDCW16 : X86GenericInstruction {
   let mayLoad = true;
 }
 
+// RIP-relative address wrapper for PIC mode global access.
+// Equivalent to X86ISD::WrapperRIP in SelectionDAG.
+def G_WRAPPER_RIP : X86GenericInstruction {
+  let OutOperandList = (outs type0:$dst);
+  let InOperandList = (ins type0:$src);
+  let hasSideEffects = false;
+}
+
 def : GINodeEquiv<G_FILD, X86fild>;
 def : GINodeEquiv<G_FIST, X86fp_to_mem>;
 def : GINodeEquiv<G_FNSTCW16, X86fp_cwd_get16>;
diff --git a/llvm/test/CodeGen/X86/GlobalISel/x86_64-legalize-GV.mir b/llvm/test/CodeGen/X86/GlobalISel/x86_64-legalize-GV.mir
index e964a47547c0c..f22ef0609b385 100644
--- a/llvm/test/CodeGen/X86/GlobalISel/x86_64-legalize-GV.mir
+++ b/llvm/test/CodeGen/X86/GlobalISel/x86_64-legalize-GV.mir
@@ -19,7 +19,7 @@ regBankSelected: false
 # CHECK-NEXT:   - { id: 1, class: _, preferred-register: '', flags: [ ] }
 registers:
   - { id: 0, class: _, preferred-register: '' }
-# CHECK:          %1:_(p0) = G_TARGET_GLOBAL_VALUE @g_int
+# CHECK:          %1:_(p0) = G_WRAPPER_RIP @g_int
 # CHECK-NEXT:     %0:_(p0) = G_LOAD %1(p0) :: (load (p0) from got)
 # CHECK-NEXT:     $rax = COPY %0(p0)
 # CHECK-NEXT:     RET 0, implicit $rax
diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td
index f158c5879e4e9..ab8763eea81f4 100644
--- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td
+++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td
@@ -96,7 +96,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [
 
 // CHECK:      const uint8_t *GenMyCombiner::getMatchTable() const {
 // CHECK-NEXT:   constexpr static uint8_t MatchTable0[] = {
-// CHECK-NEXT:      /*   0 */ GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(106), GIMT_Encode2(220), /*)*//*default:*//*Label 5*/ GIMT_Encode4(532),
+// CHECK-NEXT:      /*   0 */ GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(105), GIMT_Encode2(219), /*)*//*default:*//*Label 5*/ GIMT_Encode4(532),
 // CHECK-NEXT:      /* 10 */ /*TargetOpcode::G_STORE*//*Label 0*/ GIMT_Encode4(466), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0),
 // CHECK-NEXT:      /* 190 */ /*TargetOpcode::G_SEXT*//*Label 1*/ GIMT_Encode4(484), GIMT_Encode4(0),
 // CHECK-NEXT:      /* 198 */ /*TargetOpcode::G_ZEXT*//*Label 2*/ GIMT_Encode4(496), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0),
diff --git a/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td b/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
index 996a1c161a16c..b4cdd53d78124 100644
--- a/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
+++ b/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
@@ -570,7 +570,7 @@ def : Pat<(frag GPR32:$src1, complex:$src2, complex:$src3),
 // R00O-NEXT:  GIM_Reject,
 // R00O:       // Label [[DEFAULT_NUM]]: @[[DEFAULT]]
 // R00O-NEXT:  GIM_Reject,
-// R00O-NEXT:  }; // Size: 1930 bytes
+// R00O-NEXT:  }; // Size: 1926 bytes
 
 def INSNBOB : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3, GPR32:$src4),
                  [(set GPR32:$dst,

>From c0f6205a9d862bfd6356d7ab790d5c20dca5627e Mon Sep 17 00:00:00 2001
From: Evgenii Kudriashov <evgenii.kudriashov at intel.com>
Date: Tue, 7 Apr 2026 09:56:52 -0700
Subject: [PATCH 04/10] Remove G_TARGET_GLOBAL_VALUE residuals

---
 .../CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir | 5 +----
 .../CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir   | 5 +----
 2 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
index f5e816d1a8535..cbda65862d4c4 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
@@ -1,3 +1,4 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
 # RUN: llc -mtriple=aarch64-- -run-pass=legalizer %s \
 # RUN:     -mcpu=cortex-a75 -o - 2>&1 | FileCheck %s --check-prefixes=CHECK
 
@@ -114,10 +115,6 @@
 # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
 #
-# DEBUG-NEXT: G_TARGET_GLOBAL_VALUE (opcode {{[0-9]+}}): 1 type index, 0 imm indices
-# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
-# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
-#
 # DEBUG-NEXT: G_PTRAUTH_GLOBAL_VALUE (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
 # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
index fefbb09f2c87d..c34f2b217139c 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
@@ -1,3 +1,4 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
 # RUN: llc -mtriple=riscv32-- -run-pass=legalizer %s \
 # RUN:     -mattr=+m,+zbb,+zfh,+v -o - 2>&1 | FileCheck %s --check-prefixes=CHECK
 # RUN: llc -mtriple=riscv64-- -run-pass=legalizer %s \
@@ -112,10 +113,6 @@
 # DEBUG-NEXT: .. the first uncovered type index: 1, OK
 # DEBUG-NEXT: .. the first uncovered imm index: 0, OK
 #
-# DEBUG-NEXT: G_TARGET_GLOBAL_VALUE (opcode {{[0-9]+}}): 1 type index, 0 imm indices
-# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
-# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
-#
 # DEBUG-NEXT: G_PTRAUTH_GLOBAL_VALUE (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
 # DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined

>From 42c081896a73ed77f97373ec237e30159d6c558a Mon Sep 17 00:00:00 2001
From: Evgenii Kudriashov <evgenii.kudriashov at intel.com>
Date: Fri, 24 Apr 2026 01:28:39 +0200
Subject: [PATCH 05/10] Drop previous checks

---
 llvm/test/CodeGen/X86/GlobalISel/GV.ll | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/llvm/test/CodeGen/X86/GlobalISel/GV.ll b/llvm/test/CodeGen/X86/GlobalISel/GV.ll
index 35250aa54765c..36d6099b8e110 100644
--- a/llvm/test/CodeGen/X86/GlobalISel/GV.ll
+++ b/llvm/test/CodeGen/X86/GlobalISel/GV.ll
@@ -127,11 +127,6 @@ define dso_local ptr @test_external_global_ptrv() {
 ; X32:       # %bb.0: # %entry
 ; X32-NEXT:    movl external_g_int at GOTPCREL(%rip), %eax
 ; X32-NEXT:    retq
-; X32ABI-LABEL: test_external_global_ptrv:
-; X32ABI:       # %bb.0: # %entry
-; X32ABI-NEXT:    movl external_g_int at GOTPCREL(%rip), %eax
-; X32ABI-NEXT:    movl %eax, %eax
-; X32ABI-NEXT:    retq
 entry:
   ret ptr @external_g_int
 }
@@ -159,11 +154,6 @@ define dso_local i32 @test_external_global_valv() {
 ; X32-NEXT:    movl external_g_int at GOTPCREL(%rip), %eax
 ; X32-NEXT:    movl (%eax), %eax
 ; X32-NEXT:    retq
-; X32ABI-LABEL: test_external_global_valv:
-; X32ABI:       # %bb.0: # %entry
-; X32ABI-NEXT:    movl external_g_int at GOTPCREL(%rip), %eax
-; X32ABI-NEXT:    movl (%eax), %eax
-; X32ABI-NEXT:    retq
 entry:
   %0 = load i32, ptr @external_g_int, align 4
   ret i32 %0

>From 4d5b1cb8541e14561d7350230bf541efb5e86cc4 Mon Sep 17 00:00:00 2001
From: Evgenii Kudriashov <evgenii.kudriashov at intel.com>
Date: Fri, 24 Apr 2026 02:43:56 -0700
Subject: [PATCH 06/10] Update machine-block-hash.mir due to changed opcode ID

---
 llvm/test/CodeGen/X86/machine-block-hash.mir | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/llvm/test/CodeGen/X86/machine-block-hash.mir b/llvm/test/CodeGen/X86/machine-block-hash.mir
index b92da2eba4b40..27fb370a27884 100644
--- a/llvm/test/CodeGen/X86/machine-block-hash.mir
+++ b/llvm/test/CodeGen/X86/machine-block-hash.mir
@@ -4,8 +4,8 @@
 name:            foo
 body:             |
   ; HASH-LABEL: Machine Block Hash Info for function: foo
-  ; HASH-NEXT:  BB#0: 0xa6e9dab7a6e90002
-  ; HASH-NEXT:  BB#1: 0xa6e912e7a6e90002
+  ; HASH-NEXT:  BB#0: 0x6187c56061870002
+  ; HASH-NEXT:  BB#1: 0x61872a8661870002
   bb.0:
     $eax = MOV32ri 1
     RET 0
@@ -18,8 +18,8 @@ body:             |
 name:            func_mbb
 body:             |
   ; HASH-LABEL: Machine Block Hash Info for function: func_mbb
-  ; HASH-NEXT:  BB#0: 0x60fdab7a6e90002
-  ; HASH-NEXT:  BB#1: 0x60f12e7a6e90002
+  ; HASH-NEXT:  BB#0: 0x2a1ac56061870002
+  ; HASH-NEXT:  BB#1: 0x2a1a2a8661870002
   bb.0:
     successors: %bb.1
     $eax = MOV32ri 1
@@ -33,7 +33,7 @@ body:             |
 name:            func_global
 body:             |
   ; HASH-LABEL: Machine Block Hash Info for function: func_global
-  ; HASH-NEXT:  BB#0: 0xcc1bf164cc1b0002
+  ; HASH-NEXT:  BB#0: 0x19d4dac819d40002
   bb.0:
     $rax = MOV64rm $rip, 1, $noreg, @foo, $noreg
     RET 0
@@ -42,7 +42,7 @@ body:             |
 name:            func_fp
 body:             |
   ; HASH-LABEL: Machine Block Hash Info for function: func_fp
-  ; HASH-NEXT:  BB#0: 0x9d668f2d9d660002
+  ; HASH-NEXT:  BB#0: 0x4582b05845820002
   bb.0:
     $xmm0 = MOVSSrm $rip, 1, $noreg, %const.0, $noreg
     RET 0

>From 2db5e7c05a2f9324f7849bacf2e2d6c9cea810b4 Mon Sep 17 00:00:00 2001
From: Evgenii Kudriashov <evgenii.kudriashov at intel.com>
Date: Sat, 2 May 2026 11:40:04 -0700
Subject: [PATCH 07/10] No auto

---
 llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
index 5e98706ba52b0..f8a07eb344da9 100644
--- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
+++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
@@ -1004,22 +1004,22 @@ bool X86LegalizerInfo::legalizeSETROUNDING(MachineInstr &MI,
 bool X86LegalizerInfo::legalizeGLOBAL_VALUE(MachineInstr &MI,
                                             MachineRegisterInfo &MRI,
                                             LegalizerHelper &Helper) const {
-  auto GV = MI.getOperand(1).getGlobal();
+  const GlobalValue *GV = MI.getOperand(1).getGlobal();
   Register Dst = MI.getOperand(0).getReg();
   LLT DstTy = MRI.getType(Dst);
-  auto GVOpFlags = Subtarget.classifyGlobalReference(GV);
+  unsigned GVOpFlags = Subtarget.classifyGlobalReference(GV);
 
   // For stub references (GOT/PLT), we need G_WRAPPER_RIP + load
   if (isGlobalStubReference(GVOpFlags)) {
     MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
     MachineFunction &MF = MIRBuilder.getMF();
 
-    auto StubAddr = MRI.createGenericVirtualRegister(DstTy);
+    Register StubAddr = MRI.createGenericVirtualRegister(DstTy);
     MIRBuilder.buildInstr(X86::G_WRAPPER_RIP)
         .addDef(StubAddr)
         .addGlobalAddress(GV);
 
-    auto MMO = MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF),
+    MachineMemOperand MMO = MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF),
                                        MachineMemOperand::MOLoad, DstTy,
                                        Align(DstTy.getSizeInBytes()));
     MIRBuilder.buildLoad(Dst, StubAddr, *MMO);

>From 0b3cb112923baab360e9d1c06d131b2d0a41e60f Mon Sep 17 00:00:00 2001
From: Evgenii Kudriashov <evgenii.kudriashov at intel.com>
Date: Sun, 3 May 2026 05:34:43 -0700
Subject: [PATCH 08/10] Missing pointer and formatting

---
 llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
index 70bba107c6b3c..f3f9a84a31bf0 100644
--- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
+++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
@@ -1027,9 +1027,9 @@ bool X86LegalizerInfo::legalizeGLOBAL_VALUE(MachineInstr &MI,
         .addDef(StubAddr)
         .addGlobalAddress(GV);
 
-    MachineMemOperand MMO = MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF),
-                                       MachineMemOperand::MOLoad, DstTy,
-                                       Align(DstTy.getSizeInBytes()));
+    MachineMemOperand *MMO = MF.getMachineMemOperand(
+        MachinePointerInfo::getGOT(MF), MachineMemOperand::MOLoad, DstTy,
+        Align(DstTy.getSizeInBytes()));
     MIRBuilder.buildLoad(Dst, StubAddr, *MMO);
     MI.eraseFromParent();
   }

>From ad2721843b8349572057cc2bc96b89f3f496aa9c Mon Sep 17 00:00:00 2001
From: Evgenii Kudriashov <evgenii.kudriashov at intel.com>
Date: Sun, 3 May 2026 05:42:06 -0700
Subject: [PATCH 09/10] update machine-block-hash.mir after rebase

---
 llvm/test/CodeGen/X86/machine-block-hash.mir | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/llvm/test/CodeGen/X86/machine-block-hash.mir b/llvm/test/CodeGen/X86/machine-block-hash.mir
index 6e3a34993a90f..0b39e072728be 100644
--- a/llvm/test/CodeGen/X86/machine-block-hash.mir
+++ b/llvm/test/CodeGen/X86/machine-block-hash.mir
@@ -3,8 +3,8 @@
 name:            foo
 body:             |
   ; HASH-LABEL: Machine Block Hash Info for function: foo
-  ; HASH-NEXT:  BB#0: 0x6187c56061870002
-  ; HASH-NEXT:  BB#1: 0x61872a8661870002
+  ; HASH-NEXT:  BB#0: 0xf33ebf30f33e0002
+  ; HASH-NEXT:  BB#1: 0xf33ee99ef33e0002
   bb.0:
     $eax = MOV32ri 1
     RET 0
@@ -17,8 +17,8 @@ body:             |
 name:            func_mbb
 body:             |
   ; HASH-LABEL: Machine Block Hash Info for function: func_mbb
-  ; HASH-NEXT:  BB#0: 0x2a1ac56061870002
-  ; HASH-NEXT:  BB#1: 0x2a1a2a8661870002
+  ; HASH-NEXT:  BB#0: 0xf60abf30f33e0002
+  ; HASH-NEXT:  BB#1: 0xf60ae99ef33e0002
   bb.0:
     successors: %bb.1
     $eax = MOV32ri 1
@@ -32,7 +32,7 @@ body:             |
 name:            func_global
 body:             |
   ; HASH-LABEL: Machine Block Hash Info for function: func_global
-  ; HASH-NEXT:  BB#0: 0x19d4dac819d40002
+  ; HASH-NEXT:  BB#0: 0x7e32df2f7e320002
   bb.0:
     $rax = MOV64rm $rip, 1, $noreg, @foo, $noreg
     RET 0
@@ -41,7 +41,7 @@ body:             |
 name:            func_fp
 body:             |
   ; HASH-LABEL: Machine Block Hash Info for function: func_fp
-  ; HASH-NEXT:  BB#0: 0x4582b05845820002
+  ; HASH-NEXT:  BB#0: 0x3e6b0e5c3e6b0002
   bb.0:
     $xmm0 = MOVSSrm $rip, 1, $noreg, %const.0, $noreg
     RET 0

>From d69f44d2714e8f2029e0be27824b2bc24a6d0dd7 Mon Sep 17 00:00:00 2001
From: Evgenii Kudriashov <evgenii.kudriashov at intel.com>
Date: Tue, 5 May 2026 16:44:34 -0700
Subject: [PATCH 10/10] Add NodeEquiv for G_WRAPPER_RIP

---
 llvm/lib/Target/X86/X86InstrGISel.td | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/lib/Target/X86/X86InstrGISel.td b/llvm/lib/Target/X86/X86InstrGISel.td
index 982aaae7de676..521923175c444 100644
--- a/llvm/lib/Target/X86/X86InstrGISel.td
+++ b/llvm/lib/Target/X86/X86InstrGISel.td
@@ -53,3 +53,4 @@ def : GINodeEquiv<G_FILD, X86fild>;
 def : GINodeEquiv<G_FIST, X86fp_to_mem>;
 def : GINodeEquiv<G_FNSTCW16, X86fp_cwd_get16>;
 def : GINodeEquiv<G_FLDCW16, X86fp_cwd_set16>;
+def : GINodeEquiv<G_WRAPPER_RIP, X86WrapperRIP>;



More information about the llvm-commits mailing list