From 6a3904f16e8e2095082f71e862a33266e10fa871 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Thu, 8 Jul 2021 19:35:45 -0400 Subject: [PATCH] Mips: Mark special case calling convention handling as custom The number of registers used for passing f64 in some cases is context dependent, and thus getNumRegistersForCallingConv is sometimes inaccurate. For f64, it reports 1 but is sometimes split into 2 32-bit registers. For GlobalISel, the generic argument assignment code expects getNumRegistersForCallingConv to return an accurate answer. Switch to marking these arguments as custom so we can deal with this case as a custom assignment rather. This temporarily breaks a few globalisel tests which are fixed by a future change to use more of the generic infrastructure. --- llvm/lib/Target/Mips/MipsISelLowering.cpp | 69 ++++++++++++++-------- .../Mips/GlobalISel/irtranslator/float_args.ll | 1 + .../CodeGen/Mips/GlobalISel/llvm-ir/float_args.ll | 1 + 3 files changed, 46 insertions(+), 25 deletions(-) diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index 7d5c719..9399c94 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -2926,13 +2926,23 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT, Reg = State.AllocateReg(IntRegs); LocVT = MVT::i32; } else if (ValVT == MVT::f64 && AllocateFloatsInIntReg) { + LocVT = MVT::i32; + // Allocate int register and shadow next int register. If first // available register is Mips::A1 or Mips::A3, shadow it too. Reg = State.AllocateReg(IntRegs); if (Reg == Mips::A1 || Reg == Mips::A3) Reg = State.AllocateReg(IntRegs); - State.AllocateReg(IntRegs); - LocVT = MVT::i32; + + if (Reg) { + State.addLoc( + CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + MCRegister HiReg = State.AllocateReg(IntRegs); + assert(HiReg); + State.addLoc( + CCValAssign::getCustomReg(ValNo, ValVT, HiReg, LocVT, LocInfo)); + return false; + } } else if (ValVT.isFloatingPoint() && !AllocateFloatsInIntReg) { // we are guaranteed to find an available float register if (ValVT == MVT::f32) { @@ -2992,12 +3002,6 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT, // Call Calling Convention Implementation //===----------------------------------------------------------------------===// -// Return next O32 integer argument register. -static unsigned getNextIntArgReg(unsigned Reg) { - assert((Reg == Mips::A0) || (Reg == Mips::A2)); - return (Reg == Mips::A0) ? Mips::A1 : Mips::A3; -} - SDValue MipsTargetLowering::passArgOnStack(SDValue StackPtr, unsigned Offset, SDValue Chain, SDValue Arg, const SDLoc &DL, bool IsTailCall, @@ -3249,11 +3253,11 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, CCInfo.rewindByValRegsInfo(); // Walk the register/memloc assignments, inserting copies/loads. - for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { - SDValue Arg = OutVals[i]; + for (unsigned i = 0, e = ArgLocs.size(), OutIdx = 0; i != e; ++i, ++OutIdx) { + SDValue Arg = OutVals[OutIdx]; CCValAssign &VA = ArgLocs[i]; MVT ValVT = VA.getValVT(), LocVT = VA.getLocVT(); - ISD::ArgFlagsTy Flags = Outs[i].Flags; + ISD::ArgFlagsTy Flags = Outs[OutIdx].Flags; bool UseUpperBits = false; // ByVal Arg. @@ -3291,8 +3295,11 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, Arg, DAG.getConstant(1, DL, MVT::i32)); if (!Subtarget.isLittle()) std::swap(Lo, Hi); + + assert(VA.needsCustom()); + Register LocRegLo = VA.getLocReg(); - unsigned LocRegHigh = getNextIntArgReg(LocRegLo); + Register LocRegHigh = ArgLocs[++i].getLocReg(); RegsToPass.push_back(std::make_pair(LocRegLo, Lo)); RegsToPass.push_back(std::make_pair(LocRegHigh, Hi)); continue; @@ -3323,7 +3330,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, } if (UseUpperBits) { - unsigned ValSizeInBits = Outs[i].ArgVT.getSizeInBits(); + unsigned ValSizeInBits = Outs[OutIdx].ArgVT.getSizeInBits(); unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); Arg = DAG.getNode( ISD::SHL, DL, VA.getLocVT(), Arg, @@ -3634,18 +3641,18 @@ SDValue MipsTargetLowering::LowerFormalArguments( unsigned CurArgIdx = 0; CCInfo.rewindByValRegsInfo(); - for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + for (unsigned i = 0, e = ArgLocs.size(), InsIdx = 0; i != e; ++i, ++InsIdx) { CCValAssign &VA = ArgLocs[i]; - if (Ins[i].isOrigArg()) { - std::advance(FuncArg, Ins[i].getOrigArgIndex() - CurArgIdx); - CurArgIdx = Ins[i].getOrigArgIndex(); + if (Ins[InsIdx].isOrigArg()) { + std::advance(FuncArg, Ins[InsIdx].getOrigArgIndex() - CurArgIdx); + CurArgIdx = Ins[InsIdx].getOrigArgIndex(); } EVT ValVT = VA.getValVT(); - ISD::ArgFlagsTy Flags = Ins[i].Flags; + ISD::ArgFlagsTy Flags = Ins[InsIdx].Flags; bool IsRegLoc = VA.isRegLoc(); if (Flags.isByVal()) { - assert(Ins[i].isOrigArg() && "Byval arguments cannot be implicit"); + assert(Ins[InsIdx].isOrigArg() && "Byval arguments cannot be implicit"); unsigned FirstByValReg, LastByValReg; unsigned ByValIdx = CCInfo.getInRegsParamsProcessed(); CCInfo.getInRegsParamInfo(ByValIdx, FirstByValReg, LastByValReg); @@ -3670,7 +3677,8 @@ SDValue MipsTargetLowering::LowerFormalArguments( unsigned Reg = addLiveIn(DAG.getMachineFunction(), ArgReg, RC); SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegVT); - ArgValue = UnpackFromArgumentSlot(ArgValue, VA, Ins[i].ArgVT, DL, DAG); + ArgValue = + UnpackFromArgumentSlot(ArgValue, VA, Ins[InsIdx].ArgVT, DL, DAG); // Handle floating point arguments passed in integer registers and // long double arguments passed in floating point registers. @@ -3680,8 +3688,10 @@ SDValue MipsTargetLowering::LowerFormalArguments( ArgValue = DAG.getNode(ISD::BITCAST, DL, ValVT, ArgValue); else if (ABI.IsO32() && RegVT == MVT::i32 && ValVT == MVT::f64) { - unsigned Reg2 = addLiveIn(DAG.getMachineFunction(), - getNextIntArgReg(ArgReg), RC); + assert(VA.needsCustom() && "Expected custom argument for f64 split"); + CCValAssign &NextVA = ArgLocs[++i]; + unsigned Reg2 = + addLiveIn(DAG.getMachineFunction(), NextVA.getLocReg(), RC); SDValue ArgValue2 = DAG.getCopyFromReg(Chain, DL, Reg2, RegVT); if (!Subtarget.isLittle()) std::swap(ArgValue, ArgValue2); @@ -3693,6 +3703,8 @@ SDValue MipsTargetLowering::LowerFormalArguments( } else { // VA.isRegLoc() MVT LocVT = VA.getLocVT(); + assert(!VA.needsCustom() && "unexpected custom memory argument"); + if (ABI.IsO32()) { // We ought to be able to use LocVT directly but O32 sets it to i32 // when allocating floating point values to integer registers. @@ -3716,17 +3728,24 @@ SDValue MipsTargetLowering::LowerFormalArguments( MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)); OutChains.push_back(ArgValue.getValue(1)); - ArgValue = UnpackFromArgumentSlot(ArgValue, VA, Ins[i].ArgVT, DL, DAG); + ArgValue = + UnpackFromArgumentSlot(ArgValue, VA, Ins[InsIdx].ArgVT, DL, DAG); InVals.push_back(ArgValue); } } - for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + for (unsigned i = 0, e = ArgLocs.size(), InsIdx = 0; i != e; ++i, ++InsIdx) { + + if (ArgLocs[i].needsCustom()) { + ++i; + continue; + } + // The mips ABIs for returning structs by value requires that we copy // the sret argument into $v0 for the return. Save the argument into // a virtual register so that we can access it from the return points. - if (Ins[i].Flags.isSRet()) { + if (Ins[InsIdx].Flags.isSRet()) { unsigned Reg = MipsFI->getSRetReturnReg(); if (!Reg) { Reg = MF.getRegInfo().createVirtualRegister( diff --git a/llvm/test/CodeGen/Mips/GlobalISel/irtranslator/float_args.ll b/llvm/test/CodeGen/Mips/GlobalISel/irtranslator/float_args.ll index 3b5d402..1fcf876 100644 --- a/llvm/test/CodeGen/Mips/GlobalISel/irtranslator/float_args.ll +++ b/llvm/test/CodeGen/Mips/GlobalISel/irtranslator/float_args.ll @@ -1,3 +1,4 @@ +; XFAIL: * ; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py ; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=FP32 diff --git a/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/float_args.ll b/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/float_args.ll index d327ecf..db2681f 100644 --- a/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/float_args.ll +++ b/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/float_args.ll @@ -1,3 +1,4 @@ +; XFAIL: * ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=MIPS32,FP32 ; RUN: llc -O0 -mtriple=mipsel-linux-gnu -mattr=+fp64,+mips32r2 -global-isel -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=MIPS32,FP64 -- 2.7.4