Index: llvm/lib/Target/Mips/MipsISelLowering.cpp =================================================================== --- llvm/lib/Target/Mips/MipsISelLowering.cpp +++ llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -2926,13 +2926,23 @@ 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 @@ // 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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ } 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 @@ 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( Index: llvm/test/CodeGen/Mips/GlobalISel/irtranslator/float_args.ll =================================================================== --- llvm/test/CodeGen/Mips/GlobalISel/irtranslator/float_args.ll +++ 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 Index: llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/float_args.ll =================================================================== --- llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/float_args.ll +++ 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