- 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
This commit is contained in:
Bruno Cardoso Lopes 2009-11-19 06:06:13 +00:00
parent 0046de0550
commit 2045c47aff
5 changed files with 167 additions and 4 deletions

View File

@ -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:

View File

@ -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<MemSDNode>(N)->getMemOperand();
DebugLoc dl = N.getDebugLoc();
// The second load should start after for 4 bytes.
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Offset0))
Offset1 = CurDAG->getTargetConstant(C->getSExtValue()+4, MVT::i32);
else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(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<MachineSDNode>(LD0)->setMemRefs(MemRefs0, MemRefs0 + 1);
cast<MachineSDNode>(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<MemSDNode>(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<ConstantSDNode>(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<MachineSDNode>(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<MachineSDNode>(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

View File

@ -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;

View File

@ -17,6 +17,12 @@ class MipsReg<string n> : Register<n> {
let Namespace = "Mips";
}
class MipsRegWithSubRegs<string n, list<Register> subregs>
: RegisterWithSubRegs<n, subregs> {
field bits<5> Num;
let Namespace = "Mips";
}
// Mips CPU Registers
class MipsGPRReg<bits<5> num, string n> : MipsReg<n> {
let Num = num;
@ -28,9 +34,9 @@ class FPR<bits<5> num, string n> : MipsReg<n> {
}
// Mips 64-bit (aliased) FPU Registers
class AFPR<bits<5> num, string n, list<Register> aliases> : MipsReg<n> {
class AFPR<bits<5> num, string n, list<Register> subregs>
: MipsRegWithSubRegs<n, subregs> {
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;
}];

View File

@ -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: