[llvm] [X86] Do not hold GOT base for indirect call or absolute address (PR #203192)
Phoebe Wang via llvm-commits
llvm-commits at lists.llvm.org
Sun Jun 14 22:25:03 PDT 2026
https://github.com/phoebewang updated https://github.com/llvm/llvm-project/pull/203192
>From bc253fc51f99fd876c3299bc284dc65de9da4afd Mon Sep 17 00:00:00 2001
From: Phoebe Wang <phoebe.wang at intel.com>
Date: Thu, 11 Jun 2026 00:32:24 -0700
Subject: [PATCH 1/2] [X86] Do not hold GOT base for indirect call or constant
address
Fixes: https://github.com/llvm/llvm-project/pull/202370#discussion_r3384983368
Assisted-by: Claude Sonnet 4.6
---
llvm/lib/Target/X86/X86ISelLoweringCall.cpp | 11 ++--
llvm/test/CodeGen/X86/abi-isel.ll | 72 +++++++++------------
2 files changed, 38 insertions(+), 45 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLoweringCall.cpp b/llvm/lib/Target/X86/X86ISelLoweringCall.cpp
index 89775eb70e038..0da8d276e2d8c 100644
--- a/llvm/lib/Target/X86/X86ISelLoweringCall.cpp
+++ b/llvm/lib/Target/X86/X86ISelLoweringCall.cpp
@@ -2392,12 +2392,13 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
if (Subtarget.isPICStyleGOT()) {
// ELF / PIC requires GOT in the EBX register before function calls via PLT
- // GOT pointer (except regcall).
+ // GOT pointer.
if (!isTailCall) {
- // Indirect call with RegCall calling convertion may use up all the
- // general registers, so it is not suitable to bind EBX reister for
- // GOT address, just let register allocator handle it.
- if (CallConv != CallingConv::X86_RegCall)
+ // Only PLT calls (GlobalAddress or ExternalSymbol) require the GOT in
+ // EBX. Indirect calls through a register or a constant address do not
+ // go through the PLT and do not need EBX to hold the GOT base.
+ if ((Callee->getOpcode() == ISD::GlobalAddress ||
+ Callee->getOpcode() == ISD::ExternalSymbol))
RegsToPass.push_back(std::make_pair(
Register(X86::EBX), DAG.getNode(X86ISD::GlobalBaseReg, SDLoc(),
getPointerTy(DAG.getDataLayout()))));
diff --git a/llvm/test/CodeGen/X86/abi-isel.ll b/llvm/test/CodeGen/X86/abi-isel.ll
index 2ac392c729d19..d5e99e919b820 100644
--- a/llvm/test/CodeGen/X86/abi-isel.ll
+++ b/llvm/test/CodeGen/X86/abi-isel.ll
@@ -11608,20 +11608,18 @@ define dso_local void @icaller() nounwind {
;
; LINUX-32-PIC-LABEL: icaller:
; LINUX-32-PIC: # %bb.0: # %entry
-; LINUX-32-PIC-NEXT: pushl %ebx
; LINUX-32-PIC-NEXT: pushl %esi
-; LINUX-32-PIC-NEXT: pushl %eax
+; LINUX-32-PIC-NEXT: subl $8, %esp
; LINUX-32-PIC-NEXT: calll .L142$pb
; LINUX-32-PIC-NEXT: .L142$pb:
-; LINUX-32-PIC-NEXT: popl %ebx
+; LINUX-32-PIC-NEXT: popl %eax
; LINUX-32-PIC-NEXT: .Ltmp142:
-; LINUX-32-PIC-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp142-.L142$pb), %ebx
-; LINUX-32-PIC-NEXT: movl ifunc at GOT(%ebx), %esi
+; LINUX-32-PIC-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp142-.L142$pb), %eax
+; LINUX-32-PIC-NEXT: movl ifunc at GOT(%eax), %esi
; LINUX-32-PIC-NEXT: calll *(%esi)
; LINUX-32-PIC-NEXT: calll *(%esi)
-; LINUX-32-PIC-NEXT: addl $4, %esp
+; LINUX-32-PIC-NEXT: addl $8, %esp
; LINUX-32-PIC-NEXT: popl %esi
-; LINUX-32-PIC-NEXT: popl %ebx
; LINUX-32-PIC-NEXT: retl
;
; LINUX-64-PIC-LABEL: icaller:
@@ -11720,17 +11718,17 @@ define dso_local void @dicaller() nounwind {
;
; LINUX-32-PIC-LABEL: dicaller:
; LINUX-32-PIC: # %bb.0: # %entry
-; LINUX-32-PIC-NEXT: pushl %ebx
+; LINUX-32-PIC-NEXT: pushl %esi
; LINUX-32-PIC-NEXT: subl $8, %esp
; LINUX-32-PIC-NEXT: calll .L143$pb
; LINUX-32-PIC-NEXT: .L143$pb:
-; LINUX-32-PIC-NEXT: popl %ebx
+; LINUX-32-PIC-NEXT: popl %esi
; LINUX-32-PIC-NEXT: .Ltmp143:
-; LINUX-32-PIC-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp143-.L143$pb), %ebx
-; LINUX-32-PIC-NEXT: calll *.Ldifunc$local at GOTOFF(%ebx)
-; LINUX-32-PIC-NEXT: calll *.Ldifunc$local at GOTOFF(%ebx)
+; LINUX-32-PIC-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp143-.L143$pb), %esi
+; LINUX-32-PIC-NEXT: calll *.Ldifunc$local at GOTOFF(%esi)
+; LINUX-32-PIC-NEXT: calll *.Ldifunc$local at GOTOFF(%esi)
; LINUX-32-PIC-NEXT: addl $8, %esp
-; LINUX-32-PIC-NEXT: popl %ebx
+; LINUX-32-PIC-NEXT: popl %esi
; LINUX-32-PIC-NEXT: retl
;
; LINUX-64-PIC-LABEL: dicaller:
@@ -11821,17 +11819,17 @@ define dso_local void @licaller() nounwind {
;
; LINUX-32-PIC-LABEL: licaller:
; LINUX-32-PIC: # %bb.0: # %entry
-; LINUX-32-PIC-NEXT: pushl %ebx
+; LINUX-32-PIC-NEXT: pushl %esi
; LINUX-32-PIC-NEXT: subl $8, %esp
; LINUX-32-PIC-NEXT: calll .L144$pb
; LINUX-32-PIC-NEXT: .L144$pb:
-; LINUX-32-PIC-NEXT: popl %ebx
+; LINUX-32-PIC-NEXT: popl %esi
; LINUX-32-PIC-NEXT: .Ltmp144:
-; LINUX-32-PIC-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp144-.L144$pb), %ebx
-; LINUX-32-PIC-NEXT: calll *lifunc at GOTOFF(%ebx)
-; LINUX-32-PIC-NEXT: calll *lifunc at GOTOFF(%ebx)
+; LINUX-32-PIC-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp144-.L144$pb), %esi
+; LINUX-32-PIC-NEXT: calll *lifunc at GOTOFF(%esi)
+; LINUX-32-PIC-NEXT: calll *lifunc at GOTOFF(%esi)
; LINUX-32-PIC-NEXT: addl $8, %esp
-; LINUX-32-PIC-NEXT: popl %ebx
+; LINUX-32-PIC-NEXT: popl %esi
; LINUX-32-PIC-NEXT: retl
;
; LINUX-64-PIC-LABEL: licaller:
@@ -11923,20 +11921,18 @@ define dso_local void @itailcaller() nounwind {
;
; LINUX-32-PIC-LABEL: itailcaller:
; LINUX-32-PIC: # %bb.0: # %entry
-; LINUX-32-PIC-NEXT: pushl %ebx
; LINUX-32-PIC-NEXT: pushl %esi
-; LINUX-32-PIC-NEXT: pushl %eax
+; LINUX-32-PIC-NEXT: subl $8, %esp
; LINUX-32-PIC-NEXT: calll .L145$pb
; LINUX-32-PIC-NEXT: .L145$pb:
-; LINUX-32-PIC-NEXT: popl %ebx
+; LINUX-32-PIC-NEXT: popl %eax
; LINUX-32-PIC-NEXT: .Ltmp145:
-; LINUX-32-PIC-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp145-.L145$pb), %ebx
-; LINUX-32-PIC-NEXT: movl ifunc at GOT(%ebx), %esi
+; LINUX-32-PIC-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp145-.L145$pb), %eax
+; LINUX-32-PIC-NEXT: movl ifunc at GOT(%eax), %esi
; LINUX-32-PIC-NEXT: calll *(%esi)
; LINUX-32-PIC-NEXT: calll *(%esi)
-; LINUX-32-PIC-NEXT: addl $4, %esp
+; LINUX-32-PIC-NEXT: addl $8, %esp
; LINUX-32-PIC-NEXT: popl %esi
-; LINUX-32-PIC-NEXT: popl %ebx
; LINUX-32-PIC-NEXT: retl
;
; LINUX-64-PIC-LABEL: itailcaller:
@@ -12033,16 +12029,14 @@ define dso_local void @ditailcaller() nounwind {
;
; LINUX-32-PIC-LABEL: ditailcaller:
; LINUX-32-PIC: # %bb.0: # %entry
-; LINUX-32-PIC-NEXT: pushl %ebx
-; LINUX-32-PIC-NEXT: subl $8, %esp
+; LINUX-32-PIC-NEXT: subl $12, %esp
; LINUX-32-PIC-NEXT: calll .L146$pb
; LINUX-32-PIC-NEXT: .L146$pb:
-; LINUX-32-PIC-NEXT: popl %ebx
+; LINUX-32-PIC-NEXT: popl %eax
; LINUX-32-PIC-NEXT: .Ltmp146:
-; LINUX-32-PIC-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp146-.L146$pb), %ebx
-; LINUX-32-PIC-NEXT: calll *.Ldifunc$local at GOTOFF(%ebx)
-; LINUX-32-PIC-NEXT: addl $8, %esp
-; LINUX-32-PIC-NEXT: popl %ebx
+; LINUX-32-PIC-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp146-.L146$pb), %eax
+; LINUX-32-PIC-NEXT: calll *.Ldifunc$local at GOTOFF(%eax)
+; LINUX-32-PIC-NEXT: addl $12, %esp
; LINUX-32-PIC-NEXT: retl
;
; LINUX-64-PIC-LABEL: ditailcaller:
@@ -12120,16 +12114,14 @@ define dso_local void @litailcaller() nounwind {
;
; LINUX-32-PIC-LABEL: litailcaller:
; LINUX-32-PIC: # %bb.0: # %entry
-; LINUX-32-PIC-NEXT: pushl %ebx
-; LINUX-32-PIC-NEXT: subl $8, %esp
+; LINUX-32-PIC-NEXT: subl $12, %esp
; LINUX-32-PIC-NEXT: calll .L147$pb
; LINUX-32-PIC-NEXT: .L147$pb:
-; LINUX-32-PIC-NEXT: popl %ebx
+; LINUX-32-PIC-NEXT: popl %eax
; LINUX-32-PIC-NEXT: .Ltmp147:
-; LINUX-32-PIC-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp147-.L147$pb), %ebx
-; LINUX-32-PIC-NEXT: calll *lifunc at GOTOFF(%ebx)
-; LINUX-32-PIC-NEXT: addl $8, %esp
-; LINUX-32-PIC-NEXT: popl %ebx
+; LINUX-32-PIC-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp147-.L147$pb), %eax
+; LINUX-32-PIC-NEXT: calll *lifunc at GOTOFF(%eax)
+; LINUX-32-PIC-NEXT: addl $12, %esp
; LINUX-32-PIC-NEXT: retl
;
; LINUX-64-PIC-LABEL: litailcaller:
>From 794bdeaa99c3c960fd93aa83b6cc192b50d83631 Mon Sep 17 00:00:00 2001
From: Phoebe Wang <phoebe.wang at intel.com>
Date: Sun, 14 Jun 2026 22:23:54 -0700
Subject: [PATCH 2/2] Change constant to absolute
---
llvm/lib/Target/X86/X86ISelLoweringCall.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Target/X86/X86ISelLoweringCall.cpp b/llvm/lib/Target/X86/X86ISelLoweringCall.cpp
index 0da8d276e2d8c..7c068115df481 100644
--- a/llvm/lib/Target/X86/X86ISelLoweringCall.cpp
+++ b/llvm/lib/Target/X86/X86ISelLoweringCall.cpp
@@ -2395,7 +2395,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
// GOT pointer.
if (!isTailCall) {
// Only PLT calls (GlobalAddress or ExternalSymbol) require the GOT in
- // EBX. Indirect calls through a register or a constant address do not
+ // EBX. Indirect calls through a register or an absolute address do not
// go through the PLT and do not need EBX to hold the GOT base.
if ((Callee->getOpcode() == ISD::GlobalAddress ||
Callee->getOpcode() == ISD::ExternalSymbol))
More information about the llvm-commits
mailing list