From 309d55140c46384b6de7a7573206cbeba3f7077f Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 30 Oct 2023 15:01:01 +0100 Subject: [PATCH] [AArch64][GlobalISel] Fix incorrect ABI when tail call not supported (#70215) The check for whether a tail call is supported calls determineAssignments(), which may modify argument flags. As such, even though the check fails and a non-tail call will be emitted, it will not have a different (incorrect) ABI. Fix this by operating on a separate copy of the arguments. Fixes https://github.com/llvm/llvm-project/issues/70207. (cherry picked from commit 292f34b0d3cb2a04be5ebb85aaeb838b29f71323) --- .../AArch64/GISel/AArch64CallLowering.cpp | 7 +++++-- .../call-lowering-tail-call-fallback.ll | 18 +++++++----------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp index e78d8bb487a93f..c56e3373d3a7fc 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp @@ -829,9 +829,9 @@ bool AArch64CallLowering::doCallerAndCalleePassArgsTheSameWay( bool AArch64CallLowering::areCalleeOutgoingArgsTailCallable( CallLoweringInfo &Info, MachineFunction &MF, - SmallVectorImpl &OutArgs) const { + SmallVectorImpl &OrigOutArgs) const { // If there are no outgoing arguments, then we are done. - if (OutArgs.empty()) + if (OrigOutArgs.empty()) return true; const Function &CallerF = MF.getFunction(); @@ -851,6 +851,9 @@ bool AArch64CallLowering::areCalleeOutgoingArgsTailCallable( AArch64OutgoingValueAssigner CalleeAssigner(AssignFnFixed, AssignFnVarArg, Subtarget, /*IsReturn*/ false); + // determineAssignments() may modify argument flags, so make a copy. + SmallVector OutArgs; + append_range(OutArgs, OrigOutArgs); if (!determineAssignments(CalleeAssigner, OutArgs, OutInfo)) { LLVM_DEBUG(dbgs() << "... Could not analyze call operands.\n"); return false; diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/call-lowering-tail-call-fallback.ll b/llvm/test/CodeGen/AArch64/GlobalISel/call-lowering-tail-call-fallback.ll index fc6eefb4016b66..ebd2beca678105 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/call-lowering-tail-call-fallback.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/call-lowering-tail-call-fallback.ll @@ -3,30 +3,26 @@ declare void @func(i64, i64, i64, i64, i64, i128, i128) -; FIXME: This is a miscompile. ; Make sure the check for whether a tail call is allowed does not affect the ; calling convention if it fails. ; The first i128 argument should be passed in registers, not on the stack. define void @pr70207(i128 %arg1, i128 %arg2) nounwind { ; CHECK-LABEL: pr70207: ; CHECK: // %bb.0: -; CHECK-NEXT: sub sp, sp, #64 +; CHECK-NEXT: mov x8, x2 ; CHECK-NEXT: mov x6, x0 -; CHECK-NEXT: mov x8, x1 -; CHECK-NEXT: mov x9, x2 -; CHECK-NEXT: mov x10, x3 +; CHECK-NEXT: mov x7, x1 +; CHECK-NEXT: mov x9, x3 ; CHECK-NEXT: mov x0, xzr ; CHECK-NEXT: mov x1, xzr ; CHECK-NEXT: mov x2, xzr ; CHECK-NEXT: mov x3, xzr ; CHECK-NEXT: mov x4, xzr -; CHECK-NEXT: str x30, [sp, #48] // 8-byte Folded Spill -; CHECK-NEXT: str x8, [sp] -; CHECK-NEXT: str x9, [sp, #16] -; CHECK-NEXT: str x10, [sp, #32] +; CHECK-NEXT: str x8, [sp, #-32]! +; CHECK-NEXT: stp x9, x30, [sp, #8] // 8-byte Folded Spill ; CHECK-NEXT: bl func -; CHECK-NEXT: ldr x30, [sp, #48] // 8-byte Folded Reload -; CHECK-NEXT: add sp, sp, #64 +; CHECK-NEXT: ldr x30, [sp, #16] // 8-byte Folded Reload +; CHECK-NEXT: add sp, sp, #32 ; CHECK-NEXT: ret tail call void @func(i64 0, i64 0, i64 0, i64 0, i64 0, i128 %arg1, i128 %arg2) ret void