diff options
Diffstat (limited to 'llvm/lib/Target/Mips/MipsISelLowering.cpp')
-rw-r--r-- | llvm/lib/Target/Mips/MipsISelLowering.cpp | 285 |
1 files changed, 166 insertions, 119 deletions
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index c08367912aa..ef78df55f72 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/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<ISD::OutputArg> &Outs, + std::vector<TargetLowering::ArgListEntry> &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<ISD::InputArg> &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<bool, 4> 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<ISD::OutputArg> &Outs, + std::vector<TargetLowering::ArgListEntry> &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<ISD::InputArg> &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<CCValAssign> &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<CCValAssign, 16> 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<MipsFunctionInfo>()); + IsTailCall = isEligibleForTailCallOptimization( + CCInfo, NextStackOffset, *MF.getInfo<MipsFunctionInfo>()); 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<unsigned, SDValue> > RegsToPass; SmallVector<SDValue, 8> 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<CCValAssign, 16> 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<ISD::InputArg> &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<MCPhysReg> 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<MCPhysReg> 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<SDValue> &OutChains, SelectionDAG &DAG, const ISD::ArgFlagsTy &Flags, SmallVectorImpl<SDValue> &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<std::pair<unsigned, SDValue>> &RegsToPass, SmallVectorImpl<SDValue> &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<MCPhysReg> 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<SDValue> &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<MCPhysReg> 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); +} |