From d57911fa825a8efd9c125c57aa039ecc8656b78e Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 21 Jan 2022 10:32:21 +0100 Subject: [PATCH] [AArch64][GlobalISel] Support returned argument with multiple registers The call lowering code assumed that a returned argument could only consist of one register. Pass an ArrayRef instead of Register to make sure that all parts get assigned. Fixes https://github.com/llvm/llvm-project/issues/53315. Differential Revision: https://reviews.llvm.org/D117866 --- .../llvm/CodeGen/GlobalISel/CallLowering.h | 14 +++++------ llvm/lib/CodeGen/GlobalISel/CallLowering.cpp | 11 ++++---- .../AArch64/GISel/AArch64CallLowering.cpp | 2 +- .../CodeGen/AArch64/pr53315-returned-i128.ll | 25 +++++++++++++++++++ 4 files changed, 39 insertions(+), 13 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/pr53315-returned-i128.ll diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h b/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h index 6bdaddd9c6f54..66b800a1b1349 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h @@ -382,12 +382,12 @@ class CallLowering { /// \p Handler to move them to the assigned locations. /// /// \return True if everything has succeeded, false otherwise. - bool determineAndHandleAssignments(ValueHandler &Handler, - ValueAssigner &Assigner, - SmallVectorImpl &Args, - MachineIRBuilder &MIRBuilder, - CallingConv::ID CallConv, bool IsVarArg, - Register ThisReturnReg = Register()) const; + bool + determineAndHandleAssignments(ValueHandler &Handler, ValueAssigner &Assigner, + SmallVectorImpl &Args, + MachineIRBuilder &MIRBuilder, + CallingConv::ID CallConv, bool IsVarArg, + ArrayRef ThisReturnRegs = None) const; /// Use \p Handler to insert code to handle the argument/return values /// represented by \p Args. It's expected determineAssignments previously @@ -396,7 +396,7 @@ class CallLowering { CCState &CCState, SmallVectorImpl &ArgLocs, MachineIRBuilder &MIRBuilder, - Register ThisReturnReg = Register()) const; + ArrayRef ThisReturnRegs = None) const; /// Check whether parameters to a call that are passed in callee saved /// registers are the same as from the calling function. This needs to be diff --git a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp index d2cda9ece31a5..a68a5e27b7a83 100644 --- a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp @@ -518,7 +518,8 @@ static void buildCopyToRegs(MachineIRBuilder &B, ArrayRef DstRegs, bool CallLowering::determineAndHandleAssignments( ValueHandler &Handler, ValueAssigner &Assigner, SmallVectorImpl &Args, MachineIRBuilder &MIRBuilder, - CallingConv::ID CallConv, bool IsVarArg, Register ThisReturnReg) const { + CallingConv::ID CallConv, bool IsVarArg, + ArrayRef ThisReturnRegs) const { MachineFunction &MF = MIRBuilder.getMF(); const Function &F = MF.getFunction(); SmallVector ArgLocs; @@ -528,7 +529,7 @@ bool CallLowering::determineAndHandleAssignments( return false; return handleAssignments(Handler, Args, CCInfo, ArgLocs, MIRBuilder, - ThisReturnReg); + ThisReturnRegs); } static unsigned extendOpFromFlags(llvm::ISD::ArgFlagsTy Flags) { @@ -605,7 +606,7 @@ bool CallLowering::handleAssignments(ValueHandler &Handler, CCState &CCInfo, SmallVectorImpl &ArgLocs, MachineIRBuilder &MIRBuilder, - Register ThisReturnReg) const { + ArrayRef ThisReturnRegs) const { MachineFunction &MF = MIRBuilder.getMF(); MachineRegisterInfo &MRI = MF.getRegInfo(); const Function &F = MF.getFunction(); @@ -732,10 +733,10 @@ bool CallLowering::handleAssignments(ValueHandler &Handler, assert(!VA.needsCustom() && "custom loc should have been handled already"); - if (i == 0 && ThisReturnReg.isValid() && + if (i == 0 && !ThisReturnRegs.empty() && Handler.isIncomingArgumentHandler() && isTypeIsValidForThisReturn(ValVT)) { - Handler.assignValueToReg(Args[i].Regs[i], ThisReturnReg, VA); + Handler.assignValueToReg(ArgReg, ThisReturnRegs[Part], VA); continue; } diff --git a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp index 28b234b180fcc..4c4aed2f4ecdd 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp @@ -1130,7 +1130,7 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, if (!determineAndHandleAssignments( UsingReturnedArg ? ReturnedArgHandler : Handler, Assigner, InArgs, MIRBuilder, Info.CallConv, Info.IsVarArg, - UsingReturnedArg ? OutArgs[0].Regs[0] : Register())) + UsingReturnedArg ? makeArrayRef(OutArgs[0].Regs) : None)) return false; } diff --git a/llvm/test/CodeGen/AArch64/pr53315-returned-i128.ll b/llvm/test/CodeGen/AArch64/pr53315-returned-i128.ll new file mode 100644 index 0000000000000..0418720231288 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/pr53315-returned-i128.ll @@ -0,0 +1,25 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -O0 -mtriple=aarch64-unknown-linux-gnu -verify-machineinstrs < %s | FileCheck %s + +define void @test() nounwind { +; CHECK-LABEL: test: +; CHECK: // %bb.0: +; CHECK-NEXT: sub sp, sp, #32 +; CHECK-NEXT: str x30, [sp, #16] // 8-byte Folded Spill +; CHECK-NEXT: mov x1, xzr +; CHECK-NEXT: str x1, [sp, #8] // 8-byte Folded Spill +; CHECK-NEXT: mov x0, x1 +; CHECK-NEXT: bl returns_arg +; CHECK-NEXT: ldr x1, [sp, #8] // 8-byte Folded Reload +; CHECK-NEXT: mov x0, x1 +; CHECK-NEXT: bl accepts_arg +; CHECK-NEXT: ldr x30, [sp, #16] // 8-byte Folded Reload +; CHECK-NEXT: add sp, sp, #32 +; CHECK-NEXT: ret + %x = call i128 @returns_arg(i128 0) + call void @accepts_arg(i128 %x) + ret void +} + +declare i128 @returns_arg(i128 returned) +declare void @accepts_arg(i128)