Index: lib/Target/Mips/CMakeLists.txt =================================================================== --- lib/Target/Mips/CMakeLists.txt +++ lib/Target/Mips/CMakeLists.txt @@ -21,6 +21,7 @@ Mips16ISelDAGToDAG.cpp Mips16ISelLowering.cpp Mips16RegisterInfo.cpp + MipsABIInfo.cpp MipsAnalyzeImmediate.cpp MipsAsmPrinter.cpp MipsConstantIslandPass.cpp Index: lib/Target/Mips/Mips16ISelLowering.h =================================================================== --- lib/Target/Mips/Mips16ISelLowering.h +++ lib/Target/Mips/Mips16ISelLowering.h @@ -31,9 +31,9 @@ MachineBasicBlock *MBB) const override; private: - bool isEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, - unsigned NextStackOffset, - const MipsFunctionInfo& FI) const override; + bool isEligibleForTailCallOptimization( + const CCState &CCInfo, unsigned NextStackOffset, + const MipsFunctionInfo &FI) const override; void setMips16HardFloatLibCalls(); Index: lib/Target/Mips/Mips16ISelLowering.cpp =================================================================== --- lib/Target/Mips/Mips16ISelLowering.cpp +++ lib/Target/Mips/Mips16ISelLowering.cpp @@ -244,10 +244,9 @@ } } -bool Mips16TargetLowering:: -isEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, - unsigned NextStackOffset, - const MipsFunctionInfo& FI) const { +bool Mips16TargetLowering::isEligibleForTailCallOptimization( + const CCState &CCInfo, unsigned NextStackOffset, + const MipsFunctionInfo &FI) const { // No tail call optimization for mips16. return false; } Index: lib/Target/Mips/MipsABIInfo.h =================================================================== --- lib/Target/Mips/MipsABIInfo.h +++ lib/Target/Mips/MipsABIInfo.h @@ -10,7 +10,11 @@ #ifndef MIPSABIINFO_H #define MIPSABIINFO_H +#include "llvm/ADT/ArrayRef.h" +#include "llvm/MC/MCRegisterInfo.h" + namespace llvm { + class MipsABIInfo { public: enum class ABI { Unknown, O32, N32, N64, EABI }; @@ -34,6 +38,8 @@ bool IsEABI() const { return ThisABI == ABI::EABI; } ABI GetEnumValue() const { return ThisABI; } + const ArrayRef GetByValArgRegs() const; + /// Ordering of ABI's /// MipsGenSubtargetInfo.inc will use this to resolve conflicts when given /// multiple ABI options. Index: lib/Target/Mips/MipsABIInfo.cpp =================================================================== --- /dev/null +++ lib/Target/Mips/MipsABIInfo.cpp @@ -0,0 +1,29 @@ +//===---- MipsABIInfo.cpp - Information about MIPS ABI's ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MipsABIInfo.h" +#include "MipsRegisterInfo.h" + +using namespace llvm; + +namespace { +static const MCPhysReg O32IntRegs[4] = {Mips::A0, Mips::A1, Mips::A2, Mips::A3}; + +static const MCPhysReg Mips64IntRegs[8] = { + Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64, + Mips::T0_64, Mips::T1_64, Mips::T2_64, Mips::T3_64}; +} + +const ArrayRef MipsABIInfo::GetByValArgRegs() const { + if (IsO32()) + return makeArrayRef(O32IntRegs); + if (IsN32() || IsN64()) + return makeArrayRef(Mips64IntRegs); + llvm_unreachable("Unhandled ABI"); +} Index: lib/Target/Mips/MipsCallingConv.td =================================================================== --- lib/Target/Mips/MipsCallingConv.td +++ lib/Target/Mips/MipsCallingConv.td @@ -279,13 +279,6 @@ CCDelegateTo ]>; -//== - -def CC_Mips16RetHelper : CallingConv<[ - // Integer arguments are passed in integer registers. - CCIfType<[i32], CCAssignToReg<[V0, V1, A0, A1]>> -]>; - //===----------------------------------------------------------------------===// // Mips Calling Convention Dispatch //===----------------------------------------------------------------------===// @@ -297,7 +290,14 @@ CCDelegateTo ]>; +def CC_Mips_ByVal : CallingConv<[ + CCIfSubtarget<"isABI_O32()", CCIfByVal>>, + CCIfByVal> +]>; + def CC_Mips_FixedArg : CallingConv<[ + CCIfByVal>, + // f128 needs to be handled similarly to f32 and f64 on hard-float. However, // f128 is not legal and is lowered to i128 which is further lowered to a pair // of i64's. @@ -322,12 +322,23 @@ ]>; def CC_Mips_VarArg : CallingConv<[ + CCIfByVal>, + // FIXME: There wasn't an EABI case in the original code and it seems unlikely // that it's the same as CC_MipsN_VarArg CCIfSubtarget<"isABI_O32()", CCDelegateTo>, CCDelegateTo ]>; +//== + +def CC_Mips16RetHelper : CallingConv<[ + CCIfByVal>, + + // Integer arguments are passed in integer registers. + CCIfType<[i32], CCAssignToReg<[V0, V1, A0, A1]>> +]>; + //===----------------------------------------------------------------------===// // Callee-saved register lists. //===----------------------------------------------------------------------===// Index: lib/Target/Mips/MipsISelLowering.h =================================================================== --- lib/Target/Mips/MipsISelLowering.h +++ lib/Target/Mips/MipsISelLowering.h @@ -259,6 +259,8 @@ } }; + void HandleByVal(CCState *, unsigned &, unsigned) const override; + protected: SDValue getGlobalReg(SelectionDAG &DAG, EVT Ty) const; @@ -339,14 +341,6 @@ bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const; - /// ByValArgInfo - Byval argument information. - struct ByValArgInfo { - unsigned FirstIdx; // Index of the first register used. - unsigned NumRegs; // Number of registers used for this argument. - - ByValArgInfo() : FirstIdx(0), NumRegs(0) {} - }; - /// MipsCC - This class provides methods used to analyze formal and call /// arguments and inquire about calling convention information. class MipsCC { @@ -367,9 +361,6 @@ bool IsSoftFloat, CCState &State); - /// hasByValArg - Returns true if function has byval arguments. - bool hasByValArg() const { return !ByValArgs.empty(); } - /// reservedArgArea - The size of the area the caller reserves for /// register arguments. This is 16-byte if ABI is O32. unsigned reservedArgArea() const; @@ -377,24 +368,7 @@ /// Return pointer to array of integer argument registers. const ArrayRef intArgRegs() const; - typedef SmallVectorImpl::const_iterator byval_iterator; - byval_iterator byval_begin() const { return ByValArgs.begin(); } - byval_iterator byval_end() const { return ByValArgs.end(); } - private: - void handleByValArg(unsigned ValNo, MVT ValVT, MVT LocVT, - CCValAssign::LocInfo LocInfo, - ISD::ArgFlagsTy ArgFlags, CCState &State); - - /// useRegsForByval - Returns true if the calling convention allows the - /// use of registers to pass byval arguments. - bool useRegsForByval() const { return CallConv != CallingConv::Fast; } - - const MCPhysReg *shadowRegs() const; - - void allocateRegs(ByValArgInfo &ByVal, unsigned ByValSize, unsigned Align, - CCState &State); - /// Return the type of the register which is used to pass an argument or /// return a value. This function returns f64 if the argument is an i64 /// value which has been generated as a result of softening an f128 value. @@ -406,7 +380,6 @@ CallingConv::ID CallConv; const MipsSubtarget &Subtarget; - SmallVector ByValArgs; }; protected: SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const; @@ -471,9 +444,9 @@ /// isEligibleForTailCallOptimization - Check whether the call is eligible /// for tail call optimization. virtual bool - isEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, + isEligibleForTailCallOptimization(const CCState &CCInfo, unsigned NextStackOffset, - const MipsFunctionInfo& FI) const = 0; + const MipsFunctionInfo &FI) const = 0; /// copyByValArg - Copy argument registers which were used to pass a byval /// argument to the stack. Create a stack frame object for the byval @@ -482,14 +455,15 @@ SelectionDAG &DAG, const ISD::ArgFlagsTy &Flags, SmallVectorImpl &InVals, const Argument *FuncArg, const MipsCC &CC, - const ByValArgInfo &ByVal, const CCValAssign &VA) const; + unsigned FirstReg, unsigned LastReg, + const CCValAssign &VA) const; /// passByValArg - Pass a byval argument in registers or on stack. void passByValArg(SDValue Chain, SDLoc DL, std::deque> &RegsToPass, SmallVectorImpl &MemOpChains, SDValue StackPtr, MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg, - const MipsCC &CC, const ByValArgInfo &ByVal, + const MipsCC &CC, unsigned FirstReg, unsigned LastReg, const ISD::ArgFlagsTy &Flags, bool isLittle, const CCValAssign &VA) const; Index: lib/Target/Mips/MipsISelLowering.cpp =================================================================== --- lib/Target/Mips/MipsISelLowering.cpp +++ lib/Target/Mips/MipsISelLowering.cpp @@ -2602,9 +2602,8 @@ // Check if it's really possible to do a tail call. if (IsTailCall) - IsTailCall = - isEligibleForTailCallOptimization(MipsCCInfo, NextStackOffset, - *MF.getInfo()); + IsTailCall = isEligibleForTailCallOptimization( + CCInfo, NextStackOffset, *MF.getInfo()); if (!IsTailCall && CLI.CS && CLI.CS->isMustTailCall()) report_fatal_error("failed to perform tail call elimination on a call " @@ -2630,7 +2629,8 @@ // With EABI is it possible to have 16 args on registers. std::deque< std::pair > RegsToPass; SmallVector MemOpChains; - MipsCC::byval_iterator ByValArg = MipsCCInfo.byval_begin(); + + CCInfo.rewindByValRegsInfo(); // Walk the register/memloc assignments, inserting copies/loads. for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { @@ -2641,14 +2641,19 @@ // ByVal Arg. if (Flags.isByVal()) { + unsigned FirstByValReg, LastByValReg; + unsigned ByValIdx = CCInfo.getInRegsParamsProceed(); + CCInfo.getInRegsParamInfo(ByValIdx, FirstByValReg, LastByValReg); + assert(Flags.getByValSize() && "ByVal args of size 0 should have been ignored by front-end."); - assert(ByValArg != MipsCCInfo.byval_end()); + assert(ByValIdx < CCInfo.getInRegsParamsCount()); assert(!IsTailCall && "Do not tail-call optimize if there is a byval argument."); passByValArg(Chain, DL, RegsToPass, MemOpChains, StackPtr, MFI, DAG, Arg, - MipsCCInfo, *ByValArg, Flags, Subtarget.isLittle(), VA); - ++ByValArg; + MipsCCInfo, FirstByValReg, LastByValReg, Flags, + Subtarget.isLittle(), VA); + CCInfo.nextInRegsParam(); continue; } @@ -2887,10 +2892,10 @@ MipsCCInfo.analyzeFormalArguments(Ins, UseSoftFloat, CCInfo); CCInfo.ClearOriginalArgWasF128(); MipsFI->setFormalArgInfo(CCInfo.getNextStackOffset(), - MipsCCInfo.hasByValArg()); + CCInfo.getInRegsParamsCount() > 0); unsigned CurArgIdx = 0; - MipsCC::byval_iterator ByValArg = MipsCCInfo.byval_begin(); + CCInfo.rewindByValRegsInfo(); for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; @@ -2901,12 +2906,16 @@ bool IsRegLoc = VA.isRegLoc(); if (Flags.isByVal()) { + unsigned FirstByValReg, LastByValReg; + unsigned ByValIdx = CCInfo.getInRegsParamsProceed(); + CCInfo.getInRegsParamInfo(ByValIdx, FirstByValReg, LastByValReg); + assert(Flags.getByValSize() && "ByVal args of size 0 should have been ignored by front-end."); - assert(ByValArg != MipsCCInfo.byval_end()); + assert(ByValIdx < CCInfo.getInRegsParamsCount()); copyByValRegs(Chain, DL, OutChains, DAG, Flags, InVals, &*FuncArg, - MipsCCInfo, *ByValArg, VA); - ++ByValArg; + MipsCCInfo, FirstByValReg, LastByValReg, VA); + CCInfo.nextInRegsParam(); continue; } @@ -3612,11 +3621,6 @@ ISD::ArgFlagsTy ArgFlags = Args[I].Flags; bool R; - if (ArgFlags.isByVal()) { - handleByValArg(I, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, State); - continue; - } - if (IsVarArg && !Args[I].IsFixed) R = CC_Mips_VarArg(I, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, State); else @@ -3641,11 +3645,6 @@ MVT ArgVT = Args[I].VT; ISD::ArgFlagsTy ArgFlags = Args[I].Flags; - if (ArgFlags.isByVal()) { - handleByValArg(I, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, State); - continue; - } - if (!CC_Mips_FixedArg(I, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, State)) continue; @@ -3657,30 +3656,6 @@ } } -void MipsTargetLowering::MipsCC::handleByValArg(unsigned ValNo, MVT ValVT, - MVT LocVT, - CCValAssign::LocInfo LocInfo, - ISD::ArgFlagsTy ArgFlags, - CCState &State) { - assert(ArgFlags.getByValSize() && "Byval argument's size shouldn't be 0."); - - struct ByValArgInfo ByVal; - unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); - unsigned ByValSize = - RoundUpToAlignment(ArgFlags.getByValSize(), RegSizeInBytes); - unsigned Align = std::min(std::max(ArgFlags.getByValAlign(), RegSizeInBytes), - RegSizeInBytes * 2); - - if (useRegsForByval()) - allocateRegs(ByVal, ByValSize, Align, State); - - // Allocate space on caller's stack. - unsigned Offset = - State.AllocateStack(ByValSize - RegSizeInBytes * ByVal.NumRegs, Align); - State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); - ByValArgs.push_back(ByVal); -} - unsigned MipsTargetLowering::MipsCC::reservedArgArea() const { return (Subtarget.isABI_O32() && (CallConv != CallingConv::Fast)) ? 16 : 0; } @@ -3691,35 +3666,6 @@ return makeArrayRef(Mips64IntRegs); } -const MCPhysReg *MipsTargetLowering::MipsCC::shadowRegs() const { - return Subtarget.isABI_O32() ? O32IntRegs : Mips64DPRegs; -} - -void MipsTargetLowering::MipsCC::allocateRegs(ByValArgInfo &ByVal, - unsigned ByValSize, - unsigned Align, CCState &State) { - unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); - const ArrayRef IntArgRegs = intArgRegs(); - const MCPhysReg *ShadowRegs = shadowRegs(); - assert(!(ByValSize % RegSizeInBytes) && !(Align % RegSizeInBytes) && - "Byval argument's size and alignment should be a multiple of" - "RegSizeInBytes."); - - ByVal.FirstIdx = - State.getFirstUnallocated(IntArgRegs.data(), IntArgRegs.size()); - - // If Align > RegSizeInBytes, the first arg register must be even. - if ((Align > RegSizeInBytes) && (ByVal.FirstIdx % 2)) { - State.AllocateReg(IntArgRegs[ByVal.FirstIdx], ShadowRegs[ByVal.FirstIdx]); - ++ByVal.FirstIdx; - } - - // Mark the registers allocated. - for (unsigned I = ByVal.FirstIdx; ByValSize && (I < IntArgRegs.size()); - ByValSize -= RegSizeInBytes, ++I, ++ByVal.NumRegs) - State.AllocateReg(IntArgRegs[I], ShadowRegs[I]); -} - MVT MipsTargetLowering::MipsCC::getRegVT(MVT VT, const Type *OrigTy, const SDNode *CallNode, bool IsSoftFloat) const { @@ -3738,19 +3684,20 @@ void MipsTargetLowering::copyByValRegs( SDValue Chain, SDLoc DL, std::vector &OutChains, SelectionDAG &DAG, const ISD::ArgFlagsTy &Flags, SmallVectorImpl &InVals, - const Argument *FuncArg, const MipsCC &CC, const ByValArgInfo &ByVal, - const CCValAssign &VA) const { + const Argument *FuncArg, const MipsCC &CC, unsigned FirstReg, + unsigned LastReg, const CCValAssign &VA) const { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); unsigned GPRSizeInBytes = Subtarget.getGPRSizeInBytes(); - unsigned RegAreaSize = ByVal.NumRegs * GPRSizeInBytes; + unsigned NumRegs = LastReg - FirstReg; + unsigned RegAreaSize = NumRegs * GPRSizeInBytes; unsigned FrameObjSize = std::max(Flags.getByValSize(), RegAreaSize); int FrameObjOffset; if (RegAreaSize) FrameObjOffset = (int)CC.reservedArgArea() - - (int)((CC.intArgRegs().size() - ByVal.FirstIdx) * GPRSizeInBytes); + (int)((CC.intArgRegs().size() - FirstReg) * GPRSizeInBytes); else FrameObjOffset = VA.getLocMemOffset(); @@ -3760,15 +3707,15 @@ SDValue FIN = DAG.getFrameIndex(FI, PtrTy); InVals.push_back(FIN); - if (!ByVal.NumRegs) + if (!NumRegs) return; // Copy arg registers. MVT RegTy = MVT::getIntegerVT(GPRSizeInBytes * 8); const TargetRegisterClass *RC = getRegClassFor(RegTy); - for (unsigned I = 0; I < ByVal.NumRegs; ++I) { - unsigned ArgReg = CC.intArgRegs()[ByVal.FirstIdx + I]; + for (unsigned I = 0; I < NumRegs; ++I) { + unsigned ArgReg = CC.intArgRegs()[FirstReg + I]; unsigned VReg = addLiveIn(MF, ArgReg, RC); unsigned Offset = I * GPRSizeInBytes; SDValue StorePtr = DAG.getNode(ISD::ADD, DL, PtrTy, FIN, @@ -3786,29 +3733,29 @@ std::deque> &RegsToPass, SmallVectorImpl &MemOpChains, SDValue StackPtr, MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg, const MipsCC &CC, - const ByValArgInfo &ByVal, const ISD::ArgFlagsTy &Flags, bool isLittle, - const CCValAssign &VA) const { + unsigned FirstReg, unsigned LastReg, const ISD::ArgFlagsTy &Flags, + bool isLittle, const CCValAssign &VA) const { unsigned ByValSizeInBytes = Flags.getByValSize(); unsigned OffsetInBytes = 0; // From beginning of struct unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); unsigned Alignment = std::min(Flags.getByValAlign(), RegSizeInBytes); EVT PtrTy = getPointerTy(), RegTy = MVT::getIntegerVT(RegSizeInBytes * 8); + unsigned NumRegs = LastReg - FirstReg; - if (ByVal.NumRegs) { + if (NumRegs) { const ArrayRef ArgRegs = CC.intArgRegs(); - bool LeftoverBytes = (ByVal.NumRegs * RegSizeInBytes > ByValSizeInBytes); + bool LeftoverBytes = (NumRegs * RegSizeInBytes > ByValSizeInBytes); unsigned I = 0; // Copy words to registers. - for (; I < ByVal.NumRegs - LeftoverBytes; - ++I, OffsetInBytes += RegSizeInBytes) { + for (; I < NumRegs - LeftoverBytes; ++I, OffsetInBytes += RegSizeInBytes) { SDValue LoadPtr = DAG.getNode(ISD::ADD, DL, PtrTy, Arg, DAG.getConstant(OffsetInBytes, PtrTy)); SDValue LoadVal = DAG.getLoad(RegTy, DL, Chain, LoadPtr, MachinePointerInfo(), false, false, false, Alignment); MemOpChains.push_back(LoadVal.getValue(1)); - unsigned ArgReg = ArgRegs[ByVal.FirstIdx + I]; + unsigned ArgReg = ArgRegs[FirstReg + I]; RegsToPass.push_back(std::make_pair(ArgReg, LoadVal)); } @@ -3818,9 +3765,6 @@ // Copy the remainder of the byval argument with sub-word loads and shifts. if (LeftoverBytes) { - assert((ByValSizeInBytes > OffsetInBytes) && - (ByValSizeInBytes < OffsetInBytes + RegSizeInBytes) && - "Size of the remainder should be smaller than RegSizeInBytes."); SDValue Val; for (unsigned LoadSizeInBytes = RegSizeInBytes / 2, TotalBytesLoaded = 0; @@ -3860,7 +3804,7 @@ Alignment = std::min(Alignment, LoadSizeInBytes); } - unsigned ArgReg = ArgRegs[ByVal.FirstIdx + I]; + unsigned ArgReg = ArgRegs[FirstReg + I]; RegsToPass.push_back(std::make_pair(ArgReg, Val)); return; } @@ -3923,3 +3867,49 @@ OutChains.push_back(Store); } } + +void MipsTargetLowering::HandleByVal(CCState *State, unsigned &Size, + unsigned Align) const { + MachineFunction &MF = State->getMachineFunction(); + const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); + + assert(Size && "Byval argument's size shouldn't be 0."); + + Align = std::min(Align, TFL->getStackAlignment()); + + unsigned FirstReg = 0; + unsigned NumRegs = 0; + + if (State->getCallingConv() != CallingConv::Fast) { + unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); + const ArrayRef IntArgRegs = Subtarget.getABI().GetByValArgRegs(); + // FIXME: The O32 case actually describes no shadow registers. + const MCPhysReg *ShadowRegs = + Subtarget.isABI_O32() ? IntArgRegs.data() : Mips64DPRegs; + + // We used to check the size as well but we can't do that anymore since + // CCState::HandleByVal() rounds up the size after calling this function. + assert(!(Align % RegSizeInBytes) && + "Byval argument's alignment should be a multiple of" + "RegSizeInBytes."); + + FirstReg = State->getFirstUnallocated(IntArgRegs.data(), IntArgRegs.size()); + + // If Align > RegSizeInBytes, the first arg register must be even. + // FIXME: This condition happens to do the right thing but it's not the + // right way to test it. We want to check that the stack frame offset + // of the register is aligned. + if ((Align > RegSizeInBytes) && (FirstReg % 2)) { + State->AllocateReg(IntArgRegs[FirstReg], ShadowRegs[FirstReg]); + ++FirstReg; + } + + // Mark the registers allocated. + Size = RoundUpToAlignment(Size, RegSizeInBytes); + for (unsigned I = FirstReg; Size > 0 && (I < IntArgRegs.size()); + Size -= RegSizeInBytes, ++I, ++NumRegs) + State->AllocateReg(IntArgRegs[I], ShadowRegs[I]); + } + + State->addInRegsParamInfo(FirstReg, FirstReg + NumRegs); +} Index: lib/Target/Mips/MipsSEISelLowering.h =================================================================== --- lib/Target/Mips/MipsSEISelLowering.h +++ lib/Target/Mips/MipsSEISelLowering.h @@ -51,9 +51,9 @@ const TargetRegisterClass *getRepRegClassFor(MVT VT) const override; private: - bool isEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, - unsigned NextStackOffset, - const MipsFunctionInfo& FI) const override; + bool isEligibleForTailCallOptimization( + const CCState &CCInfo, unsigned NextStackOffset, + const MipsFunctionInfo &FI) const override; void getOpndList(SmallVectorImpl &Ops, Index: lib/Target/Mips/MipsSEISelLowering.cpp =================================================================== --- lib/Target/Mips/MipsSEISelLowering.cpp +++ lib/Target/Mips/MipsSEISelLowering.cpp @@ -1167,15 +1167,14 @@ } } -bool MipsSETargetLowering:: -isEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, - unsigned NextStackOffset, - const MipsFunctionInfo& FI) const { +bool MipsSETargetLowering::isEligibleForTailCallOptimization( + const CCState &CCInfo, unsigned NextStackOffset, + const MipsFunctionInfo &FI) const { if (!EnableMipsTailCalls) return false; // Return false if either the callee or caller has a byval argument. - if (MipsCCInfo.hasByValArg() || FI.hasByvalArg()) + if (CCInfo.getInRegsParamsCount() > 0 || FI.hasByvalArg()) return false; // Return true if the callee's argument area is no larger than the