Skip to content

Commit 82e6472

Browse files
committed
[ARM] Allow functions with sret returns to be tail-called
It is valid to tail-call a function which returns through an sret argument, as long as we have an incoming sret pointer to pass on.
1 parent c1eb790 commit 82e6472

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

llvm/lib/Target/ARM/ARMISelLowering.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3031,7 +3031,7 @@ bool ARMTargetLowering::IsEligibleForTailCallOptimization(
30313031
// return semantics.
30323032
bool isCalleeStructRet = Outs.empty() ? false : Outs[0].Flags.isSRet();
30333033
bool isCallerStructRet = MF.getFunction().hasStructRetAttr();
3034-
if (isCalleeStructRet || isCallerStructRet) {
3034+
if (isCalleeStructRet != isCallerStructRet) {
30353035
LLVM_DEBUG(dbgs() << "false (struct-ret)\n");
30363036
return false;
30373037
}

llvm/test/CodeGen/ARM/musttail.ll

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,25 @@ define i32 @fewer_args_tail(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4) {
9595
%ret = tail call i32 @many_args_callee(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6)
9696
ret i32 %ret
9797
}
98+
99+
declare void @sret_callee(ptr sret({ double, double }) align 8)
100+
101+
; Functions which return by sret can be tail-called because the incoming sret
102+
; pointer gets passed through to the callee.
103+
define void @sret_caller_tail(ptr sret({ double, double }) align 8 %result) {
104+
; CHECK-LABEL: sret_caller_tail:
105+
; CHECK: @ %bb.0: @ %entry
106+
; CHECK-NEXT: b sret_callee
107+
entry:
108+
tail call void @sret_callee(ptr sret({ double, double }) align 8 %result)
109+
ret void
110+
}
111+
112+
define void @sret_caller_musttail(ptr sret({ double, double }) align 8 %result) {
113+
; CHECK-LABEL: sret_caller_musttail:
114+
; CHECK: @ %bb.0: @ %entry
115+
; CHECK-NEXT: b sret_callee
116+
entry:
117+
musttail call void @sret_callee(ptr sret({ double, double }) align 8 %result)
118+
ret void
119+
}

0 commit comments

Comments
 (0)