diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt index c109b34df51..6028db68507 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -21,7 +21,6 @@ add_llvm_target(MipsCodeGen Mips16ISelDAGToDAG.cpp Mips16ISelLowering.cpp Mips16RegisterInfo.cpp - MipsABIInfo.cpp MipsAnalyzeImmediate.cpp MipsAsmPrinter.cpp MipsConstantIslandPass.cpp diff --git a/lib/Target/Mips/Mips16ISelLowering.cpp b/lib/Target/Mips/Mips16ISelLowering.cpp index d4852c4ece4..58f2d74f36a 100644 --- a/lib/Target/Mips/Mips16ISelLowering.cpp +++ b/lib/Target/Mips/Mips16ISelLowering.cpp @@ -244,9 +244,10 @@ Mips16TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, } } -bool Mips16TargetLowering::isEligibleForTailCallOptimization( - const CCState &CCInfo, unsigned NextStackOffset, - const MipsFunctionInfo &FI) const { +bool Mips16TargetLowering:: +isEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, + unsigned NextStackOffset, + const MipsFunctionInfo& FI) const { // No tail call optimization for mips16. return false; } diff --git a/lib/Target/Mips/Mips16ISelLowering.h b/lib/Target/Mips/Mips16ISelLowering.h index d3b9f750f34..4c21a919e71 100644 --- a/lib/Target/Mips/Mips16ISelLowering.h +++ b/lib/Target/Mips/Mips16ISelLowering.h @@ -31,9 +31,9 @@ namespace llvm { MachineBasicBlock *MBB) const override; private: - bool isEligibleForTailCallOptimization( - const CCState &CCInfo, unsigned NextStackOffset, - const MipsFunctionInfo &FI) const override; + bool isEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, + unsigned NextStackOffset, + const MipsFunctionInfo& FI) const override; void setMips16HardFloatLibCalls(); diff --git a/lib/Target/Mips/MipsABIInfo.cpp b/lib/Target/Mips/MipsABIInfo.cpp deleted file mode 100644 index 97e04b1d9f9..00000000000 --- a/lib/Target/Mips/MipsABIInfo.cpp +++ /dev/null @@ -1,29 +0,0 @@ -//===---- 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"); -} diff --git a/lib/Target/Mips/MipsABIInfo.h b/lib/Target/Mips/MipsABIInfo.h index 778b04d9ce7..c1d90a7c4f7 100644 --- a/lib/Target/Mips/MipsABIInfo.h +++ b/lib/Target/Mips/MipsABIInfo.h @@ -10,11 +10,7 @@ #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 }; @@ -38,8 +34,6 @@ public: 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. diff --git a/lib/Target/Mips/MipsCallingConv.td b/lib/Target/Mips/MipsCallingConv.td index 7e5c2a902f1..a2130bb67a0 100644 --- a/lib/Target/Mips/MipsCallingConv.td +++ b/lib/Target/Mips/MipsCallingConv.td @@ -279,6 +279,13 @@ def CC_Mips_FastCC : CallingConv<[ CCDelegateTo ]>; +//== + +def CC_Mips16RetHelper : CallingConv<[ + // Integer arguments are passed in integer registers. + CCIfType<[i32], CCAssignToReg<[V0, V1, A0, A1]>> +]>; + //===----------------------------------------------------------------------===// // Mips Calling Convention Dispatch //===----------------------------------------------------------------------===// @@ -290,29 +297,7 @@ def RetCC_Mips : CallingConv<[ 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. - // This presents us with a problem for the calling convention since hard-float - // still needs to pass them in FPU registers. We therefore resort to a - // pre-analyze (see PreAnalyzeFormalArgsForF128()) step to pass information on - // whether the argument was originally an f128 into the tablegen-erated code. - // - // f128 should only occur for the N64 ABI where long double is 128-bit. On - // N32, long double is equivalent to double. - CCIfType<[i64], - CCIfSubtargetNot<"abiUsesSoftFloat()", - CCIf<"static_cast(&State)->WasOriginalArgF128(ValNo)", - CCBitConvertToType>>>, - CCIfCC<"CallingConv::Fast", CCDelegateTo>, // FIXME: There wasn't an EABI case in the original code and it seems unlikely @@ -322,23 +307,12 @@ def CC_Mips_FixedArg : CallingConv<[ ]>; 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. //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index bc0924eac7f..c08367912aa 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -95,51 +95,10 @@ private: originalTypeIsF128(MF.getFunction()->getReturnType(), nullptr)); } - /// Identify lowered values that originated from f128 arguments and record - /// this. - void PreAnalyzeCallOperandsForF128( - const SmallVectorImpl &Outs, - std::vector &FuncArgs, SDNode *CallNode) { - for (unsigned i = 0; i < Outs.size(); ++i) - OriginalArgWasF128.push_back( - originalTypeIsF128(FuncArgs[Outs[i].OrigArgIndex].Ty, CallNode)); - } - - /// Identify lowered values that originated from f128 arguments and record - /// this. - void - PreAnalyzeFormalArgumentsForF128(const SmallVectorImpl &Ins) { - const MachineFunction &MF = getMachineFunction(); - for (unsigned i = 0; i < Ins.size(); ++i) { - Function::const_arg_iterator FuncArg = MF.getFunction()->arg_begin(); - std::advance(FuncArg, Ins[i].OrigArgIndex); - - OriginalArgWasF128.push_back( - originalTypeIsF128(FuncArg->getType(), nullptr)); - } - } - /// Records whether the value has been lowered from an f128. SmallVector OriginalArgWasF128; public: - // FIXME: Remove this from a public inteface ASAP. It's a temporary trap door - // to allow analyzeCallOperands to be removed incrementally. - void PreAnalyzeCallOperandsForF128_( - const SmallVectorImpl &Outs, - std::vector &FuncArgs, SDNode *CallNode) { - PreAnalyzeCallOperandsForF128(Outs, FuncArgs, CallNode); - } - // FIXME: Remove this from a public inteface ASAP. It's a temporary trap door - // to allow analyzeFormalArguments to be removed incrementally. - void - PreAnalyzeFormalArgumentsForF128_(const SmallVectorImpl &Ins) { - PreAnalyzeFormalArgumentsForF128(Ins); - } - // FIXME: Remove this from a public inteface ASAP. It's a temporary trap door - // to clean up after the above functions. - void ClearOriginalArgWasF128() { OriginalArgWasF128.clear(); } - MipsCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, SmallVectorImpl &locs, LLVMContext &C) : CCState(CC, isVarArg, MF, locs, C) {} @@ -2587,22 +2546,21 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // Analyze operands of the call, assigning locations to each operand. SmallVector ArgLocs; - MipsCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, - *DAG.getContext()); + CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, + *DAG.getContext()); MipsCC MipsCCInfo(CallConv, Subtarget, CCInfo); - CCInfo.PreAnalyzeCallOperandsForF128_(Outs, CLI.getArgs(), Callee.getNode()); MipsCCInfo.analyzeCallOperands(Outs, IsVarArg, Subtarget.abiUsesSoftFloat(), Callee.getNode(), CLI.getArgs(), CCInfo); - CCInfo.ClearOriginalArgWasF128(); // Get a count of how many bytes are to be pushed on the stack. unsigned NextStackOffset = CCInfo.getNextStackOffset(); // Check if it's really possible to do a tail call. if (IsTailCall) - IsTailCall = isEligibleForTailCallOptimization( - CCInfo, NextStackOffset, *MF.getInfo()); + IsTailCall = + isEligibleForTailCallOptimization(MipsCCInfo, NextStackOffset, + *MF.getInfo()); if (!IsTailCall && CLI.CS && CLI.CS->isMustTailCall()) report_fatal_error("failed to perform tail call elimination on a call " @@ -2628,8 +2586,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // With EABI is it possible to have 16 args on registers. std::deque< std::pair > RegsToPass; SmallVector MemOpChains; - - CCInfo.rewindByValRegsInfo(); + MipsCC::byval_iterator ByValArg = MipsCCInfo.byval_begin(); // Walk the register/memloc assignments, inserting copies/loads. for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { @@ -2640,19 +2597,14 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // ByVal Arg. if (Flags.isByVal()) { - unsigned FirstByValReg, LastByValReg; - unsigned ByValIdx = CCInfo.getInRegsParamsProcessed(); - CCInfo.getInRegsParamInfo(ByValIdx, FirstByValReg, LastByValReg); - assert(Flags.getByValSize() && "ByVal args of size 0 should have been ignored by front-end."); - assert(ByValIdx < CCInfo.getInRegsParamsCount()); + assert(ByValArg != MipsCCInfo.byval_end()); assert(!IsTailCall && "Do not tail-call optimize if there is a byval argument."); passByValArg(Chain, DL, RegsToPass, MemOpChains, StackPtr, MFI, DAG, Arg, - MipsCCInfo, FirstByValReg, LastByValReg, Flags, - Subtarget.isLittle(), VA); - CCInfo.nextInRegsParam(); + MipsCCInfo, *ByValArg, Flags, Subtarget.isLittle(), VA); + ++ByValArg; continue; } @@ -2680,9 +2632,6 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, } } break; - case CCValAssign::BCvt: - Arg = DAG.getNode(ISD::BITCAST, DL, LocVT, Arg); - break; case CCValAssign::SExt: Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, LocVT, Arg); break; @@ -2880,21 +2829,19 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, // Assign locations to all of the incoming arguments. SmallVector ArgLocs; - MipsCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, - *DAG.getContext()); + CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, + *DAG.getContext()); MipsCC MipsCCInfo(CallConv, Subtarget, CCInfo); Function::const_arg_iterator FuncArg = DAG.getMachineFunction().getFunction()->arg_begin(); bool UseSoftFloat = Subtarget.abiUsesSoftFloat(); - CCInfo.PreAnalyzeFormalArgumentsForF128_(Ins); - MipsCCInfo.analyzeFormalArguments(Ins, UseSoftFloat, CCInfo); - CCInfo.ClearOriginalArgWasF128(); + MipsCCInfo.analyzeFormalArguments(Ins, UseSoftFloat, FuncArg, CCInfo); MipsFI->setFormalArgInfo(CCInfo.getNextStackOffset(), - CCInfo.getInRegsParamsCount() > 0); + MipsCCInfo.hasByValArg()); unsigned CurArgIdx = 0; - CCInfo.rewindByValRegsInfo(); + MipsCC::byval_iterator ByValArg = MipsCCInfo.byval_begin(); for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; @@ -2905,16 +2852,12 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, bool IsRegLoc = VA.isRegLoc(); if (Flags.isByVal()) { - unsigned FirstByValReg, LastByValReg; - unsigned ByValIdx = CCInfo.getInRegsParamsProcessed(); - CCInfo.getInRegsParamInfo(ByValIdx, FirstByValReg, LastByValReg); - assert(Flags.getByValSize() && "ByVal args of size 0 should have been ignored by front-end."); - assert(ByValIdx < CCInfo.getInRegsParamsCount()); + assert(ByValArg != MipsCCInfo.byval_end()); copyByValRegs(Chain, DL, OutChains, DAG, Flags, InVals, &*FuncArg, - MipsCCInfo, FirstByValReg, LastByValReg, VA); - CCInfo.nextInRegsParam(); + MipsCCInfo, *ByValArg, VA); + ++ByValArg; continue; } @@ -2932,24 +2875,16 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, // If this is an 8 or 16-bit value, it has been passed promoted // to 32 bits. Insert an assert[sz]ext to capture this, then // truncate to the right size. - switch (VA.getLocInfo()) { - default: - llvm_unreachable("Unknown loc info!"); - case CCValAssign::Full: - break; - case CCValAssign::SExt: - ArgValue = DAG.getNode(ISD::AssertSext, DL, RegVT, ArgValue, - DAG.getValueType(ValVT)); + if (VA.getLocInfo() != CCValAssign::Full) { + unsigned Opcode = 0; + if (VA.getLocInfo() == CCValAssign::SExt) + Opcode = ISD::AssertSext; + else if (VA.getLocInfo() == CCValAssign::ZExt) + Opcode = ISD::AssertZext; + if (Opcode) + ArgValue = DAG.getNode(Opcode, DL, RegVT, ArgValue, + DAG.getValueType(ValVT)); ArgValue = DAG.getNode(ISD::TRUNCATE, DL, ValVT, ArgValue); - break; - case CCValAssign::ZExt: - ArgValue = DAG.getNode(ISD::AssertZext, DL, RegVT, ArgValue, - DAG.getValueType(ValVT)); - ArgValue = DAG.getNode(ISD::TRUNCATE, DL, ValVT, ArgValue); - break; - case CCValAssign::BCvt: - ArgValue = DAG.getNode(ISD::BITCAST, DL, ValVT, ArgValue); - break; } // Handle floating point arguments passed in integer registers and @@ -3621,10 +3556,18 @@ void MipsTargetLowering::MipsCC::analyzeCallOperands( 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 - R = FixedFn(I, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, State); + else { + MVT RegVT = getRegVT(ArgVT, FuncArgs[Args[I].OrigArgIndex].Ty, CallNode, + IsSoftFloat); + R = FixedFn(I, ArgVT, RegVT, CCValAssign::Full, ArgFlags, State); + } if (R) { #ifndef NDEBUG @@ -3638,14 +3581,24 @@ void MipsTargetLowering::MipsCC::analyzeCallOperands( void MipsTargetLowering::MipsCC::analyzeFormalArguments( const SmallVectorImpl &Args, bool IsSoftFloat, - CCState &State) { + Function::const_arg_iterator FuncArg, CCState &State) { unsigned NumArgs = Args.size(); + unsigned CurArgIdx = 0; for (unsigned I = 0; I != NumArgs; ++I) { MVT ArgVT = Args[I].VT; ISD::ArgFlagsTy ArgFlags = Args[I].Flags; + std::advance(FuncArg, Args[I].OrigArgIndex - CurArgIdx); + CurArgIdx = Args[I].OrigArgIndex; - if (!CC_Mips_FixedArg(I, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, State)) + if (ArgFlags.isByVal()) { + handleByValArg(I, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, State); + continue; + } + + MVT RegVT = getRegVT(ArgVT, FuncArg->getType(), nullptr, IsSoftFloat); + + if (!CC_Mips_FixedArg(I, ArgVT, RegVT, CCValAssign::Full, ArgFlags, State)) continue; #ifndef NDEBUG @@ -3656,6 +3609,30 @@ void MipsTargetLowering::MipsCC::analyzeFormalArguments( } } +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; } @@ -3666,6 +3643,35 @@ const ArrayRef MipsTargetLowering::MipsCC::intArgRegs() const { 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 { @@ -3684,20 +3690,19 @@ MVT MipsTargetLowering::MipsCC::getRegVT(MVT VT, const Type *OrigTy, void MipsTargetLowering::copyByValRegs( SDValue Chain, SDLoc DL, std::vector &OutChains, SelectionDAG &DAG, const ISD::ArgFlagsTy &Flags, SmallVectorImpl &InVals, - const Argument *FuncArg, const MipsCC &CC, unsigned FirstReg, - unsigned LastReg, const CCValAssign &VA) const { + const Argument *FuncArg, const MipsCC &CC, const ByValArgInfo &ByVal, + const CCValAssign &VA) const { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); unsigned GPRSizeInBytes = Subtarget.getGPRSizeInBytes(); - unsigned NumRegs = LastReg - FirstReg; - unsigned RegAreaSize = NumRegs * GPRSizeInBytes; + unsigned RegAreaSize = ByVal.NumRegs * GPRSizeInBytes; unsigned FrameObjSize = std::max(Flags.getByValSize(), RegAreaSize); int FrameObjOffset; if (RegAreaSize) FrameObjOffset = (int)CC.reservedArgArea() - - (int)((CC.intArgRegs().size() - FirstReg) * GPRSizeInBytes); + (int)((CC.intArgRegs().size() - ByVal.FirstIdx) * GPRSizeInBytes); else FrameObjOffset = VA.getLocMemOffset(); @@ -3707,15 +3712,15 @@ void MipsTargetLowering::copyByValRegs( SDValue FIN = DAG.getFrameIndex(FI, PtrTy); InVals.push_back(FIN); - if (!NumRegs) + if (!ByVal.NumRegs) return; // Copy arg registers. MVT RegTy = MVT::getIntegerVT(GPRSizeInBytes * 8); const TargetRegisterClass *RC = getRegClassFor(RegTy); - for (unsigned I = 0; I < NumRegs; ++I) { - unsigned ArgReg = CC.intArgRegs()[FirstReg + I]; + for (unsigned I = 0; I < ByVal.NumRegs; ++I) { + unsigned ArgReg = CC.intArgRegs()[ByVal.FirstIdx + I]; unsigned VReg = addLiveIn(MF, ArgReg, RC); unsigned Offset = I * GPRSizeInBytes; SDValue StorePtr = DAG.getNode(ISD::ADD, DL, PtrTy, FIN, @@ -3733,29 +3738,29 @@ void MipsTargetLowering::passByValArg( std::deque> &RegsToPass, SmallVectorImpl &MemOpChains, SDValue StackPtr, MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg, const MipsCC &CC, - unsigned FirstReg, unsigned LastReg, const ISD::ArgFlagsTy &Flags, - bool isLittle, const CCValAssign &VA) const { + const ByValArgInfo &ByVal, 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 (NumRegs) { + if (ByVal.NumRegs) { const ArrayRef ArgRegs = CC.intArgRegs(); - bool LeftoverBytes = (NumRegs * RegSizeInBytes > ByValSizeInBytes); + bool LeftoverBytes = (ByVal.NumRegs * RegSizeInBytes > ByValSizeInBytes); unsigned I = 0; // Copy words to registers. - for (; I < NumRegs - LeftoverBytes; ++I, OffsetInBytes += RegSizeInBytes) { + for (; I < ByVal.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[FirstReg + I]; + unsigned ArgReg = ArgRegs[ByVal.FirstIdx + I]; RegsToPass.push_back(std::make_pair(ArgReg, LoadVal)); } @@ -3765,6 +3770,9 @@ void MipsTargetLowering::passByValArg( // 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; @@ -3804,7 +3812,7 @@ void MipsTargetLowering::passByValArg( Alignment = std::min(Alignment, LoadSizeInBytes); } - unsigned ArgReg = ArgRegs[FirstReg + I]; + unsigned ArgReg = ArgRegs[ByVal.FirstIdx + I]; RegsToPass.push_back(std::make_pair(ArgReg, Val)); return; } @@ -3867,49 +3875,3 @@ void MipsTargetLowering::writeVarArgRegs(std::vector &OutChains, 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); -} diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index 9fae7af676e..ba73085161a 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -259,8 +259,6 @@ namespace llvm { } }; - void HandleByVal(CCState *, unsigned &, unsigned) const override; - protected: SDValue getGlobalReg(SelectionDAG &DAG, EVT Ty) const; @@ -341,6 +339,14 @@ namespace llvm { 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 { @@ -359,8 +365,12 @@ namespace llvm { CCState &State); void analyzeFormalArguments(const SmallVectorImpl &Ins, bool IsSoftFloat, + Function::const_arg_iterator FuncArg, 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; @@ -368,7 +378,24 @@ namespace llvm { /// 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. @@ -384,6 +411,7 @@ namespace llvm { CallingConv::ID CallConv; const MipsSubtarget &Subtarget; + SmallVector ByValArgs; }; protected: SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const; @@ -448,9 +476,9 @@ namespace llvm { /// isEligibleForTailCallOptimization - Check whether the call is eligible /// for tail call optimization. virtual bool - isEligibleForTailCallOptimization(const CCState &CCInfo, + isEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, 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 @@ -459,15 +487,14 @@ namespace llvm { SelectionDAG &DAG, const ISD::ArgFlagsTy &Flags, SmallVectorImpl &InVals, const Argument *FuncArg, const MipsCC &CC, - unsigned FirstReg, unsigned LastReg, - const CCValAssign &VA) const; + const ByValArgInfo &ByVal, 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, unsigned FirstReg, unsigned LastReg, + const MipsCC &CC, const ByValArgInfo &ByVal, const ISD::ArgFlagsTy &Flags, bool isLittle, const CCValAssign &VA) const; diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp index 4a0ce096edd..7417f6dc79f 100644 --- a/lib/Target/Mips/MipsSEISelLowering.cpp +++ b/lib/Target/Mips/MipsSEISelLowering.cpp @@ -1167,14 +1167,15 @@ MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, } } -bool MipsSETargetLowering::isEligibleForTailCallOptimization( - const CCState &CCInfo, unsigned NextStackOffset, - const MipsFunctionInfo &FI) const { +bool MipsSETargetLowering:: +isEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, + unsigned NextStackOffset, + const MipsFunctionInfo& FI) const { if (!EnableMipsTailCalls) return false; // Return false if either the callee or caller has a byval argument. - if (CCInfo.getInRegsParamsCount() > 0 || FI.hasByvalArg()) + if (MipsCCInfo.hasByValArg() || FI.hasByvalArg()) return false; // Return true if the callee's argument area is no larger than the diff --git a/lib/Target/Mips/MipsSEISelLowering.h b/lib/Target/Mips/MipsSEISelLowering.h index d44f8d82ec3..4ca94addf2c 100644 --- a/lib/Target/Mips/MipsSEISelLowering.h +++ b/lib/Target/Mips/MipsSEISelLowering.h @@ -51,9 +51,9 @@ namespace llvm { const TargetRegisterClass *getRepRegClassFor(MVT VT) const override; private: - bool isEligibleForTailCallOptimization( - const CCState &CCInfo, unsigned NextStackOffset, - const MipsFunctionInfo &FI) const override; + bool isEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, + unsigned NextStackOffset, + const MipsFunctionInfo& FI) const override; void getOpndList(SmallVectorImpl &Ops,