[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
This commit is contained in:
Daniel Sanders 2014-09-26 10:06:12 +00:00
parent 26ba182fdf
commit 7ecd98679e
3 changed files with 112 additions and 50 deletions

View File

@ -20,6 +20,27 @@ class CCIfSubtarget<string F, CCAction A, string Invert = "">
// The inverse of CCIfSubtarget
class CCIfSubtargetNot<string F, CCAction A> : CCIfSubtarget<F, A, "!">;
// 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<f64>,
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<RetCC_F128SoftFloat>>>,
CCIfSubtargetNot<"abiUsesSoftFloat()",
CCIfType<[i64], CCDelegateTo<RetCC_F128HardFloat>>>
]>;
//===----------------------------------------------------------------------===//
// 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<MipsCCState *>(&State)->WasOriginalArgF128(ValNo)",
CCDelegateTo<RetCC_F128>>>,
// 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<f64>,
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<RetCC_F128SoftFloat>>>,
CCIfSubtargetNot<"abiUsesSoftFloat()",
CCIfType<[i64], CCDelegateTo<RetCC_F128HardFloat>>>
]>;
//===----------------------------------------------------------------------===//
// Mips EABI Calling Convention
//===----------------------------------------------------------------------===//

View File

@ -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<ISD::InputArg> &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<ISD::OutputArg> &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<bool, 4> OriginalArgWasF128;
public:
MipsCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF,
SmallVectorImpl<CCValAssign> &locs, LLVMContext &C)
: CCState(CC, isVarArg, MF, locs, C) {}
void AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins,
CCAssignFn Fn,
const TargetLowering::CallLoweringInfo &CLI) {
PreAnalyzeCallResultForF128(Ins, CLI);
CCState::AnalyzeCallResult(Ins, Fn);
OriginalArgWasF128.clear();
}
void AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
CCAssignFn Fn) {
PreAnalyzeReturnForF128(Outs);
CCState::AnalyzeReturn(Outs, Fn);
OriginalArgWasF128.clear();
}
bool CheckReturn(const SmallVectorImpl<ISD::OutputArg> &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<ISD::InputArg> &Ins,
SDLoc DL, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals,
const SDNode *CallNode,
const Type *RetTy) const {
SDValue MipsTargetLowering::LowerCallResult(
SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool IsVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc DL, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals,
TargetLowering::CallLoweringInfo &CLI) const {
// Assign locations to each value returned by this call.
SmallVector<CCValAssign, 16> 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<ISD::OutputArg> &Outs,
LLVMContext &Context) const {
SmallVector<CCValAssign, 16> 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<SDValue, 4> RetOps(1, Chain);

View File

@ -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<ISD::InputArg> &Ins,
SDLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals,
const SDNode *CallNode, const Type *RetTy) const;
const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc dl,
SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
TargetLowering::CallLoweringInfo &CLI) const;
// Lower Operand specifics
SDValue lowerBR_JT(SDValue Op, SelectionDAG &DAG) const;