Skip to content

Commit

Permalink
[AArch64][GlobalISel] Support returned argument with multiple registers
Browse files Browse the repository at this point in the history
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 llvm/llvm-project#53315.

Differential Revision: https://reviews.llvm.org/D117866
  • Loading branch information
nikic authored and memfrob committed Oct 4, 2022
1 parent 6109bd0 commit 6a3ba06
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 13 deletions.
14 changes: 7 additions & 7 deletions llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -388,12 +388,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<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
Expand All @@ -402,7 +402,7 @@ class CallLowering {
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
Expand Down
11 changes: 6 additions & 5 deletions llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,8 @@ static void buildCopyToRegs(MachineIRBuilder &B, ArrayRef<Register> DstRegs,
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;
Expand All @@ -519,7 +520,7 @@ bool CallLowering::determineAndHandleAssignments(
return false;

return handleAssignments(Handler, Args, CCInfo, ArgLocs, MIRBuilder,
ThisReturnReg);
ThisReturnRegs);
}

static unsigned extendOpFromFlags(llvm::ISD::ArgFlagsTy Flags) {
Expand Down Expand Up @@ -596,7 +597,7 @@ bool CallLowering::handleAssignments(ValueHandler &Handler,
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();
Expand Down Expand Up @@ -740,10 +741,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;
}

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1179,7 +1179,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;
}

Expand Down
25 changes: 25 additions & 0 deletions llvm/test/CodeGen/AArch64/pr53315-returned-i128.ll
Original file line number Diff line number Diff line change
@@ -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)

0 comments on commit 6a3ba06

Please sign in to comment.