From: Daniel Sanders Date: Sun, 2 Nov 2014 16:09:29 +0000 (+0000) Subject: Re-commit r221056 and others with fix, "[mips] Move F128 argument handling into MipsC... X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=eaa221a23e1326a5fcf5fde57b4e932b6040e8a3 Re-commit r221056 and others with fix, "[mips] Move F128 argument handling into MipsCCState as we did for returns. NFC." sret arguments can never originate from an f128 argument so we detect sret arguments and push false into OriginalArgWasF128. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@221102 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt index 6028db68507..c109b34df51 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -21,6 +21,7 @@ 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 58f2d74f36a..d4852c4ece4 100644 --- a/lib/Target/Mips/Mips16ISelLowering.cpp +++ b/lib/Target/Mips/Mips16ISelLowering.cpp @@ -244,10 +244,9 @@ Mips16TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, } } -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; } diff --git a/lib/Target/Mips/Mips16ISelLowering.h b/lib/Target/Mips/Mips16ISelLowering.h index 4c21a919e71..d3b9f750f34 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 MipsCC &MipsCCInfo, - unsigned NextStackOffset, - const MipsFunctionInfo& FI) const override; + bool isEligibleForTailCallOptimization( + const CCState &CCInfo, unsigned NextStackOffset, + const MipsFunctionInfo &FI) const override; void setMips16HardFloatLibCalls(); diff --git a/lib/Target/Mips/MipsABIInfo.cpp b/lib/Target/Mips/MipsABIInfo.cpp new file mode 100644 index 00000000000..97e04b1d9f9 --- /dev/null +++ b/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"); +} diff --git a/lib/Target/Mips/MipsABIInfo.h b/lib/Target/Mips/MipsABIInfo.h index c1d90a7c4f7..778b04d9ce7 100644 --- a/lib/Target/Mips/MipsABIInfo.h +++ b/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 @@ 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 a2130bb67a0..7e5c2a902f1 100644 --- a/lib/Target/Mips/MipsCallingConv.td +++ b/lib/Target/Mips/MipsCallingConv.td @@ -279,13 +279,6 @@ 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 //===----------------------------------------------------------------------===// @@ -297,7 +290,29 @@ 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 @@ -307,12 +322,23 @@ 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 c08367912aa..ef78df55f72 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -95,10 +95,60 @@ 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(); + + // SRet arguments cannot originate from f128 or {f128} returns so we just + // push false. We have to handle this specially since SRet arguments + // aren't mapped to an original argument. + if (Ins[i].Flags.isSRet()) { + OriginalArgWasF128.push_back(false); + continue; + } + + assert(Ins[i].OrigArgIndex < MF.getFunction()->arg_size()); + 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) {} @@ -2546,21 +2596,22 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // Analyze operands of the call, assigning locations to each operand. SmallVector ArgLocs; - CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, - *DAG.getContext()); + MipsCCState 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(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 " @@ -2586,7 +2637,8 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // 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) { @@ -2597,14 +2649,19 @@ 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(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; } @@ -2632,6 +2689,9 @@ 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; @@ -2829,19 +2889,21 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, // Assign locations to all of the incoming arguments. SmallVector ArgLocs; - CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, - *DAG.getContext()); + MipsCCState 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(); - MipsCCInfo.analyzeFormalArguments(Ins, UseSoftFloat, FuncArg, CCInfo); + CCInfo.PreAnalyzeFormalArgumentsForF128_(Ins); + 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]; @@ -2852,12 +2914,16 @@ 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(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; } @@ -2875,16 +2941,24 @@ 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. - 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)); + 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)); + 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 @@ -3556,18 +3630,10 @@ 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 { - MVT RegVT = getRegVT(ArgVT, FuncArgs[Args[I].OrigArgIndex].Ty, CallNode, - IsSoftFloat); - R = FixedFn(I, ArgVT, RegVT, CCValAssign::Full, ArgFlags, State); - } + else + R = FixedFn(I, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, State); if (R) { #ifndef NDEBUG @@ -3581,24 +3647,14 @@ void MipsTargetLowering::MipsCC::analyzeCallOperands( void MipsTargetLowering::MipsCC::analyzeFormalArguments( const SmallVectorImpl &Args, bool IsSoftFloat, - Function::const_arg_iterator FuncArg, CCState &State) { + 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 (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)) + if (!CC_Mips_FixedArg(I, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, State)) continue; #ifndef NDEBUG @@ -3609,30 +3665,6 @@ 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; } @@ -3643,35 +3675,6 @@ 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 { @@ -3690,19 +3693,20 @@ 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, 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(); @@ -3712,15 +3716,15 @@ void MipsTargetLowering::copyByValRegs( 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, @@ -3738,29 +3742,29 @@ void MipsTargetLowering::passByValArg( 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)); } @@ -3770,9 +3774,6 @@ 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; @@ -3812,7 +3813,7 @@ void MipsTargetLowering::passByValArg( 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; } @@ -3875,3 +3876,49 @@ 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 ba73085161a..9fae7af676e 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -259,6 +259,8 @@ namespace llvm { } }; + void HandleByVal(CCState *, unsigned &, unsigned) const override; + protected: SDValue getGlobalReg(SelectionDAG &DAG, EVT Ty) const; @@ -339,14 +341,6 @@ 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 { @@ -365,12 +359,8 @@ 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; @@ -378,24 +368,7 @@ 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. @@ -411,7 +384,6 @@ namespace llvm { CallingConv::ID CallConv; const MipsSubtarget &Subtarget; - SmallVector ByValArgs; }; protected: SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const; @@ -476,9 +448,9 @@ namespace llvm { /// 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 @@ -487,14 +459,15 @@ namespace llvm { 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; diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp index 7417f6dc79f..4a0ce096edd 100644 --- a/lib/Target/Mips/MipsSEISelLowering.cpp +++ b/lib/Target/Mips/MipsSEISelLowering.cpp @@ -1167,15 +1167,14 @@ MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, } } -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 diff --git a/lib/Target/Mips/MipsSEISelLowering.h b/lib/Target/Mips/MipsSEISelLowering.h index 4ca94addf2c..d44f8d82ec3 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 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,