From: Daniel Sanders Date: Fri, 26 Sep 2014 10:06:12 +0000 (+0000) Subject: [mips] Generalize the handling of f128 return values to support f128 arguments. X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=7ecd98679e2e6e664f2d395760b570e65c20b6cf;ds=sidebyside [mips] Generalize the handling of f128 return values to support f128 arguments. Summary: This will allow us to handle f128 arguments without duplicating code from CCState::AnalyzeFormalArguments() or CCState::AnalyzeCallOperands(). No functional change. Reviewers: vmedic Reviewed By: vmedic Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D5292 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@218509 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/Mips/MipsCallingConv.td b/lib/Target/Mips/MipsCallingConv.td index 013fb0de3e3..8fda1be8469 100644 --- a/lib/Target/Mips/MipsCallingConv.td +++ b/lib/Target/Mips/MipsCallingConv.td @@ -20,6 +20,27 @@ class CCIfSubtarget // The inverse of CCIfSubtarget class CCIfSubtargetNot : CCIfSubtarget; +// For soft-float, f128 values are returned in A0_64 rather than V1_64. +def RetCC_F128SoftFloat : CallingConv<[ + CCAssignToReg<[V0_64, A0_64]> +]>; + +// For hard-float, f128 values are returned as a pair of f64's rather than a +// pair of i64's. +def RetCC_F128HardFloat : CallingConv<[ + CCBitConvertToType, + CCAssignToReg<[D0_64, D2_64]> +]>; + +// Handle F128 specially since we can't identify the original type during the +// tablegen-erated code. +def RetCC_F128 : CallingConv<[ + CCIfSubtarget<"abiUsesSoftFloat()", + CCIfType<[i64], CCDelegateTo>>, + CCIfSubtargetNot<"abiUsesSoftFloat()", + CCIfType<[i64], CCDelegateTo>> +]>; + //===----------------------------------------------------------------------===// // Mips O32 Calling Convention //===----------------------------------------------------------------------===// @@ -92,6 +113,20 @@ def CC_MipsN_VarArg : CallingConv<[ ]>; def RetCC_MipsN : CallingConv<[ + // f128 needs to be handled similarly to f32 and f64. 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, and soft-float needs to use $v0, + // and $a0 instead of the usual $v0, and $v1. We therefore resort to a + // pre-analyze (see PreAnalyzeReturnForF128()) step to pass information on + // whether the result 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], + CCIf<"static_cast(&State)->WasOriginalArgF128(ValNo)", + CCDelegateTo>>, + // Aggregate returns are positioned at the lowest address in the slot for // both little and big-endian targets. When passing in registers, this // requires that big-endian targets shift the value into the upper bits. @@ -113,27 +148,6 @@ def RetCC_MipsN : CallingConv<[ CCIfType<[f64], CCAssignToReg<[D0_64, D2_64]>> ]>; -// For soft-float, f128 values are returned in A0_64 rather than V1_64. -def RetCC_F128SoftFloat : CallingConv<[ - CCAssignToReg<[V0_64, A0_64]> -]>; - -// For hard-float, f128 values are returned as a pair of f64's rather than a -// pair of i64's. -def RetCC_F128HardFloat : CallingConv<[ - CCBitConvertToType, - CCAssignToReg<[D0_64, D2_64]> -]>; - -// Handle F128 specially since we can't identify the original type during the -// tablegen-erated code. -def RetCC_F128 : CallingConv<[ - CCIfSubtarget<"abiUsesSoftFloat()", - CCIfType<[i64], CCDelegateTo>>, - CCIfSubtargetNot<"abiUsesSoftFloat()", - CCIfType<[i64], CCDelegateTo>> -]>; - //===----------------------------------------------------------------------===// // Mips EABI Calling Convention //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index df73b6d3fb7..9b55c7e8ccd 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -71,6 +71,66 @@ static const MCPhysReg Mips64DPRegs[8] = { Mips::D16_64, Mips::D17_64, Mips::D18_64, Mips::D19_64 }; +static bool originalTypeIsF128(const Type *Ty, const SDNode *CallNode); + +namespace { +class MipsCCState : public CCState { +private: + /// Identify lowered values that originated from f128 arguments and record + /// this for use by RetCC_MipsN. + void + PreAnalyzeCallResultForF128(const SmallVectorImpl &Ins, + const TargetLowering::CallLoweringInfo &CLI) { + const MachineFunction &MF = getMachineFunction(); + for (unsigned i = 0; i < Ins.size(); ++i) + OriginalArgWasF128.push_back( + originalTypeIsF128(CLI.RetTy, CLI.Callee.getNode())); + } + + /// Identify lowered values that originated from f128 arguments and record + /// this for use by RetCC_MipsN. + void PreAnalyzeReturnForF128(const SmallVectorImpl &Outs) { + const MachineFunction &MF = getMachineFunction(); + for (unsigned i = 0; i < Outs.size(); ++i) + OriginalArgWasF128.push_back( + originalTypeIsF128(MF.getFunction()->getReturnType(), nullptr)); + } + + /// Records whether the value has been lowered from an f128. + SmallVector OriginalArgWasF128; + +public: + MipsCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, + SmallVectorImpl &locs, LLVMContext &C) + : CCState(CC, isVarArg, MF, locs, C) {} + + void AnalyzeCallResult(const SmallVectorImpl &Ins, + CCAssignFn Fn, + const TargetLowering::CallLoweringInfo &CLI) { + PreAnalyzeCallResultForF128(Ins, CLI); + CCState::AnalyzeCallResult(Ins, Fn); + OriginalArgWasF128.clear(); + } + + void AnalyzeReturn(const SmallVectorImpl &Outs, + CCAssignFn Fn) { + PreAnalyzeReturnForF128(Outs); + CCState::AnalyzeReturn(Outs, Fn); + OriginalArgWasF128.clear(); + } + + bool CheckReturn(const SmallVectorImpl &ArgsFlags, + CCAssignFn Fn) { + PreAnalyzeReturnForF128(ArgsFlags); + bool Return = CCState::CheckReturn(ArgsFlags, Fn); + OriginalArgWasF128.clear(); + return Return; + } + + bool WasOriginalArgF128(unsigned ValNo) { return OriginalArgWasF128[ValNo]; } +}; +} + // If I is a shifted mask, set the size (Size) and the first bit of the // mask (Pos), and return true. // For example, if I is 0x003ff800, (Pos, Size) = (11, 11). @@ -2373,8 +2433,6 @@ static bool CC_MipsO32_FP64(unsigned ValNo, MVT ValVT, return CC_MipsO32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State, F64Regs); } -static bool originalTypeIsF128(const Type *Ty, const SDNode *CallNode); - #include "MipsGenCallingConv.inc" //===----------------------------------------------------------------------===// @@ -2670,29 +2728,22 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // Handle result values, copying them out of physregs into vregs that we // return. - return LowerCallResult(Chain, InFlag, CallConv, IsVarArg, - Ins, DL, DAG, InVals, CLI.Callee.getNode(), CLI.RetTy); + return LowerCallResult(Chain, InFlag, CallConv, IsVarArg, Ins, DL, DAG, + InVals, CLI); } /// LowerCallResult - Lower the result values of a call into the /// appropriate copies out of appropriate physical registers. -SDValue -MipsTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, - CallingConv::ID CallConv, bool IsVarArg, - const SmallVectorImpl &Ins, - SDLoc DL, SelectionDAG &DAG, - SmallVectorImpl &InVals, - const SDNode *CallNode, - const Type *RetTy) const { +SDValue MipsTargetLowering::LowerCallResult( + SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool IsVarArg, + const SmallVectorImpl &Ins, SDLoc DL, SelectionDAG &DAG, + SmallVectorImpl &InVals, + TargetLowering::CallLoweringInfo &CLI) const { // Assign locations to each value returned by this call. SmallVector RVLocs; - CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, - *DAG.getContext()); - - if (originalTypeIsF128(RetTy, CallNode)) - CCInfo.AnalyzeCallResult(Ins, RetCC_F128); - else - CCInfo.AnalyzeCallResult(Ins, RetCC_Mips); + MipsCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, + *DAG.getContext()); + CCInfo.AnalyzeCallResult(Ins, RetCC_Mips, CLI); // Copy all of the result registers out of their specified physreg. for (unsigned i = 0; i != RVLocs.size(); ++i) { @@ -2905,7 +2956,7 @@ MipsTargetLowering::CanLowerReturn(CallingConv::ID CallConv, const SmallVectorImpl &Outs, LLVMContext &Context) const { SmallVector RVLocs; - CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context); + MipsCCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context); return CCInfo.CheckReturn(Outs, RetCC_Mips); } @@ -2921,14 +2972,11 @@ MipsTargetLowering::LowerReturn(SDValue Chain, MachineFunction &MF = DAG.getMachineFunction(); // CCState - Info about the registers and stack slot. - CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext()); + MipsCCState CCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext()); MipsCC MipsCCInfo(CallConv, Subtarget, CCInfo); // Analyze return values. - if (originalTypeIsF128(MF.getFunction()->getReturnType(), nullptr)) - CCInfo.AnalyzeReturn(Outs, RetCC_F128); - else - CCInfo.AnalyzeReturn(Outs, RetCC_Mips); + CCInfo.AnalyzeReturn(Outs, RetCC_Mips); SDValue Flag; SmallVector RetOps(1, Chain); diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index 3d0512d05e9..24bc47f458f 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -449,13 +449,13 @@ namespace llvm { unsigned Flag) const; MipsCC::SpecialCallingConvType getSpecialCallingConv(SDValue Callee) const; + // Lower Operand helpers SDValue LowerCallResult(SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool isVarArg, - const SmallVectorImpl &Ins, - SDLoc dl, SelectionDAG &DAG, - SmallVectorImpl &InVals, - const SDNode *CallNode, const Type *RetTy) const; + const SmallVectorImpl &Ins, SDLoc dl, + SelectionDAG &DAG, SmallVectorImpl &InVals, + TargetLowering::CallLoweringInfo &CLI) const; // Lower Operand specifics SDValue lowerBR_JT(SDValue Op, SelectionDAG &DAG) const;