case MipsISD::Lo : return "MipsISD::Lo";
case MipsISD::GPRel : return "MipsISD::GPRel";
case MipsISD::Ret : return "MipsISD::Ret";
+ case MipsISD::CMov : return "MipsISD::CMov";
case MipsISD::SelectCC : return "MipsISD::SelectCC";
case MipsISD::FPSelectCC : return "MipsISD::FPSelectCC";
case MipsISD::FPBrcond : return "MipsISD::FPBrcond";
setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
setOperationAction(ISD::SELECT, MVT::f32, Custom);
setOperationAction(ISD::SELECT, MVT::i32, Custom);
- setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
setOperationAction(ISD::SETCC, MVT::f32, Custom);
setOperationAction(ISD::BRCOND, MVT::Other, Custom);
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom);
setOperationAction(ISD::CTPOP, MVT::i32, Expand);
setOperationAction(ISD::CTTZ, MVT::i32, Expand);
setOperationAction(ISD::ROTL, MVT::i32, Expand);
- setOperationAction(ISD::ROTR, MVT::i32, Expand);
- setOperationAction(ISD::BSWAP, MVT::i32, Expand);
setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
if (!Subtarget->hasBitCount())
setOperationAction(ISD::CTLZ, MVT::i32, Expand);
+ if (!Subtarget->hasSwap())
+ setOperationAction(ISD::BSWAP, MVT::i32, Expand);
+
setStackPointerRegisterToSaveRestore(Mips::SP);
computeRegisterProperties();
}
case ISD::OR: return LowerANDOR(Op, DAG);
case ISD::RET: return LowerRET(Op, DAG);
case ISD::SELECT: return LowerSELECT(Op, DAG);
- case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
case ISD::SETCC: return LowerSETCC(Op, DAG);
}
return SDValue();
SDValue True = Op.getOperand(1);
SDValue False = Op.getOperand(2);
- // if the incomming condition comes from fpcmp, the select
- // operation must use FPSelectCC, otherwise SelectCC.
- if (Cond.getOpcode() != MipsISD::FPCmp)
+ // if the incomming condition comes from a integer compare, the select
+ // operation must be SelectCC or a conditional move if the subtarget
+ // supports it.
+ if (Cond.getOpcode() != MipsISD::FPCmp) {
+ if (Subtarget->hasCondMov() && !True.getValueType().isFloatingPoint())
+ return Op;
return DAG.getNode(MipsISD::SelectCC, True.getValueType(),
Cond, True, False);
-
+ }
+
+ // if the incomming condition comes from fpcmp, the select
+ // operation must use FPSelectCC.
SDValue CCNode = Cond.getOperand(2);
return DAG.getNode(MipsISD::FPSelectCC, True.getValueType(),
Cond, True, False, CCNode);
}
SDValue MipsTargetLowering::
-LowerSELECT_CC(SDValue Op, SelectionDAG &DAG)
-{
- SDValue LHS = Op.getOperand(0);
- SDValue RHS = Op.getOperand(1);
- SDValue True = Op.getOperand(2);
- SDValue False = Op.getOperand(3);
- SDValue CC = Op.getOperand(4);
-
- SDValue SetCCRes = DAG.getNode(ISD::SETCC, LHS.getValueType(), LHS, RHS, CC);
- return DAG.getNode(MipsISD::SelectCC, True.getValueType(),
- SetCCRes, True, False);
-}
-
-SDValue MipsTargetLowering::
LowerGlobalAddress(SDValue Op, SelectionDAG &DAG)
{
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
def SDT_MipsJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>;
def SDT_MipsSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 2>,
SDTCisSameAs<2, 3>, SDTCisInt<1>]>;
+def SDT_MipsCMov : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>,
+ SDTCisSameAs<1, 2>, SDTCisSameAs<3, 4>,
+ SDTCisInt<4>]>;
def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>;
def SDT_MipsCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
// Select Condition Code
def MipsSelectCC : SDNode<"MipsISD::SelectCC", SDT_MipsSelectCC>;
+// Conditional Move
+def MipsCMov : SDNode<"MipsISD::CMov", SDT_MipsCMov>;
+
//===----------------------------------------------------------------------===//
// Mips Instruction Predicate Definitions.
//===----------------------------------------------------------------------===//
def HasSEInReg : Predicate<"Subtarget.hasSEInReg()">;
def HasBitCount : Predicate<"Subtarget.hasBitCount()">;
+def HasSwap : Predicate<"Subtarget.hasSwap()">;
+def HasCondMov : Predicate<"Subtarget.hasCondMov()">;
//===----------------------------------------------------------------------===//
// Mips Operand, Complex Patterns and Transformations Definitions.
// Instruction operand types
def brtarget : Operand<OtherVT>;
def calltarget : Operand<i32>;
-def uimm16 : Operand<i32>;
def simm16 : Operand<i32>;
def shamt : Operand<i32>;
+// Unsigned Operand
+def uimm16 : Operand<i32> {
+ let PrintMethod = "printUnsignedImm";
+}
+
// Address operand
def mem : Operand<i32> {
let PrintMethod = "printMemOperand";
!strconcat(instr_asm, "\t$dst, $b, $c"),
[(set CPURegs:$dst, (OpNode CPURegs:$b, imm_type:$c))], IIAlu>;
+class ArithOverflowI<bits<6> op, string instr_asm, SDNode OpNode,
+ Operand Od, PatLeaf imm_type> :
+ FI< op,
+ (outs CPURegs:$dst),
+ (ins CPURegs:$b, Od:$c),
+ !strconcat(instr_asm, "\t$dst, $b, $c"),
+ [], IIAlu>;
+
// Arithmetic Multiply ADD/SUB
let rd=0 in
class MArithR<bits<6> func, string instr_asm> :
!strconcat(instr_asm, "\t$dst, $src"),
[(set CPURegs:$dst, (sext_inreg CPURegs:$src, vt))], NoItinerary>;
+// Byte Swap
+class ByteSwap<bits<6> func, string instr_asm>:
+ FR< 0x1f, func, (outs CPURegs:$dst), (ins CPURegs:$src),
+ !strconcat(instr_asm, "\t$dst, $src"),
+ [(set CPURegs:$dst, (bswap CPURegs:$src))], NoItinerary>;
+
+// Conditional Move
+class CondMov<bits<6> func, string instr_asm, PatLeaf MovCode>:
+ FR< 0x00, func, (outs CPURegs:$dst), (ins CPURegs:$F, CPURegs:$T,
+ CPURegs:$cond), !strconcat(instr_asm, "\t$dst, $T, $cond"),
+ [(set CPURegs:$dst, (MipsCMov CPURegs:$F, CPURegs:$T,
+ CPURegs:$cond, MovCode))], NoItinerary>;
//===----------------------------------------------------------------------===//
// Pseudo instructions
//===----------------------------------------------------------------------===//
/// Arithmetic Instructions (ALU Immediate)
-def ADDiu : ArithI<0x09, "addiu", add, uimm16, immZExt16>;
-def ADDi : ArithI<0x08, "addi", add, simm16, immSExt16>;
+def ADDiu : ArithI<0x09, "addiu", add, simm16, immSExt16>;
+def ADDi : ArithOverflowI<0x08, "addi", add, simm16, immSExt16>;
def SLTi : SetCC_I<0x0a, "slti", setlt, simm16, immSExt16>;
-def SLTiu : SetCC_I<0x0b, "sltiu", setult, uimm16, immZExt16>;
+def SLTiu : SetCC_I<0x0b, "sltiu", setult, simm16, immSExt16>;
def ANDi : LogicI<0x0c, "andi", and>;
def ORi : LogicI<0x0d, "ori", or>;
def XORi : LogicI<0x0e, "xori", xor>;
/// Count Leading
let Predicates = [HasBitCount] in {
- def CLZ : CountLeading<0b010110, "clz", ctlz>;
-//def CLO : CountLeading<0b010110, "clo">;
+ let rt = 0 in
+ def CLZ : CountLeading<0b010110, "clz", ctlz>;
+}
+
+/// Byte Swap
+let Predicates = [HasSwap] in {
+ let shamt = 0x3, rs = 0 in
+ def WSBW : ByteSwap<0x20, "wsbw">;
+}
+
+/// Conditional Move
+def MIPS_CMOV_ZERO : PatLeaf<(i32 0)>;
+def MIPS_CMOV_NZERO : PatLeaf<(i32 1)>;
+
+let Predicates = [HasCondMov], isTwoAddress = 1 in {
+ def MOVN : CondMov<0x0a, "movn", MIPS_CMOV_NZERO>;
+ def MOVZ : CondMov<0x0b, "movz", MIPS_CMOV_ZERO>;
}
/// No operation
(NOR CPURegs:$in, ZERO)>;
// extended load and stores
-def : Pat<(i32 (extloadi1 addr:$src)), (LBu addr:$src)>;
-def : Pat<(i32 (extloadi8 addr:$src)), (LBu addr:$src)>;
-def : Pat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>;
+def : Pat<(extloadi1 addr:$src), (LBu addr:$src)>;
+def : Pat<(extloadi8 addr:$src), (LBu addr:$src)>;
+def : Pat<(extloadi16 addr:$src), (LHu addr:$src)>;
// peepholes
def : Pat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>;
// brcond patterns
-// direct match equal/notequal zero branches
def : Pat<(brcond (setne CPURegs:$lhs, 0), bb:$dst),
(BNE CPURegs:$lhs, ZERO, bb:$dst)>;
def : Pat<(brcond (seteq CPURegs:$lhs, 0), bb:$dst),
(BEQ CPURegs:$lhs, ZERO, bb:$dst)>;
def : Pat<(brcond (setge CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
- (BGEZ (SUB CPURegs:$lhs, CPURegs:$rhs), bb:$dst)>;
+ (BEQ (SLT CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>;
def : Pat<(brcond (setuge CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
- (BGEZ (SUBu CPURegs:$lhs, CPURegs:$rhs), bb:$dst)>;
-
-def : Pat<(brcond (setgt CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
- (BGTZ (SUB CPURegs:$lhs, CPURegs:$rhs), bb:$dst)>;
-def : Pat<(brcond (setugt CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
- (BGTZ (SUBu CPURegs:$lhs, CPURegs:$rhs), bb:$dst)>;
+ (BEQ (SLTu CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>;
+def : Pat<(brcond (setge CPURegs:$lhs, immSExt16:$rhs), bb:$dst),
+ (BEQ (SLTi CPURegs:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>;
+def : Pat<(brcond (setuge CPURegs:$lhs, immSExt16:$rhs), bb:$dst),
+ (BEQ (SLTiu CPURegs:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>;
def : Pat<(brcond (setle CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
- (BLEZ (SUB CPURegs:$lhs, CPURegs:$rhs), bb:$dst)>;
+ (BEQ (SLT CPURegs:$rhs, CPURegs:$lhs), ZERO, bb:$dst)>;
def : Pat<(brcond (setule CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
- (BLEZ (SUBu CPURegs:$lhs, CPURegs:$rhs), bb:$dst)>;
-
-def : Pat<(brcond (setlt CPURegs:$lhs, immSExt16:$rhs), bb:$dst),
- (BNE (SLTi CPURegs:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>;
-def : Pat<(brcond (setult CPURegs:$lhs, immZExt16:$rhs), bb:$dst),
- (BNE (SLTiu CPURegs:$lhs, immZExt16:$rhs), ZERO, bb:$dst)>;
-def : Pat<(brcond (setlt CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
- (BNE (SLT CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>;
-def : Pat<(brcond (setult CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
- (BNE (SLTu CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>;
-
-def : Pat<(brcond (setlt CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
- (BLTZ (SUB CPURegs:$lhs, CPURegs:$rhs), bb:$dst)>;
-def : Pat<(brcond (setult CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
- (BLTZ (SUBu CPURegs:$lhs, CPURegs:$rhs), bb:$dst)>;
-
-// generic brcond pattern
+ (BEQ (SLTu CPURegs:$rhs, CPURegs:$lhs), ZERO, bb:$dst)>;
+
def : Pat<(brcond CPURegs:$cond, bb:$dst),
(BNE CPURegs:$cond, ZERO, bb:$dst)>;
-// setcc patterns, only matched when there
-// is no brcond following a setcc operation
+// select patterns
+def : Pat<(select (setge CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F),
+ (MOVZ CPURegs:$F, CPURegs:$T, (SLT CPURegs:$lhs, CPURegs:$rhs))>;
+def : Pat<(select (setuge CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F),
+ (MOVZ CPURegs:$F, CPURegs:$T, (SLTu CPURegs:$lhs, CPURegs:$rhs))>;
+def : Pat<(select (setge CPURegs:$lhs, immSExt16:$rhs), CPURegs:$T, CPURegs:$F),
+ (MOVZ CPURegs:$F, CPURegs:$T, (SLTi CPURegs:$lhs, immSExt16:$rhs))>;
+def : Pat<(select (setuge CPURegs:$lh, immSExt16:$rh), CPURegs:$T, CPURegs:$F),
+ (MOVZ CPURegs:$F, CPURegs:$T, (SLTiu CPURegs:$lh, immSExt16:$rh))>;
+
+def : Pat<(select (setle CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F),
+ (MOVZ CPURegs:$F, CPURegs:$T, (SLT CPURegs:$rhs, CPURegs:$lhs))>;
+def : Pat<(select (setule CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F),
+ (MOVZ CPURegs:$F, CPURegs:$T, (SLTu CPURegs:$rhs, CPURegs:$lhs))>;
+
+def : Pat<(select (seteq CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F),
+ (MOVZ CPURegs:$F, CPURegs:$T, (XOR CPURegs:$lhs, CPURegs:$rhs))>;
+def : Pat<(select (setne CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F),
+ (MOVN CPURegs:$F, CPURegs:$T, (XOR CPURegs:$lhs, CPURegs:$rhs))>;
+
+def : Pat<(select CPURegs:$cond, CPURegs:$T, CPURegs:$F),
+ (MOVN CPURegs:$F, CPURegs:$T, CPURegs:$cond)>;
+
+// setcc patterns
+def : Pat<(seteq CPURegs:$lhs, CPURegs:$rhs),
+ (SLTu (XOR CPURegs:$lhs, CPURegs:$rhs), 1)>;
+def : Pat<(setne CPURegs:$lhs, CPURegs:$rhs),
+ (SLTu ZERO, (XOR CPURegs:$lhs, CPURegs:$rhs))>;
+
def : Pat<(setle CPURegs:$lhs, CPURegs:$rhs),
(XORi (SLT CPURegs:$rhs, CPURegs:$lhs), 1)>;
def : Pat<(setule CPURegs:$lhs, CPURegs:$rhs),
def : Pat<(setuge CPURegs:$lhs, CPURegs:$rhs),
(XORi (SLTu CPURegs:$lhs, CPURegs:$rhs), 1)>;
-def : Pat<(setne CPURegs:$lhs, CPURegs:$rhs),
- (OR (SLT CPURegs:$lhs, CPURegs:$rhs),
- (SLT CPURegs:$rhs, CPURegs:$lhs))>;
-
-def : Pat<(seteq CPURegs:$lhs, CPURegs:$rhs),
- (XORi (OR (SLT CPURegs:$lhs, CPURegs:$rhs),
- (SLT CPURegs:$rhs, CPURegs:$lhs)), 1)>;
-
def : Pat<(setge CPURegs:$lhs, immSExt16:$rhs),
(XORi (SLTi CPURegs:$lhs, immSExt16:$rhs), 1)>;
-def : Pat<(setuge CPURegs:$lhs, immZExt16:$rhs),
- (XORi (SLTiu CPURegs:$lhs, immZExt16:$rhs), 1)>;
+def : Pat<(setuge CPURegs:$lhs, immSExt16:$rhs),
+ (XORi (SLTiu CPURegs:$lhs, immSExt16:$rhs), 1)>;
//===----------------------------------------------------------------------===//
// Floating Point Support