diff options
author | Akira Hatanaka <ahatanaka@mips.com> | 2013-03-05 22:54:59 +0000 |
---|---|---|
committer | Akira Hatanaka <ahatanaka@mips.com> | 2013-03-05 22:54:59 +0000 |
commit | 1e3e869899468de2210f9777905340d907c814c6 (patch) | |
tree | 52bfb15637677eceec872a9ed96ab166dedf7939 /lib/Target/Mips/MipsISelLowering.cpp | |
parent | 7433b2e1142a46c1dbb491d91e0175cb9ce83167 (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.cpp | 89 |
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; } |