Skip to content

Commit f05fa6e

Browse files
authored
[AArch64] Fix argument passing in reserved registers for preserve_nonecc (#96259)
These registers include: - X19, used by LLVM as the base pointer - X15 on Windows, where it is used for stack allocation. It can still be used on Linux/Darwin. - Adjust FrameLowering scratch register code to not assume X9 is available if the calling convention is preserve_nonecc. The code will then pick an unused register as scratch, and allow X9 to continue being used for argument passing.
1 parent b704868 commit f05fa6e

File tree

4 files changed

+267
-69
lines changed

4 files changed

+267
-69
lines changed

clang/include/clang/Basic/AttrDocs.td

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5672,9 +5672,10 @@ may be changed in the future.
56725672
be used to pass function arguments. Floating-point registers (XMMs/YMMs) still
56735673
follow the C calling convention.
56745674
- On AArch64, only LR and FP are preserved by the callee.
5675-
Registers X19-X28, X0-X7, and X9-X15 are used to pass function arguments.
5676-
X8, X16-X18, SIMD and floating-point registers follow the AAPCS calling
5677-
convention.
5675+
Registers X20-X28, X0-X7, and X9-X14 are used to pass function arguments.
5676+
X8, X16-X19, SIMD and floating-point registers follow the AAPCS calling
5677+
convention. X15 is not available for argument passing on Windows, but is
5678+
used to pass arguments on other platforms.
56785679
}];
56795680
}
56805681

llvm/lib/Target/AArch64/AArch64CallingConvention.td

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -500,23 +500,31 @@ def CC_AArch64_Preserve_None : CallingConv<[
500500
// - X8, used for sret
501501
// - X16/X17, used by the linker as IP0/IP1
502502
// - X18, the platform register
503+
// - X19, the base pointer
503504
// - X29, the frame pointer
504505
// - X30, the link register
505506
// General registers are not preserved with the exception of
506507
// FP, LR, and X18
507508
// Non-volatile registers are used first, so functions may call
508509
// normal functions without saving and reloading arguments.
509-
CCIfType<[i32], CCAssignToReg<[W19, W20, W21, W22, W23,
510+
// X9 is assigned last as it is used in FrameLowering as the first
511+
// choice for a scratch register.
512+
CCIfType<[i32], CCAssignToReg<[W20, W21, W22, W23,
510513
W24, W25, W26, W27, W28,
511514
W0, W1, W2, W3, W4, W5,
512-
W6, W7, W9, W10, W11,
513-
W12, W13, W14, W15]>>,
514-
CCIfType<[i64], CCAssignToReg<[X19, X20, X21, X22, X23,
515+
W6, W7, W10, W11,
516+
W12, W13, W14, W9]>>,
517+
CCIfType<[i64], CCAssignToReg<[X20, X21, X22, X23,
515518
X24, X25, X26, X27, X28,
516519
X0, X1, X2, X3, X4, X5,
517-
X6, X7, X9, X10, X11,
518-
X12, X13, X14, X15]>>,
519-
520+
X6, X7, X10, X11,
521+
X12, X13, X14, X9]>>,
522+
523+
// Windows uses X15 for stack allocation
524+
CCIf<"!State.getMachineFunction().getSubtarget<AArch64Subtarget>().isTargetWindows()",
525+
CCIfType<[i32], CCAssignToReg<[W15]>>>,
526+
CCIf<"!State.getMachineFunction().getSubtarget<AArch64Subtarget>().isTargetWindows()",
527+
CCIfType<[i64], CCAssignToReg<[X15]>>>,
520528
CCDelegateTo<CC_AArch64_AAPCS>
521529
]>;
522530

llvm/lib/Target/AArch64/AArch64FrameLowering.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1036,7 +1036,10 @@ static Register findScratchNonCalleeSaveRegister(MachineBasicBlock *MBB) {
10361036
MachineFunction *MF = MBB->getParent();
10371037

10381038
// If MBB is an entry block, use X9 as the scratch register
1039-
if (&MF->front() == MBB)
1039+
// preserve_none functions may be using X9 to pass arguments,
1040+
// so prefer to pick an available register below.
1041+
if (&MF->front() == MBB &&
1042+
MF->getFunction().getCallingConv() != CallingConv::PreserveNone)
10401043
return AArch64::X9;
10411044

10421045
const AArch64Subtarget &Subtarget = MF->getSubtarget<AArch64Subtarget>();

0 commit comments

Comments
 (0)