From 2045c47affc0d1462a815175e420f9d6bd3f35c6 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Thu, 19 Nov 2009 06:06:13 +0000 Subject: [PATCH] - Add sugregister logic to handle f64=(f32,f32). - Support mips1 like load/store of doubles: Instead of: sdc $f0, X($3) Generate: swc $f0, X($3) swc $f1, X+4($3) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@89322 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp | 2 + lib/Target/Mips/MipsISelDAGToDAG.cpp | 129 ++++++++++++++++++ lib/Target/Mips/MipsRegisterInfo.h | 9 ++ lib/Target/Mips/MipsRegisterInfo.td | 28 +++- test/CodeGen/Mips/2008-08-03-ReturnDouble.ll | 3 +- 5 files changed, 167 insertions(+), 4 deletions(-) diff --git a/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp b/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp index 4898faee20e..efd3fb76062 100644 --- a/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp @@ -365,6 +365,8 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { case MachineOperand::MO_ConstantPoolIndex: O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" << MO.getIndex(); + if (MO.getOffset()) + O << "+" << MO.getOffset(); break; default: diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index cbcedb8ee71..2990ba90647 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -90,6 +90,8 @@ private: bool SelectAddr(SDValue Op, SDValue N, SDValue &Base, SDValue &Offset); + SDNode *SelectLoadFp64(SDValue N); + SDNode *SelectStoreFp64(SDValue N); // getI32Imm - Return a target constant with the specified // value, of type i32. @@ -198,6 +200,121 @@ SelectAddr(SDValue Op, SDValue Addr, SDValue &Offset, SDValue &Base) return true; } +SDNode *MipsDAGToDAGISel::SelectLoadFp64(SDValue N) { + MVT::SimpleValueType NVT = + N.getNode()->getValueType(0).getSimpleVT().SimpleTy; + + if (!Subtarget.isMips1() || NVT != MVT::f64) + return NULL; + + if (!Predicate_unindexedload(N.getNode()) || + !Predicate_load(N.getNode())) + return NULL; + + SDValue Chain = N.getOperand(0); + SDValue N1 = N.getOperand(1); + SDValue Offset0, Offset1, Base; + + if (!SelectAddr(N, N1, Offset0, Base) || + N1.getValueType() != MVT::i32) + return NULL; + + MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1); + MemRefs0[0] = cast(N)->getMemOperand(); + DebugLoc dl = N.getDebugLoc(); + + // The second load should start after for 4 bytes. + if (ConstantSDNode *C = dyn_cast(Offset0)) + Offset1 = CurDAG->getTargetConstant(C->getSExtValue()+4, MVT::i32); + else if (ConstantPoolSDNode *CP = dyn_cast(Offset0)) + Offset1 = CurDAG->getTargetConstantPool(CP->getConstVal(), + MVT::i32, + CP->getAlignment(), + CP->getOffset()+4, + CP->getTargetFlags()); + else + return NULL; + + // Instead of: + // ldc $f0, X($3) + // Generate: + // lwc $f0, X($3) + // lwc $f1, X+4($3) + SDNode *LD0 = CurDAG->getMachineNode(Mips::LWC1, dl, MVT::f32, + MVT::Other, Offset0, Base, Chain); + SDValue Undef = SDValue(CurDAG->getMachineNode(TargetInstrInfo::IMPLICIT_DEF, + dl, NVT), 0); + SDValue I0 = CurDAG->getTargetInsertSubreg(Mips::SUBREG_FPEVEN, dl, + MVT::f64, Undef, SDValue(LD0, 0)); + + SDNode *LD1 = CurDAG->getMachineNode(Mips::LWC1, dl, MVT::f32, + MVT::Other, Offset1, Base, SDValue(LD0, 1)); + SDValue I1 = CurDAG->getTargetInsertSubreg(Mips::SUBREG_FPODD, dl, + MVT::f64, I0, SDValue(LD1, 0)); + + ReplaceUses(N, I1); + ReplaceUses(N.getValue(1), Chain); + cast(LD0)->setMemRefs(MemRefs0, MemRefs0 + 1); + cast(LD1)->setMemRefs(MemRefs0, MemRefs0 + 1); + return I1.getNode(); +} + +SDNode *MipsDAGToDAGISel::SelectStoreFp64(SDValue N) { + + if (!Subtarget.isMips1() || + N.getOperand(1).getValueType() != MVT::f64) + return NULL; + + SDValue Chain = N.getOperand(0); + + if (!Predicate_unindexedstore(N.getNode()) || + !Predicate_store(N.getNode())) + return NULL; + + SDValue N1 = N.getOperand(1); + SDValue N2 = N.getOperand(2); + SDValue Offset0, Offset1, Base; + + if (!SelectAddr(N, N2, Offset0, Base) || + N1.getValueType() != MVT::f64 || + N2.getValueType() != MVT::i32) + return NULL; + + MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1); + MemRefs0[0] = cast(N)->getMemOperand(); + DebugLoc dl = N.getDebugLoc(); + + // Get the even and odd part from the f64 register + SDValue FPOdd = CurDAG->getTargetExtractSubreg(Mips::SUBREG_FPODD, + dl, MVT::f32, N1); + SDValue FPEven = CurDAG->getTargetExtractSubreg(Mips::SUBREG_FPEVEN, + dl, MVT::f32, N1); + + // The second store should start after for 4 bytes. + if (ConstantSDNode *C = dyn_cast(Offset0)) + Offset1 = CurDAG->getTargetConstant(C->getSExtValue()+4, MVT::i32); + else + return NULL; + + // Instead of: + // sdc $f0, X($3) + // Generate: + // swc $f0, X($3) + // swc $f1, X+4($3) + SDValue Ops0[] = { FPEven, Offset0, Base, Chain }; + Chain = SDValue(CurDAG->getMachineNode(Mips::SWC1, dl, + MVT::Other, Ops0, 4), 0); + cast(Chain.getNode())->setMemRefs(MemRefs0, MemRefs0 + 1); + + SDValue Ops1[] = { FPOdd, Offset1, Base, Chain }; + Chain = SDValue(CurDAG->getMachineNode(Mips::SWC1, dl, + MVT::Other, Ops1, 4), 0); + cast(Chain.getNode())->setMemRefs(MemRefs0, MemRefs0 + 1); + + ReplaceUses(N.getValue(0), Chain); + return Chain.getNode(); +} + /// Select instructions not customized! Used for /// expanded, promoted and normal instructions SDNode* MipsDAGToDAGISel::Select(SDValue N) { @@ -345,6 +462,18 @@ SDNode* MipsDAGToDAGISel::Select(SDValue N) { break; } + case ISD::LOAD: + if (SDNode *ResNode = SelectLoadFp64(N)) + return ResNode; + // Other cases are autogenerated. + break; + + case ISD::STORE: + if (SDNode *ResNode = SelectStoreFp64(N)) + return ResNode; + // Other cases are autogenerated. + break; + /// Handle direct and indirect calls when using PIC. On PIC, when /// GOT is smaller than about 64k (small code) the GA target is /// loaded with only one instruction. Otherwise GA's target must diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h index 5b4592193fe..6a3ec00a4ec 100644 --- a/lib/Target/Mips/MipsRegisterInfo.h +++ b/lib/Target/Mips/MipsRegisterInfo.h @@ -23,6 +23,15 @@ class MipsSubtarget; class TargetInstrInfo; class Type; +namespace Mips { + /// SubregIndex - The index of various sized subregister classes. Note that + /// these indices must be kept in sync with the class indices in the + /// MipsRegisterInfo.td file. + enum SubregIndex { + SUBREG_FPEVEN = 1, SUBREG_FPODD = 2 + }; +} + struct MipsRegisterInfo : public MipsGenRegisterInfo { const MipsSubtarget &Subtarget; const TargetInstrInfo &TII; diff --git a/lib/Target/Mips/MipsRegisterInfo.td b/lib/Target/Mips/MipsRegisterInfo.td index bbb275c6624..00e7723312f 100644 --- a/lib/Target/Mips/MipsRegisterInfo.td +++ b/lib/Target/Mips/MipsRegisterInfo.td @@ -17,6 +17,12 @@ class MipsReg : Register { let Namespace = "Mips"; } +class MipsRegWithSubRegs subregs> + : RegisterWithSubRegs { + field bits<5> Num; + let Namespace = "Mips"; +} + // Mips CPU Registers class MipsGPRReg num, string n> : MipsReg { let Num = num; @@ -28,9 +34,9 @@ class FPR num, string n> : MipsReg { } // Mips 64-bit (aliased) FPU Registers -class AFPR num, string n, list aliases> : MipsReg { +class AFPR num, string n, list subregs> + : MipsRegWithSubRegs { let Num = num; - let Aliases = aliases; } //===----------------------------------------------------------------------===// @@ -134,6 +140,23 @@ let Namespace = "Mips" in { def FCR31 : Register<"31">; } +//===----------------------------------------------------------------------===// +// Subregister Set Definitions +//===----------------------------------------------------------------------===// + +def mips_subreg_fpeven : PatLeaf<(i32 1)>; +def mips_subreg_fpodd : PatLeaf<(i32 2)>; + +def : SubRegSet<1, [D0, D1, D2, D3, D4, D5, D6, D7, + D8, D9, D10, D11, D12, D13, D14, D15], + [F0, F2, F4, F6, F8, F10, F12, F14, + F16, F18, F20, F22, F24, F26, F28, F30]>; + +def : SubRegSet<2, [D0, D1, D2, D3, D4, D5, D6, D7, + D8, D9, D10, D11, D12, D13, D14, D15], + [F1, F3, F5, F7, F9, F11, F13, F15, + F17, F19, F21, F23, F25, F27, F29, F31]>; + //===----------------------------------------------------------------------===// // Register Classes //===----------------------------------------------------------------------===// @@ -232,6 +255,7 @@ def AFGR64 : RegisterClass<"Mips", [f64], 64, // Reserved D15]> { + let SubRegClassList = [FGR32, FGR32]; let MethodProtos = [{ iterator allocation_order_end(const MachineFunction &MF) const; }]; diff --git a/test/CodeGen/Mips/2008-08-03-ReturnDouble.ll b/test/CodeGen/Mips/2008-08-03-ReturnDouble.ll index 1244a3ed605..04fdd4e5da4 100644 --- a/test/CodeGen/Mips/2008-08-03-ReturnDouble.ll +++ b/test/CodeGen/Mips/2008-08-03-ReturnDouble.ll @@ -1,7 +1,6 @@ ; Double return in abicall (default) -; RUN: llc < %s -march=mips +; RUN: llc < %s -march=mips | FileCheck %s ; PR2615 -; XFAIL: * define double @main(...) { entry: -- 2.34.1