[llvm] 1b32574 - [X86][GISel] lower GOT-relative G_GLOBAL_VALUEs (#181983)

via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 23 05:34:52 PDT 2026


Author: Rose Hudson
Date: 2026-04-23T13:34:47+01:00
New Revision: 1b325745f13471bdb11ba32cd5dece51dcf299ac

URL: https://github.com/llvm/llvm-project/commit/1b325745f13471bdb11ba32cd5dece51dcf299ac
DIFF: https://github.com/llvm/llvm-project/commit/1b325745f13471bdb11ba32cd5dece51dcf299ac.diff

LOG: [X86][GISel] lower GOT-relative G_GLOBAL_VALUEs (#181983)

During selection if we see a GOT-relative G_GLOBAL_VALUE, don't try to
fold it into an X86AddressMode (like we would with other modes of
accessing globals) because it needs a load from the GOT. Then select mov
for the G_GLOBAL_VALUE to do that load.

Added: 
    

Modified: 
    llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
    llvm/test/CodeGen/X86/GlobalISel/GV.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp b/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
index 19cbb307529d7..985a9eb30b5f5 100644
--- a/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
+++ b/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
@@ -633,12 +633,18 @@ static bool X86SelectAddress(MachineInstr &I, const X86TargetMachine &TM,
     // Can't handle alternate code models yet.
     if (TM.getCodeModel() != CodeModel::Small)
       return false;
-    AM.GV = GV;
-    AM.GVOpFlags = STI.classifyGlobalReference(GV);
 
-    // TODO: The ABI requires an extra load. not supported yet.
-    if (isGlobalStubReference(AM.GVOpFlags))
-      return false;
+    unsigned int GVOpFlags = STI.classifyGlobalReference(GV);
+
+    // If it's a stub, we need to do a load to find the real address, and we
+    // can't fold that into just an AM. The load will come from lowering this
+    // G_GLOBAL_VALUE later.
+    if (isGlobalStubReference(GVOpFlags))
+      break;
+
+    // If it's not a stub, point AM directly at the global.
+    AM.GV = GV;
+    AM.GVOpFlags = GVOpFlags;
 
     // TODO: This reference is relative to the pic base. not supported yet.
     if (isGlobalRelativeToPICBase(AM.GVOpFlags))
@@ -773,12 +779,27 @@ bool X86InstructionSelector::selectGlobalValue(MachineInstr &I,
          "unexpected instruction");
 
   X86AddressMode AM;
-  if (!X86SelectAddress(I, TM, MRI, STI, AM))
-    return false;
+  unsigned NewOpc;
 
-  const Register DefReg = I.getOperand(0).getReg();
-  LLT Ty = MRI.getType(DefReg);
-  unsigned NewOpc = getLeaOP(Ty, STI);
+  const GlobalValue *GV = I.getOperand(1).getGlobal();
+  const auto GVOpFlags = STI.classifyGlobalReference(GV);
+  if (isGlobalStubReference(GVOpFlags)) {
+    // If it's a stub, we need a load from the GOT instead of lea.
+    AM.GV = GV;
+    AM.GVOpFlags = GVOpFlags;
+    if (STI.isPICStyleRIPRel() || AM.GVOpFlags == X86II::MO_GOTPCREL ||
+        AM.GVOpFlags == X86II::MO_GOTPCREL_NORELAX)
+      AM.Base.Reg = X86::RIP;
+
+    NewOpc = STI.isTarget64BitLP64() ? X86::MOV64rm : X86::MOV32rm;
+  } else {
+    if (!X86SelectAddress(I, TM, MRI, STI, AM))
+      return false;
+
+    const Register DefReg = I.getOperand(0).getReg();
+    LLT Ty = MRI.getType(DefReg);
+    NewOpc = getLeaOP(Ty, STI);
+  }
 
   I.setDesc(TII.get(NewOpc));
   MachineInstrBuilder MIB(MF, I);

diff  --git a/llvm/test/CodeGen/X86/GlobalISel/GV.ll b/llvm/test/CodeGen/X86/GlobalISel/GV.ll
index c161a32fd6b95..1681992ddca4d 100644
--- a/llvm/test/CodeGen/X86/GlobalISel/GV.ll
+++ b/llvm/test/CodeGen/X86/GlobalISel/GV.ll
@@ -5,6 +5,7 @@
 ; RUN: llc -mtriple=x86_64-linux-gnux32 -global-isel -verify-machineinstrs                       < %s -o - | FileCheck %s --check-prefix=X32ABI
 
 @g_int = dso_local global i32 0, align 4
+ at external_g_int = external global i32, align 4
 
 ; Function Attrs: noinline nounwind optnone uwtable
 define dso_local ptr @test_global_ptrv() #3 {
@@ -58,3 +59,55 @@ entry:
   ret i32 %0
 }
 
+define dso_local ptr @test_external_global_ptrv() {
+; X64-LABEL: test_external_global_ptrv:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    movq external_g_int at GOTPCREL(%rip), %rax
+; X64-NEXT:    retq
+;
+; X64_DARWIN_PIC-LABEL: test_external_global_ptrv:
+; X64_DARWIN_PIC:       ## %bb.0: ## %entry
+; X64_DARWIN_PIC-NEXT:    movq _external_g_int at GOTPCREL(%rip), %rax
+; X64_DARWIN_PIC-NEXT:    retq
+;
+; X32-LABEL: test_external_global_ptrv:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    leal external_g_int, %eax
+; X32-NEXT:    retl
+;
+; 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
+}
+
+define dso_local i32 @test_external_global_valv() {
+; X64-LABEL: test_external_global_valv:
+; X64:       # %bb.0: # %entry
+; X64-NEXT:    movq external_g_int at GOTPCREL(%rip), %rax
+; X64-NEXT:    movl (%rax), %eax
+; X64-NEXT:    retq
+;
+; X64_DARWIN_PIC-LABEL: test_external_global_valv:
+; X64_DARWIN_PIC:       ## %bb.0: ## %entry
+; X64_DARWIN_PIC-NEXT:    movq _external_g_int at GOTPCREL(%rip), %rax
+; X64_DARWIN_PIC-NEXT:    movl (%rax), %eax
+; X64_DARWIN_PIC-NEXT:    retq
+;
+; X32-LABEL: test_external_global_valv:
+; X32:       # %bb.0: # %entry
+; X32-NEXT:    movl external_g_int, %eax
+; X32-NEXT:    retl
+;
+; 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
+}


        


More information about the llvm-commits mailing list