Added support for fround, fextend and FP_TO_SINT

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72483 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bruno Cardoso Lopes 2009-05-27 17:23:44 +00:00
parent 0d09b83a48
commit d3bdf19ce7
9 changed files with 90 additions and 29 deletions

View File

@ -39,6 +39,8 @@ def FeatureFP64Bit : SubtargetFeature<"fp64", "IsFP64bit", "true",
"Support 64-bit FP registers.">;
def FeatureSingleFloat : SubtargetFeature<"single-float", "IsSingleFloat",
"true", "Only supports single precision float">;
def FeatureMips1 : SubtargetFeature<"mips1", "MipsArchVersion", "Mips1",
"Mips1 ISA Support">;
def FeatureMips2 : SubtargetFeature<"mips2", "MipsArchVersion", "Mips2",
"Mips2 ISA Support">;
def FeatureO32 : SubtargetFeature<"o32", "MipsABI", "O32",
@ -67,9 +69,9 @@ def FeatureBitCount : SubtargetFeature<"bitcount", "HasBitCount", "true",
class Proc<string Name, list<SubtargetFeature> Features>
: Processor<Name, MipsGenericItineraries, Features>;
def : Proc<"mips1", []>;
def : Proc<"r2000", []>;
def : Proc<"r3000", []>;
def : Proc<"mips1", [FeatureMips1]>;
def : Proc<"r2000", [FeatureMips1]>;
def : Proc<"r3000", [FeatureMips1]>;
def : Proc<"mips2", [FeatureMips2]>;
def : Proc<"r6000", [FeatureMips2]>;

View File

@ -48,6 +48,7 @@ getTargetNodeName(unsigned Opcode) const
case MipsISD::FPSelectCC : return "MipsISD::FPSelectCC";
case MipsISD::FPBrcond : return "MipsISD::FPBrcond";
case MipsISD::FPCmp : return "MipsISD::FPCmp";
case MipsISD::FPRound : return "MipsISD::FPRound";
default : return NULL;
}
}
@ -96,8 +97,10 @@ MipsTargetLowering(MipsTargetMachine &TM): TargetLowering(TM)
setOperationAction(ISD::SELECT, MVT::f32, Custom);
setOperationAction(ISD::SELECT, MVT::i32, Custom);
setOperationAction(ISD::SETCC, MVT::f32, Custom);
setOperationAction(ISD::SETCC, MVT::f64, Custom);
setOperationAction(ISD::BRCOND, MVT::Other, Custom);
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom);
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
// We custom lower AND/OR to handle the case where the DAG contain 'ands/ors'
// with operands comming from setcc fp comparions. This is necessary since
@ -166,6 +169,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG)
case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG);
case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG);
case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
case ISD::JumpTable: return LowerJumpTable(Op, DAG);
@ -358,6 +362,39 @@ MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
// Misc Lower Operation implementation
//===----------------------------------------------------------------------===//
SDValue MipsTargetLowering::
LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG)
{
if (!Subtarget->isMips1())
return Op;
MachineFunction &MF = DAG.getMachineFunction();
unsigned CCReg = AddLiveIn(MF, Mips::FCR31, Mips::CCRRegisterClass);
SDValue Chain = DAG.getEntryNode();
DebugLoc dl = Op.getDebugLoc();
SDValue Src = Op.getOperand(0);
// Set the condition register
SDValue CondReg = DAG.getCopyFromReg(Chain, dl, CCReg, MVT::i32);
CondReg = DAG.getCopyToReg(Chain, dl, Mips::AT, CondReg);
CondReg = DAG.getCopyFromReg(CondReg, dl, Mips::AT, MVT::i32);
SDValue Cst = DAG.getConstant(3, MVT::i32);
SDValue Or = DAG.getNode(ISD::OR, dl, MVT::i32, CondReg, Cst);
Cst = DAG.getConstant(2, MVT::i32);
SDValue Xor = DAG.getNode(ISD::XOR, dl, MVT::i32, Or, Cst);
SDValue InFlag(0, 0);
CondReg = DAG.getCopyToReg(Chain, dl, Mips::FCR31, Xor, InFlag);
// Emit the round instruction and bit convert to integer
SDValue Trunc = DAG.getNode(MipsISD::FPRound, dl, MVT::f32,
Src, CondReg.getValue(1));
SDValue BitCvt = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Trunc);
return BitCvt;
}
SDValue MipsTargetLowering::
LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG)
{

View File

@ -55,6 +55,9 @@ namespace llvm {
// Floating Point Compare
FPCmp,
// Floating Point Rounding
FPRound,
// Return
Ret
};
@ -98,6 +101,7 @@ namespace llvm {
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG);
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG);
SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG);
SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG);
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG);
SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG);
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG);

