Skip to content

Commit 3006ddd

Browse files
authored
[M68k] fix call frame destruction elimination when returning structs (llvm#107579)
Fixes llvm#106213. This adjusts `eliminateCallFramePseudoInstr` to match the behaviour of the X86 backend.
1 parent 7111d03 commit 3006ddd

File tree

2 files changed

+76
-4
lines changed

2 files changed

+76
-4
lines changed

llvm/lib/Target/M68k/M68kFrameLowering.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333

3434
using namespace llvm;
3535

36+
#define DEBUG_TYPE "m68k-frame"
37+
3638
M68kFrameLowering::M68kFrameLowering(const M68kSubtarget &STI, Align Alignment)
3739
: TargetFrameLowering(StackGrowsDown, Alignment, -4), STI(STI),
3840
TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {
@@ -231,8 +233,8 @@ MachineBasicBlock::iterator M68kFrameLowering::eliminateCallFramePseudoInstr(
231233
unsigned Opcode = I->getOpcode();
232234
bool IsDestroy = Opcode == TII.getCallFrameDestroyOpcode();
233235
DebugLoc DL = I->getDebugLoc();
234-
uint64_t Amount = !ReserveCallFrame ? I->getOperand(0).getImm() : 0;
235-
uint64_t InternalAmt = (IsDestroy && Amount) ? I->getOperand(1).getImm() : 0;
236+
uint64_t Amount = I->getOperand(0).getImm();
237+
uint64_t InternalAmt = (IsDestroy || Amount) ? I->getOperand(1).getImm() : 0;
236238
I = MBB.erase(I);
237239

238240
if (!ReserveCallFrame) {

llvm/test/CodeGen/M68k/multiple-return.ll

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
22
; RUN: llc < %s -mtriple=m68k-linux -verify-machineinstrs | FileCheck %s
33

4-
define { i32, i32, i32, i32 } @test() {
5-
; CHECK-LABEL: test:
4+
define { i32, i32, i32, i32 } @test0() {
5+
; CHECK-LABEL: test0:
66
; CHECK: .cfi_startproc
77
; CHECK-NEXT: ; %bb.0: ; %start
88
; CHECK-NEXT: move.l (4,%sp), %a0
@@ -18,3 +18,73 @@ define { i32, i32, i32, i32 } @test() {
1818
start:
1919
ret { i32, i32, i32, i32 } { i32 13, i32 17, i32 19, i32 23 }
2020
}
21+
22+
define void @call_test0() {
23+
; CHECK-LABEL: call_test0:
24+
; CHECK: .cfi_startproc
25+
; CHECK-NEXT: ; %bb.0: ; %start
26+
; CHECK-NEXT: suba.l #20, %sp
27+
; CHECK-NEXT: .cfi_def_cfa_offset -24
28+
; CHECK-NEXT: lea (4,%sp), %a0
29+
; CHECK-NEXT: move.l %a0, (%sp)
30+
; CHECK-NEXT: jsr test0
31+
; CHECK-NEXT: adda.l #16, %sp
32+
; CHECK-NEXT: rts
33+
start:
34+
%val = call { i32, i32, i32, i32 } @test0()
35+
ret void
36+
}
37+
38+
define void @test1(ptr sret({ i32, i32, i32, i32 }) %ret_val) {
39+
; CHECK-LABEL: test1:
40+
; CHECK: .cfi_startproc
41+
; CHECK-NEXT: ; %bb.0: ; %start
42+
; CHECK-NEXT: move.l (4,%sp), %d0
43+
; CHECK-NEXT: move.l (%sp), %a1
44+
; CHECK-NEXT: adda.l #4, %sp
45+
; CHECK-NEXT: move.l %a1, (%sp)
46+
; CHECK-NEXT: rts
47+
start:
48+
ret void
49+
}
50+
51+
define void @call_test1() {
52+
; CHECK-LABEL: call_test1:
53+
; CHECK: .cfi_startproc
54+
; CHECK-NEXT: ; %bb.0: ; %start
55+
; CHECK-NEXT: suba.l #20, %sp
56+
; CHECK-NEXT: .cfi_def_cfa_offset -24
57+
; CHECK-NEXT: lea (4,%sp), %a0
58+
; CHECK-NEXT: move.l %a0, (%sp)
59+
; CHECK-NEXT: jsr test1
60+
; CHECK-NEXT: adda.l #16, %sp
61+
; CHECK-NEXT: rts
62+
start:
63+
%ret_val = alloca { i32, i32, i32, i32 }
64+
call void @test1(ptr %ret_val)
65+
ret void
66+
}
67+
68+
define i32 @test2() {
69+
; CHECK-LABEL: test2:
70+
; CHECK: .cfi_startproc
71+
; CHECK-NEXT: ; %bb.0: ; %start
72+
; CHECK-NEXT: moveq #13, %d0
73+
; CHECK-NEXT: rts
74+
start:
75+
ret i32 13
76+
}
77+
78+
define void @call_test2() {
79+
; CHECK-LABEL: call_test2:
80+
; CHECK: .cfi_startproc
81+
; CHECK-NEXT: ; %bb.0: ; %start
82+
; CHECK-NEXT: suba.l #4, %sp
83+
; CHECK-NEXT: .cfi_def_cfa_offset -8
84+
; CHECK-NEXT: jsr test2
85+
; CHECK-NEXT: adda.l #4, %sp
86+
; CHECK-NEXT: rts
87+
start:
88+
%0 = call i32 @test2()
89+
ret void
90+
}

0 commit comments

Comments
 (0)