llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang

@llvm/pr-subscribers-backend-aarch64

Author: dong jianqiang (dongjianqiang2)

<details>
<summary>Changes</summary>

This patch implements backend support for -mlong-calls on AArch64 targets. When 
enabled, calls to external functions are lowered to an indirect call via an 
address computed using `adrp` and `add` rather than a direct `bl` instruction, 
which is limited to a ±128MB PC-relative offset.

This is particularly useful when code and/or data exceeds the 26-bit immediate 
range of `bl`, such as in large binaries or link-time-optimized builds.

Key changes:
- In SelectionDAG lowering (`LowerCall`), detect `-mlong-calls` and emit:
    - `adrp + add` address calculation
    - `blr` indirect call instruction

This patch ensures that long-calls are emitted correctly for both GlobalAddress 
and ExternalSymbol call targets.

Tested:
- New codegen tests under `llvm/test/CodeGen/AArch64/aarch64-long-calls.ll`
- Verified `adrp + add + blr` output in `.s` for global and external functions

---
Full diff: https://github.com/llvm/llvm-project/pull/142982.diff


4 Files Affected:

- (modified) clang/lib/Driver/ToolChains/Arch/AArch64.cpp (+6) 
- (modified) llvm/lib/Target/AArch64/AArch64Features.td (+4) 
- (modified) llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (+10-3) 
- (added) llvm/test/CodeGen/AArch64/aarch64-long-calls.ll (+26) 


``````````diff
diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp 
b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
index eaae9f876e3ad..2463bcdae2f4f 100644
--- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
@@ -466,6 +466,12 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,
 
   if (Args.getLastArg(options::OPT_mno_bti_at_return_twice))
     Features.push_back("+no-bti-at-return-twice");
+
+  if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
+                               options::OPT_mno_long_calls)) {
+    if (A->getOption().matches(options::OPT_mlong_calls))
+      Features.push_back("+long-calls");
+  }
 }
 
 void aarch64::setPAuthABIInTriple(const Driver &D, const ArgList &Args,
diff --git a/llvm/lib/Target/AArch64/AArch64Features.td 
b/llvm/lib/Target/AArch64/AArch64Features.td
index 469c76752c78c..5af6ed5f1ffa2 100644
--- a/llvm/lib/Target/AArch64/AArch64Features.td
+++ b/llvm/lib/Target/AArch64/AArch64Features.td
@@ -825,6 +825,10 @@ def FeatureDisableFastIncVL : 
SubtargetFeature<"disable-fast-inc-vl",
                                                "HasDisableFastIncVL", "true",
                                                "Do not prefer INC/DEC, ALL, { 
1, 2, 4 } over ADDVL">;
 
+def FeatureLongCalls : SubtargetFeature<"long-calls", "GenLongCalls", "true",
+                                        "Generate calls via indirect call "
+                                        "instructions">;
+
 
//===----------------------------------------------------------------------===//
 // Architectures.
 //
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp 
b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 9f51caef6d228..d6015ccf94afc 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -9286,8 +9286,12 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
       Callee = DAG.getTargetGlobalAddress(CalledGlobal, DL, PtrVT, 0, OpFlags);
       Callee = DAG.getNode(AArch64ISD::LOADgot, DL, PtrVT, Callee);
     } else {
-      const GlobalValue *GV = G->getGlobal();
-      Callee = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, OpFlags);
+      if (Subtarget->genLongCalls())
+        Callee = getAddr(G, DAG, OpFlags);
+      else {
+        const GlobalValue *GV = G->getGlobal();
+        Callee = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, OpFlags);
+      }
     }
   } else if (auto *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
     bool UseGot = (getTargetMachine().getCodeModel() == CodeModel::Large &&
@@ -9298,7 +9302,10 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
       Callee = DAG.getTargetExternalSymbol(Sym, PtrVT, AArch64II::MO_GOT);
       Callee = DAG.getNode(AArch64ISD::LOADgot, DL, PtrVT, Callee);
     } else {
-      Callee = DAG.getTargetExternalSymbol(Sym, PtrVT, 0);
+      if (Subtarget->genLongCalls())
+        Callee = getAddr(S, DAG, 0);
+      else
+        Callee = DAG.getTargetExternalSymbol(Sym, PtrVT, 0);
     }
   }
 
diff --git a/llvm/test/CodeGen/AArch64/aarch64-long-calls.ll 
b/llvm/test/CodeGen/AArch64/aarch64-long-calls.ll
new file mode 100644
index 0000000000000..cb41c3cf519e0
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/aarch64-long-calls.ll
@@ -0,0 +1,26 @@
+; RUN: llc -O2 -mtriple=aarch64-linux-gnu -mcpu=generic -mattr=+long-calls < 
%s | FileCheck %s
+
+declare void @far_func()
+declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg)
+
+define void @test() {
+entry:
+  call void @far_func()
+  ret void
+}
+
+define void @test2(ptr %dst, i8 %val, i64 %len) {
+entry:
+  call void @llvm.memset.p0.i64(ptr %dst, i8 %val, i64 %len, i1 false)
+  ret void
+}
+
+; CHECK-LABEL: test:
+; CHECK: adrp {{x[0-9]+}}, far_func
+; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, :lo12:far_func
+; CHECK: blr {{x[0-9]+}}
+
+; CHECK-LABEL: test2:
+; CHECK: adrp {{x[0-9]+}}, memset
+; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, :lo12:memset
+; CHECK: blr {{x[0-9]+}}

``````````

</details>


https://github.com/llvm/llvm-project/pull/142982
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to