[mips] Fix MipsTargetLowering::LowerCallResult and LowerReturn to correctly

handle fp128 returns.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@176523 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Akira Hatanaka 2013-03-05 22:41:55 +00:00
parent cb2eafdfa3
commit 7433b2e114
3 changed files with 92 additions and 15 deletions

View File

@ -3593,7 +3593,7 @@ 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);
Ins, dl, DAG, InVals, CLI.Callee.getNode(), CLI.RetTy);
}
/// LowerCallResult - Lower the result values of a call into the
@ -3603,20 +3603,29 @@ MipsTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
CallingConv::ID CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) const {
SmallVectorImpl<SDValue> &InVals,
const SDNode *CallNode,
const Type *RetTy) const {
// Assign locations to each value returned by this call.
SmallVector<CCValAssign, 16> RVLocs;
CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
getTargetMachine(), RVLocs, *DAG.getContext());
MipsCC MipsCCInfo(CallConv, IsO32, CCInfo);
CCInfo.AnalyzeCallResult(Ins, RetCC_Mips);
MipsCCInfo.analyzeCallResult(Ins, getTargetMachine().Options.UseSoftFloat,
CallNode, RetTy);
// Copy all of the result registers out of their specified physreg.
for (unsigned i = 0; i != RVLocs.size(); ++i) {
Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
RVLocs[i].getValVT(), InFlag).getValue(1);
InFlag = Chain.getValue(2);
InVals.push_back(Chain.getValue(0));
SDValue Val = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
RVLocs[i].getLocVT(), InFlag);
Chain = Val.getValue(1);
InFlag = Val.getValue(2);
if (RVLocs[i].getValVT() != RVLocs[i].getLocVT())
Val = DAG.getNode(ISD::BITCAST, dl, RVLocs[i].getValVT(), Val);
InVals.push_back(Val);
}
return Chain;
@ -3799,27 +3808,33 @@ MipsTargetLowering::LowerReturn(SDValue Chain,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<SDValue> &OutVals,
DebugLoc dl, SelectionDAG &DAG) const {
// CCValAssign - represent the assignment of
// the return value to a location
SmallVector<CCValAssign, 16> RVLocs;
MachineFunction &MF = DAG.getMachineFunction();
// CCState - Info about the registers and stack slot.
CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
getTargetMachine(), RVLocs, *DAG.getContext());
CCState CCInfo(CallConv, isVarArg, MF, getTargetMachine(), RVLocs,
*DAG.getContext());
MipsCC MipsCCInfo(CallConv, IsO32, CCInfo);
// Analize return values.
CCInfo.AnalyzeReturn(Outs, RetCC_Mips);
MipsCCInfo.analyzeReturn(Outs, getTargetMachine().Options.UseSoftFloat,
MF.getFunction()->getReturnType());
SDValue Flag;
SmallVector<SDValue, 4> RetOps(1, Chain);
// Copy the result values into the output registers.
for (unsigned i = 0; i != RVLocs.size(); ++i) {
SDValue Val = OutVals[i];
CCValAssign &VA = RVLocs[i];
assert(VA.isRegLoc() && "Can only return in registers!");
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag);
if (RVLocs[i].getValVT() != RVLocs[i].getLocVT())
Val = DAG.getNode(ISD::BITCAST, dl, RVLocs[i].getLocVT(), Val);
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), Val, Flag);
// Guarantee that all emitted copies are stuck together with flags.
Flag = Chain.getValue(1);
@ -3830,8 +3845,7 @@ MipsTargetLowering::LowerReturn(SDValue Chain,
// the sret argument into $v0 for the return. We saved the argument into
// a virtual register in the entry block, so now we copy the value out
// and into $v0.
if (DAG.getMachineFunction().getFunction()->hasStructRetAttr()) {
MachineFunction &MF = DAG.getMachineFunction();
if (MF.getFunction()->hasStructRetAttr()) {
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
unsigned Reg = MipsFI->getSRetReturnReg();
@ -4214,6 +4228,38 @@ analyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Args,
}
}
template<typename Ty>
void MipsTargetLowering::MipsCC::
analyzeReturn(const SmallVectorImpl<Ty> &RetVals, bool IsSoftFloat,
const SDNode *CallNode, const Type *RetTy) const {
for (unsigned I = 0, E = RetVals.size(); I < E; ++I) {
MVT VT = RetVals[I].VT;
ISD::ArgFlagsTy Flags = RetVals[I].Flags;
MVT RegVT = this->getRegVT(VT, RetTy, CallNode, IsSoftFloat);
if (RetCC_Mips(I, VT, RegVT, CCValAssign::Full, Flags,
this->CCInfo)) {
#ifndef NDEBUG
dbgs() << "Call result #" << I << " has unhandled type "
<< EVT(VT).getEVTString() << '\n';
#endif
llvm_unreachable(0);
}
}
}
void MipsTargetLowering::MipsCC::
analyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins, bool IsSoftFloat,
const SDNode *CallNode, const Type *RetTy) const {
analyzeReturn(Ins, IsSoftFloat, CallNode, RetTy);
}
void MipsTargetLowering::MipsCC::
analyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs, bool IsSoftFloat,
const Type *RetTy) const {
analyzeReturn(Outs, IsSoftFloat, 0, RetTy);
}
void
MipsTargetLowering::MipsCC::handleByValArg(unsigned ValNo, MVT ValVT,
MVT LocVT,

View File

@ -211,6 +211,14 @@ namespace llvm {
void analyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
bool IsSoftFloat,
Function::const_arg_iterator FuncArg);
void analyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins,
bool IsSoftFloat, const SDNode *CallNode,
const Type *RetTy) const;
void analyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
bool IsSoftFloat, const Type *RetTy) const;
const CCState &getCCInfo() const { return CCInfo; }
/// hasByValArg - Returns true if function has byval arguments.
@ -260,6 +268,10 @@ namespace llvm {
MVT getRegVT(MVT VT, const Type *OrigTy, const SDNode *CallNode,
bool IsSoftFloat) const;
template<typename Ty>
void analyzeReturn(const SmallVectorImpl<Ty> &RetVals, bool IsSoftFloat,
const SDNode *CallNode, const Type *RetTy) const;
CCState &CCInfo;
CallingConv::ID CallConv;
bool IsO32;
@ -276,7 +288,8 @@ namespace llvm {
CallingConv::ID CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
DebugLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) const;
SmallVectorImpl<SDValue> &InVals,
const SDNode *CallNode, const Type *RetTy) const;
// Lower Operand specifics
SDValue LowerBRCOND(SDValue Op, SelectionDAG &DAG) const;

View File

@ -1,6 +1,7 @@
; RUN: llc -march=mips64el -mcpu=mips64r2 < %s | FileCheck %s
@gld0 = external global fp128
@gld1 = external global fp128
; CHECK: foo0
; CHECK: sdc1 $f13, 8(${{[0-9]+}})
@ -24,3 +25,20 @@ entry:
}
declare void @foo2(fp128)
; CHECK: ld $[[R0:[0-9]+]], %got_disp(gld0)
; CHECK: sdc1 $f2, 8($[[R0]])
; CHECK: sdc1 $f0, 0($[[R0]])
; CHECK: ld $[[R1:[0-9]+]], %got_disp(gld1)
; CHECK: ldc1 $f0, 0($[[R1]])
; CHECK: ldc1 $f2, 8($[[R1]])
define fp128 @foo3() {
entry:
%call = tail call fp128 @foo4()
store fp128 %call, fp128* @gld0, align 16
%0 = load fp128* @gld1, align 16
ret fp128 %0
}
declare fp128 @foo4()