[llvm] [ARM] mlong-calls generate PIC code using GOT #39970 (PR #147313)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 13 01:51:05 PDT 2025


https://github.com/jiangxuezhi updated https://github.com/llvm/llvm-project/pull/147313

>From f54d66da76028867b51c959dc5372aa13971e5ed Mon Sep 17 00:00:00 2001
From: jiangxuezhi <jiangxuezhi2 at huawei.com>
Date: Sun, 13 Jul 2025 16:48:55 +0800
Subject: [PATCH] [ARM] support -mlong-calls -fPIC on arm32 #39970 #147313

---
 llvm/lib/Target/ARM/ARMISelLowering.cpp       | 14 ++++-
 .../ARM/subtarget-features-long-calls.ll      | 61 +++++++++++++++++++
 2 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index fb72bab03e750..242bec2735b6f 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -2793,8 +2793,6 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   auto PtrVt = getPointerTy(DAG.getDataLayout());
 
   if (Subtarget->genLongCalls()) {
-    assert((!isPositionIndependent() || Subtarget->isTargetWindows()) &&
-           "long-calls codegen is not position independent!");
     // Handle a global address or an external symbol. If it's not one of
     // those, the target's already in a register, so we don't need to do
     // anything extra.
@@ -2804,6 +2802,14 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
           ++NumMovwMovt;
         Callee = DAG.getNode(ARMISD::Wrapper, dl, PtrVt,
                              DAG.getTargetGlobalAddress(GVal, dl, PtrVt));
+      } else if (isPositionIndependent() && !Subtarget->isTargetWindows()){
+        SDValue G = DAG.getTargetGlobalAddress(
+              GVal, dl, PtrVt, 0, GVal->isDSOLocal() ? 0 : ARMII::MO_GOT);
+        Callee = DAG.getNode(ARMISD::WrapperPIC, dl, PtrVt, G);
+        if (!GVal->isDSOLocal())
+          Callee =
+              DAG.getLoad(PtrVt, dl, DAG.getEntryNode(), Callee,
+                          MachinePointerInfo::getGOT(DAG.getMachineFunction()));
       } else {
         // Create a constant pool entry for the callee address
         unsigned ARMPCLabelIndex = AFI->createPICLabelUId();
@@ -2837,6 +2843,10 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
         Callee = DAG.getLoad(
             PtrVt, dl, DAG.getEntryNode(), Addr,
             MachinePointerInfo::getConstantPool(DAG.getMachineFunction()));
+        if (isPositionIndependent() && !Subtarget->isTargetWindows()) {
+          SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, dl, MVT::i32);
+          Callee = DAG.getNode(ARMISD::PIC_ADD, dl, PtrVt, Callee, PICLabel);
+        }
       }
     }
   } else if (isa<GlobalAddressSDNode>(Callee)) {
diff --git a/llvm/test/CodeGen/ARM/subtarget-features-long-calls.ll b/llvm/test/CodeGen/ARM/subtarget-features-long-calls.ll
index 112a840ba92ee..7d4ea72ebd3cc 100644
--- a/llvm/test/CodeGen/ARM/subtarget-features-long-calls.ll
+++ b/llvm/test/CodeGen/ARM/subtarget-features-long-calls.ll
@@ -4,6 +4,9 @@
 ; RUN: llc -mtriple=thumb-- -mcpu=cortex-a8 -relocation-model=static %s -o - -O0 | FileCheck -check-prefix=NO-OPTION %s
 ; RUN: llc -mtriple=thumb-- -mcpu=cortex-a8 -relocation-model=static %s -o - -O0 -mattr=+long-calls | FileCheck -check-prefix=LONGCALL %s
 ; RUN: llc -mtriple=thumb-- -mcpu=cortex-a8 -relocation-model=static %s -o - -O0 -mattr=-long-calls | FileCheck -check-prefix=NO-LONGCALL %s
+; RUN: llc -mtriple=arm-linux-gnueabi -mcpu=cortex-a8 -relocation-model=pic %s -o - -O0 -mattr=+long-calls | FileCheck -check-prefix=PIC-O0-LONGCALL %s
+; RUN: llc -mtriple=arm-linux-gnueabi -mcpu=cortex-a8 -relocation-model=pic %s -o - -O1 -mattr=+long-calls | FileCheck -check-prefix=PIC-LONGCALL %s
+; RUN: llc -mtriple=arm-linux-gnueabi -mcpu=cortex-a8 -relocation-model=pic %s -o - -O2 -mattr=+long-calls | FileCheck -check-prefix=PIC-LONGCALL %s
 
 ; NO-OPTION-LABEL: {{_?}}caller0
 ; NO-OPTION: ldr [[R0:r[0-9]+]], [[L0:.*]] 
@@ -46,4 +49,62 @@ entry:
 
 declare void @callee0()
 
+; PIC-O0-LONGCALL-LABEL: global_func:
+; PIC-O0-LONGCALL:       bx lr
+
+; PIC-LONGCALL-LABEL: global_func:
+; PIC-LONGCALL:       bx lr
+define void @global_func() {
+entry:
+  ret void
+}
+
+; PIC-O0-LONGCALL-LABEL: test_global:
+; PIC-O0-LONGCALL:       push {r11, lr}
+; PIC-O0-LONGCALL:       ldr r0, [[GOT_LABEL:.*]]
+; PIC-O0-LONGCALL:       ldr r0, [pc, r0]
+; PIC-O0-LONGCALL:       blx r0
+; PIC-O0-LONGCALL:       pop {r11, pc}
+; PIC-O0-LONGCALL:       [[GOT_LABEL]]:
+; PIC-O0-LONGCALL:       .long global_func(GOT_PREL)
+
+; PIC-LONGCALL-LABEL: test_global:
+; PIC-LONGCALL:       push {r11, lr}
+; PIC-LONGCALL:       ldr r0, [[GOT_LABEL:.*]]
+; PIC-LONGCALL:       ldr r0, [pc, r0]
+; PIC-LONGCALL:       blx r0
+; PIC-LONGCALL:       pop {r11, pc}
+; PIC-LONGCALL:       [[GOT_LABEL]]:
+; PIC-LONGCALL:       .long global_func(GOT_PREL)
+define void @test_global() {
+entry:
+  call void @global_func()
+  ret void
+}
+
+; PIC-O0-LONGCALL-LABEL: test_memset:
+; PIC-O0-LONGCALL:       push {r11, lr}
+; PIC-O0-LONGCALL:       ldr r3, [[GOT_LABEL:.*]]
+; PIC-O0-LONGCALL:       ldr r3, [pc, r3]
+; PIC-O0-LONGCALL:       blx r3
+; PIC-O0-LONGCALL:       pop {r11, pc}
+; PIC-O0-LONGCALL:       [[GOT_LABEL]]:
+; PIC-O0-LONGCALL:       .long memset(GOT_PREL)
+
+; PIC-LONGCALL-LABEL: test_memset:
+; PIC-LONGCALL:       push {r11, lr}
+; PIC-LONGCALL:       ldr r3, [[MEMSET_LABEL:.*]]
+; PIC-LONGCALL:       add r3, pc, r3
+; PIC-LONGCALL:       blx r3
+; PIC-LONGCALL:       pop {r11, pc}
+; PIC-LONGCALL:       [[MEMSET_LABEL]]:
+; PIC-LONGCALL:       .long memset
+declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg)
+
+define void @test_memset(ptr %dst, i8 %val, i32 %len) {
+entry:
+  call void @llvm.memset.p0.i32(ptr %dst, i8 %val, i32 %len, i1 false)
+  ret void
+}
+
 attributes #0 = { "target-features"="+long-calls" }



More information about the llvm-commits mailing list