aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/Mips/MipsISelLowering.cpp
diff options
context:
space:
mode:
authorAkira Hatanaka <ahatanaka@mips.com>2013-03-05 22:54:59 +0000
committerAkira Hatanaka <ahatanaka@mips.com>2013-03-05 22:54:59 +0000
commit1e3e869899468de2210f9777905340d907c814c6 (patch)
tree52bfb15637677eceec872a9ed96ab166dedf7939 /lib/Target/Mips/MipsISelLowering.cpp
parent7433b2e1142a46c1dbb491d91e0175cb9ce83167 (diff)
[mips] Fix MipsCC::analyzeReturn so that, in soft-float mode, fp128 gets
returned in registers $2 and $4. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@176527 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/Mips/MipsISelLowering.cpp')
-rw-r--r--lib/Target/Mips/MipsISelLowering.cpp89
1 files changed, 49 insertions, 40 deletions
diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp
index 4cdca16e9e..dd569f65a3 100644
--- a/lib/Target/Mips/MipsISelLowering.cpp
+++ b/lib/Target/Mips/MipsISelLowering.cpp
@@ -4152,6 +4152,46 @@ unsigned MipsTargetLowering::getJumpTableEncoding() const {
return TargetLowering::getJumpTableEncoding();
}
+/// This function returns true if CallSym is a long double emulation routine.
+static bool isF128SoftLibCall(const char *CallSym) {
+ const char *const LibCalls[] =
+ {"__addtf3", "__divtf3", "__eqtf2", "__extenddftf2", "__extendsftf2",
+ "__fixtfdi", "__fixtfsi", "__fixtfti", "__fixunstfdi", "__fixunstfsi",
+ "__fixunstfti", "__floatditf", "__floatsitf", "__floattitf",
+ "__floatunditf", "__floatunsitf", "__floatuntitf", "__getf2", "__gttf2",
+ "__letf2", "__lttf2", "__multf3", "__netf2", "__powitf2", "__subtf3",
+ "__trunctfdf2", "__trunctfsf2", "__unordtf2",
+ "ceill", "copysignl", "cosl", "exp2l", "expl", "floorl", "fmal", "fmodl",
+ "log10l", "log2l", "logl", "nearbyintl", "powl", "rintl", "sinl", "sqrtl",
+ "truncl"};
+
+ const char * const *End = LibCalls + array_lengthof(LibCalls);
+
+ // Check that LibCalls is sorted alphabetically.
+#ifndef NDEBUG
+ ltstr Comp;
+
+ for (const char * const *I = LibCalls; I < End - 1; ++I)
+ assert(Comp(*I, *(I + 1)));
+#endif
+
+ return std::binary_search(LibCalls, End, CallSym, ltstr());
+}
+
+/// This function returns true if Ty is fp128 or i128 which was originally a
+/// fp128.
+static bool originalTypeIsF128(const Type *Ty, const SDNode *CallNode) {
+ if (Ty->isFP128Ty())
+ return true;
+
+ const ExternalSymbolSDNode *ES =
+ dyn_cast_or_null<const ExternalSymbolSDNode>(CallNode);
+
+ // If the Ty is i128 and the function being called is a long double emulation
+ // routine, then the original type is f128.
+ return (ES && Ty->isIntegerTy(128) && isF128SoftLibCall(ES->getSymbol()));
+}
+
MipsTargetLowering::MipsCC::MipsCC(CallingConv::ID CC, bool IsO32_,
CCState &Info)
: CCInfo(Info), CallConv(CC), IsO32(IsO32_) {
@@ -4232,13 +4272,19 @@ template<typename Ty>
void MipsTargetLowering::MipsCC::
analyzeReturn(const SmallVectorImpl<Ty> &RetVals, bool IsSoftFloat,
const SDNode *CallNode, const Type *RetTy) const {
+ CCAssignFn *Fn;
+
+ if (IsSoftFloat && originalTypeIsF128(RetTy, CallNode))
+ Fn = RetCC_F128Soft;
+ else
+ Fn = RetCC_Mips;
+
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)) {
+ if (Fn(I, VT, RegVT, CCValAssign::Full, Flags, this->CCInfo)) {
#ifndef NDEBUG
dbgs() << "Call result #" << I << " has unhandled type "
<< EVT(VT).getEVTString() << '\n';
@@ -4334,33 +4380,6 @@ void MipsTargetLowering::MipsCC::allocateRegs(ByValArgInfo &ByVal,
CCInfo.AllocateReg(IntArgRegs[I], ShadowRegs[I]);
}
-/// This function returns true if CallSym is a long double emulation routine.
-static bool isF128SoftLibCall(const char *CallSym) {
- const char *const LibCalls[] =
- {"__addtf3", "__divtf3", "__eqtf2", "__extenddftf2", "__extendsftf2",
- "__fixtfdi", "__fixtfsi", "__fixtfti", "__fixunstfdi", "__fixunstfsi",
- "__fixunstfti", "__floatditf", "__floatsitf", "__floattitf",
- "__floatunditf", "__floatunsitf", "__floatuntitf", "__getf2", "__gttf2",
- "__letf2", "__lttf2", "__multf3", "__netf2", "__powitf2", "__subtf3",
- "__trunctfdf2", "__trunctfsf2", "__unordtf2",
- "ceill", "copysignl", "cosl", "exp2l", "expl", "floorl", "fmal", "fmodl",
- "log10l", "log2l", "logl", "nearbyintl", "powl", "rintl", "sinl", "sqrtl",
- "truncl"};
-
- const char * const *End = LibCalls + array_lengthof(LibCalls);
-
- // Check that LibCalls is sorted alphabetically.
-#ifndef NDEBUG
- ltstr Comp;
-
- for (const char * const *I = LibCalls; I < End - 1; ++I)
- assert(Comp(*I, *(I + 1)));
-#endif
-
- return std::binary_search(LibCalls, End, CallSym, ltstr());
-}
-
-
MVT MipsTargetLowering::MipsCC::getRegVT(MVT VT, const Type *OrigTy,
const SDNode *CallNode,
bool IsSoftFloat) const {
@@ -4368,17 +4387,7 @@ MVT MipsTargetLowering::MipsCC::getRegVT(MVT VT, const Type *OrigTy,
return VT;
// Check if the original type was fp128.
- if (OrigTy->isFP128Ty()) {
- assert(VT == MVT::i64);
- return MVT::f64;
- }
-
- const ExternalSymbolSDNode *ES =
- dyn_cast_or_null<const ExternalSymbolSDNode>(CallNode);
-
- // If the original type was i128 and the function being called is a long
- // double emulation routine, the argument must be passed in an f64 register.
- if (ES && OrigTy->isIntegerTy(128) && isF128SoftLibCall(ES->getSymbol())) {
+ if (originalTypeIsF128(OrigTy, CallNode)) {
assert(VT == MVT::i64);
return MVT::f64;
}