View File

@ -30,6 +30,8 @@ def SDT_MipsFPCmp : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisFP<0>,
SDTCisInt<2>]>;
def SDT_MipsFPSelectCC : SDTypeProfile<1, 4, [SDTCisInt<1>, SDTCisInt<4>,
SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3>]>;
def MipsFPRound : SDNode<"MipsISD::FPRound", SDTFPRoundOp, [SDNPOptInFlag]>;
def MipsFPBrcond : SDNode<"MipsISD::FPBrcond", SDT_MipsFPBrcond,
[SDNPHasChain]>;
def MipsFPCmp : SDNode<"MipsISD::FPCmp", SDT_MipsFPCmp>;
@ -66,7 +68,7 @@ multiclass FFR1_1<bits<6> funct, string asmstr>
def _S32 : FFR<0x11, funct, 0x0, (outs FGR32:$fd), (ins FGR32:$fs),
!strconcat(asmstr, ".s $fd, $fs"), []>;
def _D32 : FFR<0x11, funct, 0x1, (outs AFGR64:$fd), (ins AFGR64:$fs),
def _D32 : FFR<0x11, funct, 0x1, (outs FGR32:$fd), (ins AFGR64:$fs),
!strconcat(asmstr, ".d $fd, $fs"), []>, Requires<[In32BitMode]>;
}
@ -157,12 +159,12 @@ let ft = 0 in {
// regardless of register aliasing.
let fd = 0 in {
/// Move Control Registers From/To CPU Registers
///def CFC1 : FFR<0x11, 0x0, 0x2, (outs CPURegs:$rt), (ins FGR32:$fs),
/// "cfc1 $rt, $fs", []>;
def CFC1 : FFR<0x11, 0x0, 0x2, (outs CPURegs:$rt), (ins CCR:$fs),
"cfc1 $rt, $fs", []>;
///def CTC1 : FFR<0x11, 0x0, 0x6, (outs CPURegs:$rt), (ins FGR32:$fs),
/// "ctc1 $rt, $fs", []>;
///
def CTC1 : FFR<0x11, 0x0, 0x6, (outs CCR:$rt), (ins CPURegs:$fs),
"ctc1 $fs, $rt", []>;
def MFC1 : FFR<0x11, 0x00, 0x00, (outs CPURegs:$rt), (ins FGR32:$fs),
"mfc1 $rt, $fs", []>;
@ -272,6 +274,9 @@ def Select_FCC_S32 : PseudoFPSelCC<FGR32, "# MipsSelect_FCC_S32_f32">;
def Select_FCC_D32 : PseudoFPSelCC<AFGR64, "# MipsSelect_FCC_D32_f32">,
Requires<[In32BitMode]>;
def MOVCCRToCCR : MipsPseudo<(outs CCR:$dst), (ins CCR:$src),
"# MOVCCRToCCR", []>;
//===----------------------------------------------------------------------===//
// Floating Point Patterns
//===----------------------------------------------------------------------===//
@ -288,3 +293,12 @@ def : Pat<(i32 (fp_to_sint FGR32:$src)), (MFC1 (TRUNC_W_S32 FGR32:$src))>;
def : Pat<(i32 (bitconvert FGR32:$src)), (MFC1 FGR32:$src)>;
def : Pat<(f32 (bitconvert CPURegs:$src)), (MTC1 CPURegs:$src)>;
let Predicates = [In32BitMode] in {
def : Pat<(f32 (fround AFGR64:$src)), (CVTS_D32 AFGR64:$src)>;
def : Pat<(f64 (fextend FGR32:$src)), (CVTD_S32 FGR32:$src)>;
}
// MipsFPRound is only emitted for MipsI targets.
def : Pat<(f32 (MipsFPRound AFGR64:$src)), (CVTW_D32 AFGR64:$src)>;

View File

@ -55,7 +55,8 @@ isMoveInstr(const MachineInstr &MI, unsigned &SrcReg, unsigned &DstReg,
if (MI.getOpcode() == Mips::FMOV_S32 ||
MI.getOpcode() == Mips::FMOV_D32 ||
MI.getOpcode() == Mips::MFC1 ||
MI.getOpcode() == Mips::MTC1 ) {
MI.getOpcode() == Mips::MTC1 ||
MI.getOpcode() == Mips::MOVCCRToCCR) {
DstReg = MI.getOperand(0).getReg();
SrcReg = MI.getOperand(1).getReg();
return true;
@ -69,6 +70,7 @@ isMoveInstr(const MachineInstr &MI, unsigned &SrcReg, unsigned &DstReg,
return true;
}
}
return false;
}
@ -132,22 +134,23 @@ copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
if (I != MBB.end()) DL = I->getDebugLoc();
if (DestRC != SrcRC) {
// Moves between coprocessors and cpu
// Copy to/from FCR31 condition register
if ((DestRC == Mips::CPURegsRegisterClass) &&
(SrcRC == Mips::CCRRegisterClass))
BuildMI(MBB, I, DL, get(Mips::CFC1), DestReg).addReg(SrcReg);
else if ((DestRC == Mips::CCRRegisterClass) &&
(SrcRC == Mips::CPURegsRegisterClass))
BuildMI(MBB, I, DL, get(Mips::CTC1), DestReg).addReg(SrcReg);
// Moves between coprocessors and cpu
else if ((DestRC == Mips::CPURegsRegisterClass) &&
(SrcRC == Mips::FGR32RegisterClass))
BuildMI(MBB, I, DL, get(Mips::MFC1), DestReg).addReg(SrcReg);
else if ((DestRC == Mips::FGR32RegisterClass) &&
(SrcRC == Mips::CPURegsRegisterClass))
BuildMI(MBB, I, DL, get(Mips::MTC1), DestReg).addReg(SrcReg);
// Condition registers
else if ((SrcRC == Mips::CCRRegisterClass) &&
(SrcReg == Mips::FCR31))
return true; // This register is used implicitly, no copy needed.
else if ((DestRC == Mips::CCRRegisterClass) &&
(DestReg == Mips::FCR31))
return true; // This register is used implicitly, no copy needed.
// Move from/to Hi/Lo registers
else if ((DestRC == Mips::HILORegisterClass) &&
(SrcRC == Mips::CPURegsRegisterClass)) {
@ -172,6 +175,8 @@ copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
BuildMI(MBB, I, DL, get(Mips::FMOV_S32), DestReg).addReg(SrcReg);
else if (DestRC == Mips::AFGR64RegisterClass)
BuildMI(MBB, I, DL, get(Mips::FMOV_D32), DestReg).addReg(SrcReg);
else if (DestRC == Mips::CCRRegisterClass)
BuildMI(MBB, I, DL, get(Mips::MOVCCRToCCR), DestReg).addReg(SrcReg);
else
// Can't copy this register
return false;

View File

@ -518,10 +518,10 @@ let Uses = [LO] in
/// Sign Ext In Register Instructions.
let Predicates = [HasSEInReg] in {
let shamt = 0x10, rs = 0 in
let shamt = 0x10, rs = 0 in
def SEB : SignExtInReg<0x21, "seb", i8>;
let shamt = 0x18, rs = 0 in
let shamt = 0x18, rs = 0 in
def SEH : SignExtInReg<0x20, "seh", i16>;
}

View File

@ -131,7 +131,7 @@ let Namespace = "Mips" in {
def LO : Register<"lo">, DwarfRegNum<[65]>;
// Status flags register
def FCR31 : Register<"FCR31">;
def FCR31 : Register<"31">;
}
//===----------------------------------------------------------------------===//
@ -244,11 +244,9 @@ def AFGR64 : RegisterClass<"Mips", [f64], 64,
}];
}
def CCR : RegisterClass<"Mips", [i32], 32, [FCR31]> {
let CopyCost = -1; // Don't allow copying of status registers.
}
// Condition Register for floating point operations
def CCR : RegisterClass<"Mips", [i32], 32, [FCR31]>;
def HILO : RegisterClass<"Mips", [i32], 32, [HI, LO]> {
//let CopyCost = -1; // Don't allow copying of hi/lo registers.
}
// Hi/Lo Registers
def HILO : RegisterClass<"Mips", [i32], 32, [HI, LO]>;

View File

@ -37,6 +37,7 @@ MipsSubtarget::MipsSubtarget(const TargetMachine &TM, const Module &M,
HasMulDivAdd(false), HasMinMax(false), HasSwap(false), HasBitCount(false)
{
std::string CPU = "mips1";
MipsArchVersion = Mips1;
// Parse features string.
ParseSubtargetFeatures(FS, CPU);

View File

@ -112,7 +112,7 @@ public:
std::string ParseSubtargetFeatures(const std::string &FS,
const std::string &CPU);
bool hasMips2Ops() const { return MipsArchVersion >= Mips2; }
bool isMips1() const { return MipsArchVersion == Mips1; }
bool isLittle() const { return IsLittle; }
bool isFP64bit() const { return IsFP64bit; };