mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-22 13:29:44 +00:00
[mips] Correct handling of fp128 (long double) formals and read long double
parameters from floating point registers if target is mips64 hard float. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@176520 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f84606732c
commit
5fdee6d2b5
@ -30,7 +30,6 @@
|
||||
#include "llvm/CodeGen/ValueTypes.h"
|
||||
#include "llvm/IR/CallingConv.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/GlobalVariable.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
@ -3647,13 +3646,14 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain,
|
||||
CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
|
||||
getTargetMachine(), ArgLocs, *DAG.getContext());
|
||||
MipsCC MipsCCInfo(CallConv, IsO32, CCInfo);
|
||||
Function::const_arg_iterator FuncArg =
|
||||
DAG.getMachineFunction().getFunction()->arg_begin();
|
||||
bool UseSoftFloat = getTargetMachine().Options.UseSoftFloat;
|
||||
|
||||
MipsCCInfo.analyzeFormalArguments(Ins);
|
||||
MipsCCInfo.analyzeFormalArguments(Ins, UseSoftFloat, FuncArg);
|
||||
MipsFI->setFormalArgInfo(CCInfo.getNextStackOffset(),
|
||||
MipsCCInfo.hasByValArg());
|
||||
|
||||
Function::const_arg_iterator FuncArg =
|
||||
DAG.getMachineFunction().getFunction()->arg_begin();
|
||||
unsigned CurArgIdx = 0;
|
||||
MipsCC::byval_iterator ByValArg = MipsCCInfo.byval_begin();
|
||||
|
||||
@ -3713,9 +3713,11 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain,
|
||||
ArgValue = DAG.getNode(ISD::TRUNCATE, dl, ValVT, ArgValue);
|
||||
}
|
||||
|
||||
// Handle floating point arguments passed in integer registers.
|
||||
// Handle floating point arguments passed in integer registers and
|
||||
// long double arguments passed in floating point registers.
|
||||
if ((RegVT == MVT::i32 && ValVT == MVT::f32) ||
|
||||
(RegVT == MVT::i64 && ValVT == MVT::f64))
|
||||
(RegVT == MVT::i64 && ValVT == MVT::f64) ||
|
||||
(RegVT == MVT::f64 && ValVT == MVT::i64))
|
||||
ArgValue = DAG.getNode(ISD::BITCAST, dl, ValVT, ArgValue);
|
||||
else if (IsO32 && RegVT == MVT::i32 && ValVT == MVT::f64) {
|
||||
unsigned Reg2 = AddLiveIn(DAG.getMachineFunction(),
|
||||
@ -4175,20 +4177,26 @@ analyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Args,
|
||||
}
|
||||
|
||||
void MipsTargetLowering::MipsCC::
|
||||
analyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Args) {
|
||||
analyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Args,
|
||||
bool IsSoftFloat, Function::const_arg_iterator FuncArg) {
|
||||
unsigned NumArgs = Args.size();
|
||||
llvm::CCAssignFn *FixedFn = fixedArgFn();
|
||||
unsigned CurArgIdx = 0;
|
||||
|
||||
for (unsigned I = 0; I != NumArgs; ++I) {
|
||||
MVT ArgVT = Args[I].VT;
|
||||
ISD::ArgFlagsTy ArgFlags = Args[I].Flags;
|
||||
std::advance(FuncArg, Args[I].OrigArgIndex - CurArgIdx);
|
||||
CurArgIdx = Args[I].OrigArgIndex;
|
||||
|
||||
if (ArgFlags.isByVal()) {
|
||||
handleByValArg(I, ArgVT, ArgVT, CCValAssign::Full, ArgFlags);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!FixedFn(I, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, CCInfo))
|
||||
MVT RegVT = getRegVT(ArgVT, FuncArg->getType(), 0, IsSoftFloat);
|
||||
|
||||
if (!FixedFn(I, ArgVT, RegVT, CCValAssign::Full, ArgFlags, CCInfo))
|
||||
continue;
|
||||
|
||||
#ifndef NDEBUG
|
||||
@ -4273,6 +4281,58 @@ 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 {
|
||||
if (IsSoftFloat || IsO32)
|
||||
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())) {
|
||||
assert(VT == MVT::i64);
|
||||
return MVT::f64;
|
||||
}
|
||||
|
||||
return VT;
|
||||
}
|
||||
|
||||
void MipsTargetLowering::
|
||||
copyByValRegs(SDValue Chain, DebugLoc DL, std::vector<SDValue> &OutChains,
|
||||
SelectionDAG &DAG, const ISD::ArgFlagsTy &Flags,
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "MipsSubtarget.h"
|
||||
#include "llvm/CodeGen/CallingConvLower.h"
|
||||
#include "llvm/CodeGen/SelectionDAG.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/Target/TargetLowering.h"
|
||||
#include <deque>
|
||||
#include <string>
|
||||
@ -205,7 +206,9 @@ namespace llvm {
|
||||
|
||||
void analyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs,
|
||||
bool IsVarArg);
|
||||
void analyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins);
|
||||
void analyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
|
||||
bool IsSoftFloat,
|
||||
Function::const_arg_iterator FuncArg);
|
||||
const CCState &getCCInfo() const { return CCInfo; }
|
||||
|
||||
/// hasByValArg - Returns true if function has byval arguments.
|
||||
@ -248,6 +251,13 @@ namespace llvm {
|
||||
void allocateRegs(ByValArgInfo &ByVal, unsigned ByValSize,
|
||||
unsigned Align);
|
||||
|
||||
/// Return the type of the register which is used to pass an argument or
|
||||
/// return a value. This function returns f64 if the argument is an i64
|
||||
/// value which has been generated as a result of softening an f128 value.
|
||||
/// Otherwise, it just returns VT.
|
||||
MVT getRegVT(MVT VT, const Type *OrigTy, const SDNode *CallNode,
|
||||
bool IsSoftFloat) const;
|
||||
|
||||
CCState &CCInfo;
|
||||
CallingConv::ID CallConv;
|
||||
bool IsO32;
|
||||
|
13
test/CodeGen/Mips/mips64-call.ll
Normal file
13
test/CodeGen/Mips/mips64-call.ll
Normal file
@ -0,0 +1,13 @@
|
||||
; RUN: llc -march=mips64el -mcpu=mips64r2 < %s | FileCheck %s
|
||||
|
||||
@gld0 = external global fp128
|
||||
|
||||
; CHECK: foo0
|
||||
; CHECK: sdc1 $f13, 8(${{[0-9]+}})
|
||||
; CHECK: sdc1 $f12, 0(${{[0-9]+}})
|
||||
|
||||
define void @foo0(fp128 %a0) {
|
||||
entry:
|
||||
store fp128 %a0, fp128* @gld0, align 16
|
||||
ret void
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user