[llvm] [Statepoint] Handle struct return through stack (PR #157251)
Abhishek Kaushik via llvm-commits
llvm-commits at lists.llvm.org
Sat Sep 6 04:56:33 PDT 2025
https://github.com/abhishek-kaushik22 created https://github.com/llvm/llvm-project/pull/157251
Handle struct return from stack in `lowerCallFromStatepointLoweringInfo`
Patch by @e-kud
Fixes #74612
>From 60d53ae26eb3e04b66a1952de291a6194f0599f0 Mon Sep 17 00:00:00 2001
From: Abhishek Kaushik <abhishek.kaushik at intel.com>
Date: Sat, 6 Sep 2025 17:25:44 +0530
Subject: [PATCH] [Statepoint] Handle struct return through stack
Handle struct return from stack in `lowerCallFromStatepointLoweringInfo`
Patch by @e-kud
Fixes #74612
---
.../SelectionDAG/StatepointLowering.cpp | 8 +++-
llvm/test/CodeGen/statepoint-struct-return.ll | 39 +++++++++++++++++++
2 files changed, 45 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/CodeGen/statepoint-struct-return.ll
diff --git a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
index 46a5e44374e1c..befb27c2039fd 100644
--- a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
@@ -337,13 +337,17 @@ static std::pair<SDValue, SDNode *> lowerCallFromStatepointLoweringInfo(
//
// get_return_value can either be a sequence of CopyFromReg instructions
// to grab the return value from the return register(s), or it can be a LOAD
- // to load a value returned by reference via a stack slot.
+ // to load a value returned by reference via a stack slot, or it can be a
+ // struct returned by value through stack.
if (CallEnd->getOpcode() == ISD::EH_LABEL)
CallEnd = CallEnd->getOperand(0).getNode();
- bool HasDef = !SI.CLI.RetTy->isVoidTy();
+ bool HasDef = !SI.CLI.RetTy->isVoidTy() || !SI.CLI.OutVals.empty();
if (HasDef) {
+ if (CallEnd->getOpcode() == ISD::TokenFactor)
+ CallEnd = CallEnd->getOperand(0).getNode();
+
if (CallEnd->getOpcode() == ISD::LOAD)
CallEnd = CallEnd->getOperand(0).getNode();
else
diff --git a/llvm/test/CodeGen/statepoint-struct-return.ll b/llvm/test/CodeGen/statepoint-struct-return.ll
new file mode 100644
index 0000000000000..36f5a6ce14473
--- /dev/null
+++ b/llvm/test/CodeGen/statepoint-struct-return.ll
@@ -0,0 +1,39 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=x86_64-- | FileCheck %s
+
+%t = type { i32, i32, i32, i32 }
+
+define %t @foo() gc "statepoint-example" {
+; CHECK-LABEL: foo:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pushq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: subq $16, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: .cfi_offset %rbx, -16
+; CHECK-NEXT: movq %rdi, %rbx
+; CHECK-NEXT: movq %rsp, %rdi
+; CHECK-NEXT: callq bar at PLT
+; CHECK-NEXT: .Ltmp0:
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ecx
+; CHECK-NEXT: movl (%rsp), %edx
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %esi
+; CHECK-NEXT: movl %edx, (%rbx)
+; CHECK-NEXT: movl %ecx, 8(%rbx)
+; CHECK-NEXT: movl %eax, 12(%rbx)
+; CHECK-NEXT: movl %esi, 4(%rbx)
+; CHECK-NEXT: movq %rbx, %rax
+; CHECK-NEXT: addq $16, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 8
+; CHECK-NEXT: retq
+ %statepoint_token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(%t ()) @bar, i32 0, i32 0, i32 0, i32 0)
+ %res = call %t @llvm.experimental.gc.result.s_zeros(token %statepoint_token)
+ ret %t %res
+}
+
+declare %t @bar()
+declare token @llvm.experimental.gc.statepoint.p0(i64, i32, ptr, i32, i32, ...)
+declare %t @llvm.experimental.gc.result.s_zeros(token)
More information about the llvm-commits
mailing list