[llvm] [BPF] Implement `canLowerReturn` for big returns (PR #174478)
Lucas Ste via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 8 10:11:02 PST 2026
https://github.com/LucasSte updated https://github.com/llvm/llvm-project/pull/174478
>From cc97a5a493f5c83533c366e92b84a819f057cc73 Mon Sep 17 00:00:00 2001
From: Lucas <lucas.tnagel at gmail.com>
Date: Mon, 5 Jan 2026 17:40:07 -0300
Subject: [PATCH 1/2] Implement canLowerReturn
---
llvm/lib/Target/BPF/BPFISelLowering.cpp | 10 +++++++++
llvm/lib/Target/BPF/BPFISelLowering.h | 5 +++++
llvm/test/CodeGen/BPF/atomic-oversize.ll | 2 --
llvm/test/CodeGen/BPF/i128_return.ll | 27 ++++++++++++++++++++++++
llvm/test/CodeGen/BPF/struct_ret2.ll | 2 +-
5 files changed, 43 insertions(+), 3 deletions(-)
create mode 100644 llvm/test/CodeGen/BPF/i128_return.ll
diff --git a/llvm/lib/Target/BPF/BPFISelLowering.cpp b/llvm/lib/Target/BPF/BPFISelLowering.cpp
index 5c03776dd6653..c7202d9434f33 100644
--- a/llvm/lib/Target/BPF/BPFISelLowering.cpp
+++ b/llvm/lib/Target/BPF/BPFISelLowering.cpp
@@ -1196,3 +1196,13 @@ bool BPFTargetLowering::isLegalAddressingMode(const DataLayout &DL,
return true;
}
+
+bool BPFTargetLowering::CanLowerReturn(
+ CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
+ const Type *RetTy) const {
+ // At minimal return Outs.size() <= 1, or check valid types in CC.
+ SmallVector<CCValAssign, 16> RVLocs;
+ CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
+ return CCInfo.CheckReturn(Outs, getHasAlu32() ? RetCC_BPF32 : RetCC_BPF64);
+}
diff --git a/llvm/lib/Target/BPF/BPFISelLowering.h b/llvm/lib/Target/BPF/BPFISelLowering.h
index 8607e4f8c9e69..71bbf09cbcfdb 100644
--- a/llvm/lib/Target/BPF/BPFISelLowering.h
+++ b/llvm/lib/Target/BPF/BPFISelLowering.h
@@ -163,6 +163,11 @@ class BPFTargetLowering : public TargetLowering {
MachineBasicBlock *
EmitInstrWithCustomInserterLDimm64(MachineInstr &MI,
MachineBasicBlock *BB) const;
+
+ bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
+ bool IsVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ LLVMContext &Context, const Type *RetTy) const override;
};
}
diff --git a/llvm/test/CodeGen/BPF/atomic-oversize.ll b/llvm/test/CodeGen/BPF/atomic-oversize.ll
index 187f0964d4fb8..6dc49398f091d 100644
--- a/llvm/test/CodeGen/BPF/atomic-oversize.ll
+++ b/llvm/test/CodeGen/BPF/atomic-oversize.ll
@@ -1,6 +1,4 @@
; RUN: llc -mtriple=bpf < %s | FileCheck %s
-; XFAIL: *
-; Doesn't currently build, with error 'only small returns supported'.
define void @test(ptr %a) nounwind {
; CHECK-LABEL: test:
diff --git a/llvm/test/CodeGen/BPF/i128_return.ll b/llvm/test/CodeGen/BPF/i128_return.ll
new file mode 100644
index 0000000000000..710608842107d
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/i128_return.ll
@@ -0,0 +1,27 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -march=bpfel < %s | FileCheck %s
+; This test used to fail with "unable to allocate function return #1"
+
+define i128 @foo(i64 %a, i64 %b) {
+; CHECK-LABEL: foo:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: r5 = r2
+; CHECK-NEXT: r5 += r3
+; CHECK-NEXT: w4 = 1
+; CHECK-NEXT: if r5 < r2 goto LBB0_2
+; CHECK-NEXT: # %bb.1: # %entry
+; CHECK-NEXT: w4 = 0
+; CHECK-NEXT: LBB0_2: # %entry
+; CHECK-NEXT: *(u64 *)(r1 + 0) = r5
+; CHECK-NEXT: r3 s>>= 63
+; CHECK-NEXT: r2 s>>= 63
+; CHECK-NEXT: r2 += r3
+; CHECK-NEXT: r2 += r4
+; CHECK-NEXT: *(u64 *)(r1 + 8) = r2
+; CHECK-NEXT: exit
+entry:
+ %a1 = sext i64 %a to i128
+ %b1 = sext i64 %b to i128
+ %c = add i128 %a1, %b1
+ ret i128 %c
+}
diff --git a/llvm/test/CodeGen/BPF/struct_ret2.ll b/llvm/test/CodeGen/BPF/struct_ret2.ll
index 170d55cc29df0..a20280949215e 100644
--- a/llvm/test/CodeGen/BPF/struct_ret2.ll
+++ b/llvm/test/CodeGen/BPF/struct_ret2.ll
@@ -1,6 +1,6 @@
; RUN: not llc -mtriple=bpf < %s 2> %t1
; RUN: FileCheck %s < %t1
-; CHECK: only small returns
+; CHECK: too many arguments
; Function Attrs: nounwind uwtable
define { i64, i32 } @foo(i32 %a, i32 %b, i32 %c) #0 {
>From 8b23eea139d60c83ccfc85d42c69e6a99a4016cc Mon Sep 17 00:00:00 2001
From: Lucas <lucas.tnagel at gmail.com>
Date: Thu, 8 Jan 2026 15:10:48 -0300
Subject: [PATCH 2/2] Add callee in the test
---
llvm/test/CodeGen/BPF/i128_return.ll | 27 +++++++++++++++++++++++++--
1 file changed, 25 insertions(+), 2 deletions(-)
diff --git a/llvm/test/CodeGen/BPF/i128_return.ll b/llvm/test/CodeGen/BPF/i128_return.ll
index 710608842107d..358113462d917 100644
--- a/llvm/test/CodeGen/BPF/i128_return.ll
+++ b/llvm/test/CodeGen/BPF/i128_return.ll
@@ -2,16 +2,39 @@
; RUN: llc -march=bpfel < %s | FileCheck %s
; This test used to fail with "unable to allocate function return #1"
+
+define i64 @bar(i64 %a, i64 %b) {
+; CHECK-LABEL: bar:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: r3 = r2
+; CHECK-NEXT: r2 = r1
+; CHECK-NEXT: r1 = r10
+; CHECK-NEXT: r1 += -16
+; CHECK-NEXT: call foo
+; CHECK-NEXT: r1 = *(u64 *)(r10 - 16)
+; CHECK-NEXT: r0 = *(u64 *)(r10 - 8)
+; CHECK-NEXT: r0 += r1
+; CHECK-NEXT: exit
+entry:
+ %c = call i128 @foo(i64 %a, i64 %b)
+ %d = lshr i128 %c, 64
+ %e = trunc i128 %d to i64
+ %f = trunc i128 %c to i64
+ %g = add i64 %e, %f
+ ret i64 %g
+}
+
+
define i128 @foo(i64 %a, i64 %b) {
; CHECK-LABEL: foo:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: r5 = r2
; CHECK-NEXT: r5 += r3
; CHECK-NEXT: w4 = 1
-; CHECK-NEXT: if r5 < r2 goto LBB0_2
+; CHECK-NEXT: if r5 < r2 goto LBB1_2
; CHECK-NEXT: # %bb.1: # %entry
; CHECK-NEXT: w4 = 0
-; CHECK-NEXT: LBB0_2: # %entry
+; CHECK-NEXT: LBB1_2: # %entry
; CHECK-NEXT: *(u64 *)(r1 + 0) = r5
; CHECK-NEXT: r3 s>>= 63
; CHECK-NEXT: r2 s>>= 63
More information about the llvm-commits
mailing list