Skip to content

Commit e70ccd7

Browse files
committed
[AArch64] Fix variadic tail-calls on ARM64EC
ARM64EC varargs calls expect that x4 = sp at entry, special handling is needed to ensure this with tail calls since they occur after the epilogue and the X4 write happens before.
1 parent ea4d22f commit e70ccd7

File tree

3 files changed

+54
-1
lines changed

3 files changed

+54
-1
lines changed

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7991,11 +7991,19 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
79917991
}
79927992

79937993
if (IsVarArg && Subtarget->isWindowsArm64EC()) {
7994+
SDValue ParamPtr = StackPtr;
7995+
if (IsTailCall) {
7996+
// Create a dummy object at the top of the stack that can be used to get
7997+
// the SP after the epilogue
7998+
int FI = MF.getFrameInfo().CreateFixedObject(1, FPDiff, true);
7999+
ParamPtr = DAG.getFrameIndex(FI, PtrVT);
8000+
}
8001+
79948002
// For vararg calls, the Arm64EC ABI requires values in x4 and x5
79958003
// describing the argument list. x4 contains the address of the
79968004
// first stack parameter. x5 contains the size in bytes of all parameters
79978005
// passed on the stack.
7998-
RegsToPass.emplace_back(AArch64::X4, StackPtr);
8006+
RegsToPass.emplace_back(AArch64::X4, ParamPtr);
79998007
RegsToPass.emplace_back(AArch64::X5,
80008008
DAG.getConstant(NumBytes, DL, MVT::i64));
80018009
}

llvm/test/CodeGen/AArch64/arm64ec-varargs.ll

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,5 +100,42 @@ define void @varargs_many_argscalleer() nounwind {
100100
ret void
101101
}
102102

103+
define void @varargs_caller_tail() nounwind {
104+
; CHECK-LABEL: varargs_caller_tail:
105+
; CHECK: // %bb.0:
106+
; CHECK-NEXT: sub sp, sp, #48
107+
; CHECK-NEXT: mov x4, sp
108+
; CHECK-NEXT: add x8, sp, #16
109+
; CHECK-NEXT: mov x9, #4617315517961601024 // =0x4014000000000000
110+
; CHECK-NEXT: mov x0, #4607182418800017408 // =0x3ff0000000000000
111+
; CHECK-NEXT: mov w1, #2 // =0x2
112+
; CHECK-NEXT: mov x2, #4613937818241073152 // =0x4008000000000000
113+
; CHECK-NEXT: mov w3, #4 // =0x4
114+
; CHECK-NEXT: mov w5, #16 // =0x10
115+
; CHECK-NEXT: stp xzr, x30, [sp, #24] // 8-byte Folded Spill
116+
; CHECK-NEXT: stp x9, x8, [sp]
117+
; CHECK-NEXT: str xzr, [sp, #16]
118+
; CHECK-NEXT: .weak_anti_dep varargs_callee
119+
; CHECK-NEXT:.set varargs_callee, "#varargs_callee"@WEAKREF
120+
; CHECK-NEXT: .weak_anti_dep "#varargs_callee"
121+
; CHECK-NEXT:.set "#varargs_callee", varargs_callee@WEAKREF
122+
; CHECK-NEXT: bl "#varargs_callee"
123+
; CHECK-NEXT: ldr x30, [sp, #32] // 8-byte Folded Reload
124+
; CHECK-NEXT: add x4, sp, #48
125+
; CHECK-NEXT: mov x0, #4607182418800017408 // =0x3ff0000000000000
126+
; CHECK-NEXT: mov w1, #4 // =0x4
127+
; CHECK-NEXT: mov w2, #3 // =0x3
128+
; CHECK-NEXT: mov w3, #2 // =0x2
129+
; CHECK-NEXT: mov x5, xzr
130+
; CHECK-NEXT: add sp, sp, #48
131+
; CHECK-NEXT: .weak_anti_dep varargs_callee
132+
; CHECK-NEXT:.set varargs_callee, "#varargs_callee"@WEAKREF
133+
; CHECK-NEXT: .weak_anti_dep "#varargs_callee"
134+
; CHECK-NEXT:.set "#varargs_callee", varargs_callee@WEAKREF
135+
; CHECK-NEXT: b "#varargs_callee"
136+
call void (double, ...) @varargs_callee(double 1.0, i32 2, double 3.0, i32 4, double 5.0, <2 x double> <double 0.0, double 0.0>)
137+
tail call void (double, ...) @varargs_callee(double 1.0, i32 4, i32 3, i32 2)
138+
ret void
139+
}
103140

104141
declare void @llvm.va_start(ptr)

llvm/test/CodeGen/AArch64/vararg-tallcall.ll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
; RUN: llc -mtriple=aarch64-windows-msvc %s -o - | FileCheck %s
22
; RUN: llc -mtriple=aarch64-linux-gnu %s -o - | FileCheck %s
3+
; RUN: llc -mtriple=arm64ec-windows-msvc %s -o - | FileCheck %s --check-prefixes=CHECK-EC
34
; RUN: llc -global-isel -global-isel-abort=2 -verify-machineinstrs -mtriple=aarch64-windows-msvc %s -o - | FileCheck %s
45
; RUN: llc -global-isel -global-isel-abort=2 -verify-machineinstrs -mtriple=aarch64-linux-gnu %s -o - | FileCheck %s
56

@@ -32,3 +33,10 @@ attributes #1 = { noinline optnone "thunk" }
3233
; CHECK: ldr x9, [x9]
3334
; CHECK: mov v0.16b, v16.16b
3435
; CHECK: br x9
36+
; CHECK-EC: mov v7.16b, v0.16b
37+
; CHECK-EC: ldr x9, [x0]
38+
; CHECK-EC: ldr x11, [x9]
39+
; CHECK-EC: mov v0.16b, v7.16b
40+
; CHECK-EC: add x4, sp, #64
41+
; CHECK-EC: add sp, sp, #64
42+
; CHECK-EC: br x11

0 commit comments

Comments
 (0)