aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/Mips/MipsAsmPrinter.cpp21
-rw-r--r--lib/Target/Mips/MipsISelDAGToDAG.cpp139
-rw-r--r--lib/Target/Mips/MipsInstrFPU.td2
-rw-r--r--lib/Target/Mips/MipsInstrInfo.cpp30
-rw-r--r--lib/Target/Mips/MipsMCInstLower.cpp44
-rw-r--r--lib/Target/Mips/MipsMCInstLower.h4
-rw-r--r--test/CodeGen/Mips/select.ll2
7 files changed, 74 insertions, 168 deletions
diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp
index 4013d6c110..28358abc00 100644
--- a/lib/Target/Mips/MipsAsmPrinter.cpp
+++ b/lib/Target/Mips/MipsAsmPrinter.cpp
@@ -18,6 +18,7 @@
#include "MipsInstrInfo.h"
#include "MipsMachineFunction.h"
#include "MipsMCInstLower.h"
+#include "MipsMCSymbolRefExpr.h"
#include "InstPrinter/MipsInstPrinter.h"
#include "llvm/BasicBlock.h"
#include "llvm/Instructions.h"
@@ -36,6 +37,7 @@
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/raw_ostream.h"
@@ -53,9 +55,26 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
}
MipsMCInstLower MCInstLowering(Mang, *MF, *this);
+ unsigned Opc = MI->getOpcode();
+
+ // If target is Mips1, expand double precision load/store to two single
+ // precision loads/stores (and delay slot if MI is a load).
+ if (Subtarget->isMips1() && (Opc == Mips::LDC1 || Opc == Mips::SDC1)) {
+ SmallVector<MCInst, 4> MCInsts;
+ const unsigned* SubReg =
+ TM.getRegisterInfo()->getSubRegisters(MI->getOperand(0).getReg());
+ MCInstLowering.LowerMips1F64LoadStore(MI, Opc, MCInsts,
+ Subtarget->isLittle(), SubReg);
+
+ for (SmallVector<MCInst, 4>::iterator I = MCInsts.begin();
+ I != MCInsts.end(); ++I)
+ OutStreamer.EmitInstruction(*I);
+
+ return;
+ }
+
MCInst TmpInst0;
MCInstLowering.Lower(MI, TmpInst0);
- unsigned Opc = MI->getOpcode();
// Convert aligned loads/stores to their unaligned counterparts.
// FIXME: expand other unaligned memory accesses too.
diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp
index 47015056e1..63463bb504 100644
--- a/lib/Target/Mips/MipsISelDAGToDAG.cpp
+++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp
@@ -86,9 +86,6 @@ private:
// Complex Pattern.
bool SelectAddr(SDValue N, SDValue &Base, SDValue &Offset);
- SDNode *SelectLoadFp64(SDNode *N);
- SDNode *SelectStoreFp64(SDNode *N);
-
// getI32Imm - Return a target constant with the specified
// value, of type i32.
inline SDValue getI32Imm(unsigned Imm) {
@@ -184,130 +181,6 @@ SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
return true;
}
-SDNode *MipsDAGToDAGISel::SelectLoadFp64(SDNode *N) {
- MVT::SimpleValueType NVT =
- N->getValueType(0).getSimpleVT().SimpleTy;
-
- if (!Subtarget.isMips1() || NVT != MVT::f64)
- return NULL;
-
- LoadSDNode *LN = cast<LoadSDNode>(N);
- if (LN->getExtensionType() != ISD::NON_EXTLOAD ||
- LN->getAddressingMode() != ISD::UNINDEXED)
- return NULL;
-
- SDValue Chain = N->getOperand(0);
- SDValue N1 = N->getOperand(1);
- SDValue Offset0, Offset1, Base;
-
- if (!SelectAddr(N1, Base, Offset0) ||
- 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;
-
- // Choose the offsets depending on the endianess
- if (TM.getTargetData()->isBigEndian())
- std::swap(Offset0, Offset1);
-
- // 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, Base, Offset0, Chain);
- SDValue Undef = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
- dl, NVT), 0);
- SDValue I0 = CurDAG->getTargetInsertSubreg(Mips::sub_fpeven, dl,
- MVT::f64, Undef, SDValue(LD0, 0));
-
- SDNode *LD1 = CurDAG->getMachineNode(Mips::LWC1, dl, MVT::f32,
- MVT::Other, Base, Offset1, SDValue(LD0, 1));
- SDValue I1 = CurDAG->getTargetInsertSubreg(Mips::sub_fpodd, dl,
- MVT::f64, I0, SDValue(LD1, 0));
-
- ReplaceUses(SDValue(N, 0), I1);
- ReplaceUses(SDValue(N, 1), Chain);
- cast<MachineSDNode>(LD0)->setMemRefs(MemRefs0, MemRefs0 + 1);
- cast<MachineSDNode>(LD1)->setMemRefs(MemRefs0, MemRefs0 + 1);
- return I1.getNode();
-}
-
-SDNode *MipsDAGToDAGISel::SelectStoreFp64(SDNode *N) {
-
- if (!Subtarget.isMips1() ||
- N->getOperand(1).getValueType() != MVT::f64)
- return NULL;
-
- SDValue Chain = N->getOperand(0);
-
- StoreSDNode *SN = cast<StoreSDNode>(N);
- if (SN->isTruncatingStore() || SN->getAddressingMode() != ISD::UNINDEXED)
- return NULL;
-
- SDValue N1 = N->getOperand(1);
- SDValue N2 = N->getOperand(2);
- SDValue Offset0, Offset1, Base;
-
- if (!SelectAddr(N2, Base, Offset0) ||
- 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::sub_fpodd,
- dl, MVT::f32, N1);
- SDValue FPEven = CurDAG->getTargetExtractSubreg(Mips::sub_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;
-
- // Choose the offsets depending on the endianess
- if (TM.getTargetData()->isBigEndian())
- std::swap(Offset0, Offset1);
-
- // Instead of:
- // sdc $f0, X($3)
- // Generate:
- // swc $f0, X($3)
- // swc $f1, X+4($3)
- SDValue Ops0[] = { FPEven, Base, Offset0, Chain };
- Chain = SDValue(CurDAG->getMachineNode(Mips::SWC1, dl,
- MVT::Other, Ops0, 4), 0);
- cast<MachineSDNode>(Chain.getNode())->setMemRefs(MemRefs0, MemRefs0 + 1);
-
- SDValue Ops1[] = { FPOdd, Base, Offset1, Chain };
- Chain = SDValue(CurDAG->getMachineNode(Mips::SWC1, dl,
- MVT::Other, Ops1, 4), 0);
- cast<MachineSDNode>(Chain.getNode())->setMemRefs(MemRefs0, MemRefs0 + 1);
-
- ReplaceUses(SDValue(N, 0), Chain);
- return Chain.getNode();
-}
-
/// Select instructions not customized! Used for
/// expanded, promoted and normal instructions
SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
@@ -423,18 +296,6 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
break;
}
- case ISD::LOAD:
- if (SDNode *ResNode = SelectLoadFp64(Node))
- return ResNode;
- // Other cases are autogenerated.
- break;
-
- case ISD::STORE:
- if (SDNode *ResNode = SelectStoreFp64(Node))
- return ResNode;
- // Other cases are autogenerated.
- break;
-
case MipsISD::ThreadPointer: {
unsigned SrcReg = Mips::HWR29;
unsigned DestReg = Mips::V1;
diff --git a/lib/Target/Mips/MipsInstrFPU.td b/lib/Target/Mips/MipsInstrFPU.td
index 021c167997..24e95aec4c 100644
--- a/lib/Target/Mips/MipsInstrFPU.td
+++ b/lib/Target/Mips/MipsInstrFPU.td
@@ -190,7 +190,7 @@ def FMOV_D32 : FFR<0x11, 0b000110, 0x1, (outs AFGR64:$fd), (ins AFGR64:$fs),
"mov.d\t$fd, $fs", []>;
/// Floating Point Memory Instructions
-let Predicates = [IsNotSingleFloat, IsNotMipsI] in {
+let Predicates = [IsNotSingleFloat] in {
def LDC1 : FFI<0b110101, (outs AFGR64:$ft), (ins mem:$addr),
"ldc1\t$ft, $addr", [(set AFGR64:$ft, (load addr:$addr))]>;
diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp
index 0a7a7f2dfe..d04cc3b066 100644
--- a/lib/Target/Mips/MipsInstrInfo.cpp
+++ b/lib/Target/Mips/MipsInstrInfo.cpp
@@ -175,21 +175,9 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
BuildMI(MBB, I, DL, get(Mips::SWC1)).addReg(SrcReg, getKillRegState(isKill))
.addFrameIndex(FI).addImm(0);
else if (RC == Mips::AFGR64RegisterClass) {
- if (!TM.getSubtarget<MipsSubtarget>().isMips1()) {
- BuildMI(MBB, I, DL, get(Mips::SDC1))
- .addReg(SrcReg, getKillRegState(isKill))
- .addFrameIndex(FI).addImm(0);
- } else {
- const TargetRegisterInfo *TRI =
- MBB.getParent()->getTarget().getRegisterInfo();
- const unsigned *SubSet = TRI->getSubRegisters(SrcReg);
- BuildMI(MBB, I, DL, get(Mips::SWC1))
- .addReg(SubSet[0], getKillRegState(isKill))
- .addFrameIndex(FI).addImm(0);
- BuildMI(MBB, I, DL, get(Mips::SWC1))
- .addReg(SubSet[1], getKillRegState(isKill))
- .addFrameIndex(FI).addImm(4);
- }
+ BuildMI(MBB, I, DL, get(Mips::SDC1))
+ .addReg(SrcReg, getKillRegState(isKill))
+ .addFrameIndex(FI).addImm(0);
} else
llvm_unreachable("Register class not handled!");
}
@@ -208,17 +196,7 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
else if (RC == Mips::FGR32RegisterClass)
BuildMI(MBB, I, DL, get(Mips::LWC1), DestReg).addFrameIndex(FI).addImm(0);
else if (RC == Mips::AFGR64RegisterClass) {
- if (!TM.getSubtarget<MipsSubtarget>().isMips1()) {
- BuildMI(MBB, I, DL, get(Mips::LDC1), DestReg).addFrameIndex(FI).addImm(0);
- } else {
- const TargetRegisterInfo *TRI =
- MBB.getParent()->getTarget().getRegisterInfo();
- const unsigned *SubSet = TRI->getSubRegisters(DestReg);
- BuildMI(MBB, I, DL, get(Mips::LWC1), SubSet[0])
- .addFrameIndex(FI).addImm(0);
- BuildMI(MBB, I, DL, get(Mips::LWC1), SubSet[1])
- .addFrameIndex(FI).addImm(4);
- }
+ BuildMI(MBB, I, DL, get(Mips::LDC1), DestReg).addFrameIndex(FI).addImm(0);
} else
llvm_unreachable("Register class not handled!");
}
diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp
index 16ec41ef51..58e1844305 100644
--- a/lib/Target/Mips/MipsMCInstLower.cpp
+++ b/lib/Target/Mips/MipsMCInstLower.cpp
@@ -83,6 +83,50 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
Ctx));
}
+// If target is Mips1, expand double precision load/store to two single
+// precision loads/stores.
+//
+// ldc1 $f0, lo($CPI0_0)($5) gets expanded to the following two instructions:
+// (little endian)
+// lwc1 $f0, lo($CPI0_0)($5) and
+// lwc1 $f1, lo($CPI0_0+4)($5)
+// (big endian)
+// lwc1 $f1, lo($CPI0_0)($5) and
+// lwc1 $f0, lo($CPI0_0+4)($5)
+void MipsMCInstLower::LowerMips1F64LoadStore(const MachineInstr *MI,
+ unsigned Opc,
+ SmallVector<MCInst, 4>& MCInsts,
+ bool isLittle,
+ const unsigned *SubReg) const {
+ MCInst InstLo, InstHi, DelaySlot;
+ unsigned SingleOpc = (Opc == Mips::LDC1 ? Mips::LWC1 : Mips::SWC1);
+ unsigned RegLo = isLittle ? *SubReg : *(SubReg + 1);
+ unsigned RegHi = isLittle ? *(SubReg + 1) : *SubReg;
+ const MachineOperand &MO1 = MI->getOperand(1);
+ const MachineOperand &MO2 = MI->getOperand(2);
+
+ InstLo.setOpcode(SingleOpc);
+ InstLo.addOperand(MCOperand::CreateReg(RegLo));
+ InstLo.addOperand(LowerOperand(MO1));
+ InstLo.addOperand(LowerOperand(MO2));
+ MCInsts.push_back(InstLo);
+
+ InstHi.setOpcode(SingleOpc);
+ InstHi.addOperand(MCOperand::CreateReg(RegHi));
+ InstHi.addOperand(LowerOperand(MO1));
+ if (MO2.isImm())// The offset of addr operand is an immediate: e.g. 0($sp)
+ InstHi.addOperand(MCOperand::CreateImm(MO2.getImm() + 4));
+ else// Otherwise, the offset must be a symbol: e.g. lo($CPI0_0)($5)
+ InstHi.addOperand(LowerSymbolOperand(MO2, MO2.getType(), 4));
+ MCInsts.push_back(InstHi);
+
+ // Need to insert a NOP in LWC1's delay slot.
+ if (SingleOpc == Mips::LWC1) {
+ DelaySlot.setOpcode(Mips::NOP);
+ MCInsts.push_back(DelaySlot);
+ }
+}
+
MCOperand MipsMCInstLower::LowerOperand(const MachineOperand& MO) const {
MachineOperandType MOTy = MO.getType();
diff --git a/lib/Target/Mips/MipsMCInstLower.h b/lib/Target/Mips/MipsMCInstLower.h
index f401536e01..d59f3f107f 100644
--- a/lib/Target/Mips/MipsMCInstLower.h
+++ b/lib/Target/Mips/MipsMCInstLower.h
@@ -9,6 +9,7 @@
#ifndef MIPSMCINSTLOWER_H
#define MIPSMCINSTLOWER_H
+#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/Support/Compiler.h"
@@ -34,6 +35,9 @@ public:
MipsMCInstLower(Mangler *mang, const MachineFunction &MF,
MipsAsmPrinter &asmprinter);
void Lower(const MachineInstr *MI, MCInst &OutMI) const;
+ void LowerMips1F64LoadStore(const MachineInstr *MI, unsigned Opc,
+ SmallVector<MCInst, 4>& MCInsts,
+ bool isLittle, const unsigned *SubReg) const;
private:
MCOperand LowerSymbolOperand(const MachineOperand &MO,
MachineOperandType MOTy, unsigned Offset) const;
diff --git a/test/CodeGen/Mips/select.ll b/test/CodeGen/Mips/select.ll
index c83fa3ece0..3ea4c4b2e3 100644
--- a/test/CodeGen/Mips/select.ll
+++ b/test/CodeGen/Mips/select.ll
@@ -25,7 +25,7 @@ entry:
define double @sel2_1(i32 %s, double %f0, double %f1) nounwind readnone {
entry:
; CHECK-MIPS32R2: movn.d
-; CHECK-MIPS1: beq
+; CHECK-MIPS1: bne
%tobool = icmp ne i32 %s, 0
%cond = select i1 %tobool, double %f0, double %f1
ret double %cond