mark "addr" as having type "iPTR", eliminating some type comparisons
[oota-llvm.git] / lib / Target / Mips / MipsInstrInfo.td
index 89e8ee26ea12aabad5e0c2b154560678cc0ac223..f16a8053358dea5ab09981cff419b79f85cfba75 100644 (file)
@@ -21,12 +21,15 @@ def SDT_MipsRet          : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
 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>]>;
 
 // Call
-def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain,
-                         SDNPOutFlag]>;
+def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, 
+                         [SDNPHasChain, SDNPOutFlag, SDNPOptInFlag]>;
 
 // Hi and Lo nodes are used to handle global addresses. Used on 
 // MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol 
@@ -48,11 +51,16 @@ def callseq_end   : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeqEnd,
 // 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.
@@ -61,10 +69,14 @@ def HasBitCount : Predicate<"Subtarget.hasBitCount()">;
 // 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";
@@ -73,21 +85,21 @@ def mem : Operand<i32> {
 
 // Transformation Function - get the lower 16 bits.
 def LO16 : SDNodeXForm<imm, [{
-  return getI32Imm((unsigned)N->getValue() & 0xFFFF);
+  return getI32Imm((unsigned)N->getZExtValue() & 0xFFFF);
 }]>;
 
 // Transformation Function - get the higher 16 bits.
 def HI16 : SDNodeXForm<imm, [{
-  return getI32Imm((unsigned)N->getValue() >> 16);
+  return getI32Imm((unsigned)N->getZExtValue() >> 16);
 }]>;
 
 // Node immediate fits as 16-bit sign extended on target immediate.
 // e.g. addi, andi
 def immSExt16  : PatLeaf<(imm), [{
   if (N->getValueType(0) == MVT::i32)
-    return (int32_t)N->getValue() == (short)N->getValue();
+    return (int32_t)N->getZExtValue() == (short)N->getZExtValue();
   else
-    return (int64_t)N->getValue() == (short)N->getValue();
+    return (int64_t)N->getZExtValue() == (short)N->getZExtValue();
 }]>;
 
 // Node immediate fits as 16-bit zero extended on target immediate.
@@ -96,19 +108,19 @@ def immSExt16  : PatLeaf<(imm), [{
 // e.g. addiu, sltiu
 def immZExt16  : PatLeaf<(imm), [{
   if (N->getValueType(0) == MVT::i32)
-    return (uint32_t)N->getValue() == (unsigned short)N->getValue();
+    return (uint32_t)N->getZExtValue() == (unsigned short)N->getZExtValue();
   else
-    return (uint64_t)N->getValue() == (unsigned short)N->getValue();
+    return (uint64_t)N->getZExtValue() == (unsigned short)N->getZExtValue();
 }], LO16>;
 
 // shamt field must fit in 5 bits.
 def immZExt5 : PatLeaf<(imm), [{
-  return N->getValue() == ((N->getValue()) & 0x1f) ;
+  return N->getZExtValue() == ((N->getZExtValue()) & 0x1f) ;
 }]>;
 
 // Mips Address Mode! SDNode frameindex could possibily be a match
 // since load and store instructions from stack used it.
-def addr : ComplexPattern<i32, 2, "SelectAddr", [frameindex], []>;
+def addr : ComplexPattern<iPTR, 2, "SelectAddr", [frameindex], []>;
 
 //===----------------------------------------------------------------------===//
 // Instructions specific format
@@ -143,6 +155,14 @@ class ArithI<bits<6> op, string instr_asm, SDNode OpNode,
       !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> :
@@ -204,7 +224,7 @@ class LoadUpper<bits<6> op, string instr_asm>:
       [], IIAlu>;
 
 // Memory Load/Store
-let isSimpleLoad = 1, hasDelaySlot = 1 in
+let canFoldAsLoad = 1, hasDelaySlot = 1 in
 class LoadM<bits<6> op, string instr_asm, PatFrag OpNode>:
   FI< op,
       (outs CPURegs:$dst),
@@ -286,7 +306,7 @@ let isCall=1, hasDelaySlot=1,
   class JumpLink<bits<6> op, string instr_asm>:
     FJ< op,
         (outs),
-        (ins calltarget:$target),
+        (ins calltarget:$target, variable_ops),
         !strconcat(instr_asm, "\t$target"),
         [(MipsJmpLink imm:$target)], IIBranch>;
 
@@ -295,14 +315,14 @@ let isCall=1, hasDelaySlot=1,
     FR< op,
         func,
         (outs),
-        (ins CPURegs:$rs),
+        (ins CPURegs:$rs, variable_ops),
         !strconcat(instr_asm, "\t$rs"),
         [(MipsJmpLink CPURegs:$rs)], IIBranch>;
 
   class BranchLink<string instr_asm>:
     FI< 0x1,
         (outs),
-        (ins CPURegs:$rs, brtarget:$target),
+        (ins CPURegs:$rs, brtarget:$target, variable_ops),
         !strconcat(instr_asm, "\t$rs, $target"),
         [], IIBranch>;
 }
@@ -352,6 +372,18 @@ class SignExtInReg<bits<6> func, string instr_asm, ValueType vt>:
       !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
@@ -361,10 +393,10 @@ class SignExtInReg<bits<6> func, string instr_asm, ValueType vt>:
 let Defs = [SP], Uses = [SP] in {
 def ADJCALLSTACKDOWN : MipsPseudo<(outs), (ins uimm16:$amt),
                                   "!ADJCALLSTACKDOWN $amt",
-                                  [(callseq_start imm:$amt)]>;
+                                  [(callseq_start timm:$amt)]>;
 def ADJCALLSTACKUP   : MipsPseudo<(outs), (ins uimm16:$amt1, uimm16:$amt2),
                                   "!ADJCALLSTACKUP $amt1",
-                                  [(callseq_end imm:$amt1, imm:$amt2)]>;
+                                  [(callseq_end timm:$amt1, timm:$amt2)]>;
 }
 
 // Some assembly macros need to avoid pseudoinstructions and assembler
@@ -385,7 +417,7 @@ def CPRESTORE : MipsPseudo<(outs), (ins uimm16:$loc), ".cprestore\t$loc\n", []>;
 // operation. The solution is to create a Mips pseudo SELECT_CC instruction
 // (MipsSelectCC), use LowerSELECT_CC to generate this instruction and finally 
 // replace it for real supported nodes into EmitInstrWithCustomInserter
-let usesCustomDAGSchedInserter = 1 in {
+let usesCustomInserter = 1 in {
   class PseudoSelCC<RegisterClass RC, string asmstr>: 
     MipsPseudo<(outs RC:$dst), (ins CPURegs:$CmpRes, RC:$T, RC:$F), asmstr, 
     [(set RC:$dst, (MipsSelectCC CPURegs:$CmpRes, RC:$T, RC:$F))]>;
@@ -402,10 +434,10 @@ def Select_CC : PseudoSelCC<CPURegs, "# MipsSelect_CC_i32">;
 //===----------------------------------------------------------------------===//
 
 /// 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>;
@@ -486,17 +518,32 @@ 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>;
 }
 
 /// 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
@@ -573,55 +620,65 @@ def : Pat<(not CPURegs:$in),
           (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),
@@ -637,18 +694,10 @@ def : Pat<(setge 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