Skip to content

Commit aae152a

Browse files
committed
[X86] Reuse unchanged incoming stack args for tail calls
When a musttail call forwards an incoming stack argument unchanged to the same outgoing stack offset, X86 lowering still creates a fixed object and stores the value back to the stack. In the common same-signature tail-call case this materializes unnecessary stack traffic before the tail jump. Reuse the incoming stack slot when MatchingStackOffset proves that the outgoing argument already resides at the required offset. Keep byval arguments on the existing copy path and limit the first reuse path to non-negative fixed stack offsets. Assisted-by: OpenAI Codex
1 parent 4f339ee commit aae152a

2 files changed

Lines changed: 82 additions & 2 deletions

File tree

llvm/lib/Target/X86/X86ISelLoweringCall.cpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2084,6 +2084,29 @@ X86TargetLowering::ByValCopyKind X86TargetLowering::ByValNeedsCopyForTailCall(
20842084
return CopyViaTemp;
20852085
}
20862086

2087+
static bool MatchingStackOffset(SDValue Arg, unsigned Offset,
2088+
ISD::ArgFlagsTy Flags, MachineFrameInfo &MFI,
2089+
const MachineRegisterInfo *MRI,
2090+
const X86InstrInfo *TII, const CCValAssign &VA);
2091+
2092+
static bool canReuseIncomingTailCallStackArg(SDValue Arg, int32_t Offset,
2093+
ISD::ArgFlagsTy Flags,
2094+
MachineFunction &MF,
2095+
const X86Subtarget &Subtarget,
2096+
const CCValAssign &VA) {
2097+
// ByVal tailcall arguments have extra temporary-copy handling above this
2098+
// point. Keep the first reuse pass limited to direct scalar/vector stack
2099+
// arguments, matching the common musttail same-signature case.
2100+
if (Flags.isByVal())
2101+
return false;
2102+
2103+
if (Offset < 0)
2104+
return false;
2105+
2106+
return MatchingStackOffset(Arg, unsigned(Offset), Flags, MF.getFrameInfo(),
2107+
&MF.getRegInfo(), Subtarget.getInstrInfo(), VA);
2108+
}
2109+
20872110
SDValue
20882111
X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
20892112
SmallVectorImpl<SDValue> &InVals) const {
@@ -2532,8 +2555,14 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
25322555
if (Flags.isInAlloca() || Flags.isPreallocated())
25332556
continue;
25342557
// Create frame index.
2535-
int32_t Offset = VA.getLocMemOffset()+FPDiff;
2536-
uint32_t OpSize = (VA.getLocVT().getSizeInBits()+7)/8;
2558+
int32_t Offset = VA.getLocMemOffset() + FPDiff;
2559+
uint32_t OpSize = (VA.getLocVT().getSizeInBits() + 7) / 8;
2560+
2561+
if (Is64Bit && isTailCall &&
2562+
canReuseIncomingTailCallStackArg(Arg, Offset, Flags, MF, Subtarget,
2563+
VA))
2564+
continue;
2565+
25372566
FI = MF.getFrameInfo().CreateFixedObject(OpSize, Offset, true);
25382567
FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
25392568

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -relocation-model=static | FileCheck %s
2+
3+
declare preserve_nonecc void @next(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64)
4+
declare preserve_nonecc void @next_with_cond(i1, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64)
5+
6+
define preserve_nonecc void @static_tail_unchanged(i64 %a0, i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6, i64 %a7, i64 %a8, i64 %a9, i64 %a10, i64 %a11, i64 %a12, i64 %a13, i64 %a14, i64 %a15, i64 %a16, i64 %a17, i64 %a18, i64 %a19, i64 %a20, i64 %a21, i64 %a22, i64 %a23, i64 %a24, i64 %a25, i64 %a26, i64 %a27, i64 %a28, i64 %a29, i64 %a30, i64 %a31, i64 %a32, i64 %a33, i64 %a34, i64 %a35) {
7+
; CHECK-LABEL: static_tail_unchanged:
8+
; CHECK: # %bb.0:
9+
; CHECK-NEXT: jmp next@PLT # TAILCALL
10+
entry:
11+
musttail call preserve_nonecc void @next(i64 %a0, i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6, i64 %a7, i64 %a8, i64 %a9, i64 %a10, i64 %a11, i64 %a12, i64 %a13, i64 %a14, i64 %a15, i64 %a16, i64 %a17, i64 %a18, i64 %a19, i64 %a20, i64 %a21, i64 %a22, i64 %a23, i64 %a24, i64 %a25, i64 %a26, i64 %a27, i64 %a28, i64 %a29, i64 %a30, i64 %a31, i64 %a32, i64 %a33, i64 %a34, i64 %a35)
12+
ret void
13+
}
14+
15+
define preserve_nonecc void @static_tail_changed(i64 %a0, i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6, i64 %a7, i64 %a8, i64 %a9, i64 %a10, i64 %a11, i64 %a12, i64 %a13, i64 %a14, i64 %a15, i64 %a16, i64 %a17, i64 %a18, i64 %a19, i64 %a20, i64 %a21, i64 %a22, i64 %a23, i64 %a24, i64 %a25, i64 %a26, i64 %a27, i64 %a28, i64 %a29, i64 %a30, i64 %a31, i64 %a32, i64 %a33, i64 %a34, i64 %a35) {
16+
; CHECK-LABEL: static_tail_changed:
17+
; CHECK: # %bb.0:
18+
; CHECK-NEXT: movq 168(%rsp), %r10
19+
; CHECK-NEXT: incq %r10
20+
; CHECK-NEXT: movq %r10, 168(%rsp)
21+
; CHECK-NEXT: jmp next@PLT # TAILCALL
22+
entry:
23+
%a32x = add i64 %a32, 1
24+
musttail call preserve_nonecc void @next(i64 %a0, i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6, i64 %a7, i64 %a8, i64 %a9, i64 %a10, i64 %a11, i64 %a12, i64 %a13, i64 %a14, i64 %a15, i64 %a16, i64 %a17, i64 %a18, i64 %a19, i64 %a20, i64 %a21, i64 %a22, i64 %a23, i64 %a24, i64 %a25, i64 %a26, i64 %a27, i64 %a28, i64 %a29, i64 %a30, i64 %a31, i64 %a32x, i64 %a33, i64 %a34, i64 %a35)
25+
ret void
26+
}
27+
28+
define preserve_nonecc void @phi_tail(i1 %cond, i64 %a0, i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6, i64 %a7, i64 %a8, i64 %a9, i64 %a10, i64 %a11, i64 %a12, i64 %a13, i64 %a14, i64 %a15, i64 %a16, i64 %a17, i64 %a18, i64 %a19, i64 %a20, i64 %a21, i64 %a22, i64 %a23, i64 %a24, i64 %a25, i64 %a26, i64 %a27, i64 %a28, i64 %a29, i64 %a30, i64 %a31, i64 %a32, i64 %a33, i64 %a34, i64 %a35) {
29+
; CHECK-LABEL: phi_tail:
30+
; CHECK: # %bb.0:
31+
; CHECK-NEXT: movq 176(%rsp), %r10
32+
; CHECK-NEXT: testb $1, %dil
33+
; CHECK-NEXT: je .LBB2_2
34+
; CHECK: # %bb.1:
35+
; CHECK-NEXT: incq %r10
36+
; CHECK: .LBB2_2:
37+
; CHECK-NEXT: movq %r10, 176(%rsp)
38+
; CHECK-NEXT: movzbl %dil, %edi
39+
; CHECK-NEXT: jmp next_with_cond@PLT # TAILCALL
40+
entry:
41+
br i1 %cond, label %a, label %b
42+
a:
43+
%a32x = add i64 %a32, 1
44+
br label %join
45+
b:
46+
br label %join
47+
join:
48+
%a32m = phi i64 [ %a32x, %a ], [ %a32, %b ]
49+
musttail call preserve_nonecc void @next_with_cond(i1 %cond, i64 %a0, i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6, i64 %a7, i64 %a8, i64 %a9, i64 %a10, i64 %a11, i64 %a12, i64 %a13, i64 %a14, i64 %a15, i64 %a16, i64 %a17, i64 %a18, i64 %a19, i64 %a20, i64 %a21, i64 %a22, i64 %a23, i64 %a24, i64 %a25, i64 %a26, i64 %a27, i64 %a28, i64 %a29, i64 %a30, i64 %a31, i64 %a32m, i64 %a33, i64 %a34, i64 %a35)
50+
ret void
51+
}

0 commit comments

Comments
 (0)