mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-01 17:28:21 +00:00
[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:
parent
cb2eafdfa3
commit
7433b2e114
@ -3593,7 +3593,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
|||||||
// Handle result values, copying them out of physregs into vregs that we
|
// Handle result values, copying them out of physregs into vregs that we
|
||||||
// return.
|
// return.
|
||||||
return LowerCallResult(Chain, InFlag, CallConv, isVarArg,
|
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
|
/// 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,
|
CallingConv::ID CallConv, bool isVarArg,
|
||||||
const SmallVectorImpl<ISD::InputArg> &Ins,
|
const SmallVectorImpl<ISD::InputArg> &Ins,
|
||||||
DebugLoc dl, SelectionDAG &DAG,
|
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.
|
// Assign locations to each value returned by this call.
|
||||||
SmallVector<CCValAssign, 16> RVLocs;
|
SmallVector<CCValAssign, 16> RVLocs;
|
||||||
CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
|
CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
|
||||||
getTargetMachine(), RVLocs, *DAG.getContext());
|
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.
|
// Copy all of the result registers out of their specified physreg.
|
||||||
for (unsigned i = 0; i != RVLocs.size(); ++i) {
|
for (unsigned i = 0; i != RVLocs.size(); ++i) {
|
||||||
Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
|
SDValue Val = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
|
||||||
RVLocs[i].getValVT(), InFlag).getValue(1);
|
RVLocs[i].getLocVT(), InFlag);
|
||||||
InFlag = Chain.getValue(2);
|
Chain = Val.getValue(1);
|
||||||
InVals.push_back(Chain.getValue(0));
|
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;
|
return Chain;
|
||||||
@ -3799,27 +3808,33 @@ MipsTargetLowering::LowerReturn(SDValue Chain,
|
|||||||
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
||||||
const SmallVectorImpl<SDValue> &OutVals,
|
const SmallVectorImpl<SDValue> &OutVals,
|
||||||
DebugLoc dl, SelectionDAG &DAG) const {
|
DebugLoc dl, SelectionDAG &DAG) const {
|
||||||
|
|
||||||
// CCValAssign - represent the assignment of
|
// CCValAssign - represent the assignment of
|
||||||
// the return value to a location
|
// the return value to a location
|
||||||
SmallVector<CCValAssign, 16> RVLocs;
|
SmallVector<CCValAssign, 16> RVLocs;
|
||||||
|
MachineFunction &MF = DAG.getMachineFunction();
|
||||||
|
|
||||||
// CCState - Info about the registers and stack slot.
|
// CCState - Info about the registers and stack slot.
|
||||||
CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
|
CCState CCInfo(CallConv, isVarArg, MF, getTargetMachine(), RVLocs,
|
||||||
getTargetMachine(), RVLocs, *DAG.getContext());
|
*DAG.getContext());
|
||||||
|
MipsCC MipsCCInfo(CallConv, IsO32, CCInfo);
|
||||||
|
|
||||||
// Analize return values.
|
// Analize return values.
|
||||||
CCInfo.AnalyzeReturn(Outs, RetCC_Mips);
|
MipsCCInfo.analyzeReturn(Outs, getTargetMachine().Options.UseSoftFloat,
|
||||||
|
MF.getFunction()->getReturnType());
|
||||||
|
|
||||||
SDValue Flag;
|
SDValue Flag;
|
||||||
SmallVector<SDValue, 4> RetOps(1, Chain);
|
SmallVector<SDValue, 4> RetOps(1, Chain);
|
||||||
|
|
||||||
// Copy the result values into the output registers.
|
// Copy the result values into the output registers.
|
||||||
for (unsigned i = 0; i != RVLocs.size(); ++i) {
|
for (unsigned i = 0; i != RVLocs.size(); ++i) {
|
||||||
|
SDValue Val = OutVals[i];
|
||||||
CCValAssign &VA = RVLocs[i];
|
CCValAssign &VA = RVLocs[i];
|
||||||
assert(VA.isRegLoc() && "Can only return in registers!");
|
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.
|
// Guarantee that all emitted copies are stuck together with flags.
|
||||||
Flag = Chain.getValue(1);
|
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
|
// 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
|
// a virtual register in the entry block, so now we copy the value out
|
||||||
// and into $v0.
|
// and into $v0.
|
||||||
if (DAG.getMachineFunction().getFunction()->hasStructRetAttr()) {
|
if (MF.getFunction()->hasStructRetAttr()) {
|
||||||
MachineFunction &MF = DAG.getMachineFunction();
|
|
||||||
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
|
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
|
||||||
unsigned Reg = MipsFI->getSRetReturnReg();
|
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
|
void
|
||||||
MipsTargetLowering::MipsCC::handleByValArg(unsigned ValNo, MVT ValVT,
|
MipsTargetLowering::MipsCC::handleByValArg(unsigned ValNo, MVT ValVT,
|
||||||
MVT LocVT,
|
MVT LocVT,
|
||||||
|
@ -211,6 +211,14 @@ namespace llvm {
|
|||||||
void analyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
|
void analyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
|
||||||
bool IsSoftFloat,
|
bool IsSoftFloat,
|
||||||
Function::const_arg_iterator FuncArg);
|
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; }
|
const CCState &getCCInfo() const { return CCInfo; }
|
||||||
|
|
||||||
/// hasByValArg - Returns true if function has byval arguments.
|
/// hasByValArg - Returns true if function has byval arguments.
|
||||||
@ -260,6 +268,10 @@ namespace llvm {
|
|||||||
MVT getRegVT(MVT VT, const Type *OrigTy, const SDNode *CallNode,
|
MVT getRegVT(MVT VT, const Type *OrigTy, const SDNode *CallNode,
|
||||||
bool IsSoftFloat) const;
|
bool IsSoftFloat) const;
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
void analyzeReturn(const SmallVectorImpl<Ty> &RetVals, bool IsSoftFloat,
|
||||||
|
const SDNode *CallNode, const Type *RetTy) const;
|
||||||
|
|
||||||
CCState &CCInfo;
|
CCState &CCInfo;
|
||||||
CallingConv::ID CallConv;
|
CallingConv::ID CallConv;
|
||||||
bool IsO32;
|
bool IsO32;
|
||||||
@ -276,7 +288,8 @@ namespace llvm {
|
|||||||
CallingConv::ID CallConv, bool isVarArg,
|
CallingConv::ID CallConv, bool isVarArg,
|
||||||
const SmallVectorImpl<ISD::InputArg> &Ins,
|
const SmallVectorImpl<ISD::InputArg> &Ins,
|
||||||
DebugLoc dl, SelectionDAG &DAG,
|
DebugLoc dl, SelectionDAG &DAG,
|
||||||
SmallVectorImpl<SDValue> &InVals) const;
|
SmallVectorImpl<SDValue> &InVals,
|
||||||
|
const SDNode *CallNode, const Type *RetTy) const;
|
||||||
|
|
||||||
// Lower Operand specifics
|
// Lower Operand specifics
|
||||||
SDValue LowerBRCOND(SDValue Op, SelectionDAG &DAG) const;
|
SDValue LowerBRCOND(SDValue Op, SelectionDAG &DAG) const;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
; RUN: llc -march=mips64el -mcpu=mips64r2 < %s | FileCheck %s
|
; RUN: llc -march=mips64el -mcpu=mips64r2 < %s | FileCheck %s
|
||||||
|
|
||||||
@gld0 = external global fp128
|
@gld0 = external global fp128
|
||||||
|
@gld1 = external global fp128
|
||||||
|
|
||||||
; CHECK: foo0
|
; CHECK: foo0
|
||||||
; CHECK: sdc1 $f13, 8(${{[0-9]+}})
|
; CHECK: sdc1 $f13, 8(${{[0-9]+}})
|
||||||
@ -24,3 +25,20 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
declare void @foo2(fp128)
|
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()
|
||||||
|
Loading…
Reference in New Issue
Block a user