[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<Register> 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
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h b/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h
index 6bdaddd..66b800a 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h
@@ -382,12 +382,12 @@
/// \p Handler to move them to the assigned locations.
///
/// \return True if everything has succeeded, false otherwise.
- bool determineAndHandleAssignments(ValueHandler &Handler,
- ValueAssigner &Assigner,
- SmallVectorImpl<ArgInfo> &Args,
- MachineIRBuilder &MIRBuilder,
- CallingConv::ID CallConv, bool IsVarArg,
- Register ThisReturnReg = Register()) const;
+ bool
+ determineAndHandleAssignments(ValueHandler &Handler, ValueAssigner &Assigner,
+ SmallVectorImpl<ArgInfo> &Args,
+ MachineIRBuilder &MIRBuilder,
+ CallingConv::ID CallConv, bool IsVarArg,
+ ArrayRef<Register> 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 @@
CCState &CCState,
SmallVectorImpl<CCValAssign> &ArgLocs,
MachineIRBuilder &MIRBuilder,
- Register ThisReturnReg = Register()) const;
+ ArrayRef<Register> 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 d2cda9e..a68a5e2 100644
--- a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
@@ -518,7 +518,8 @@
bool CallLowering::determineAndHandleAssignments(
ValueHandler &Handler, ValueAssigner &Assigner,
SmallVectorImpl<ArgInfo> &Args, MachineIRBuilder &MIRBuilder,
- CallingConv::ID CallConv, bool IsVarArg, Register ThisReturnReg) const {
+ CallingConv::ID CallConv, bool IsVarArg,
+ ArrayRef<Register> ThisReturnRegs) const {
MachineFunction &MF = MIRBuilder.getMF();
const Function &F = MF.getFunction();
SmallVector<CCValAssign, 16> ArgLocs;
@@ -528,7 +529,7 @@
return false;
return handleAssignments(Handler, Args, CCInfo, ArgLocs, MIRBuilder,
- ThisReturnReg);
+ ThisReturnRegs);
}
static unsigned extendOpFromFlags(llvm::ISD::ArgFlagsTy Flags) {
@@ -605,7 +606,7 @@
CCState &CCInfo,
SmallVectorImpl<CCValAssign> &ArgLocs,
MachineIRBuilder &MIRBuilder,
- Register ThisReturnReg) const {
+ ArrayRef<Register> ThisReturnRegs) const {
MachineFunction &MF = MIRBuilder.getMF();
MachineRegisterInfo &MRI = MF.getRegInfo();
const Function &F = MF.getFunction();
@@ -732,10 +733,10 @@
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 28b234b..4c4aed2 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
@@ -1130,7 +1130,7 @@
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 0000000..0418720
--- /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)