Expand 64-bit logical shift right inline
[oota-llvm.git] / lib / Target / SystemZ / SystemZInstrInfo.td
index 8985169e6cffbd515fd35052aee21b434aa7eb28..1891bba2aa4a3e44574bbd05e0874f25cabe9305 100644 (file)
@@ -32,12 +32,12 @@ def SDT_SystemZCall         : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
 def SDT_SystemZCallSeqStart : SDCallSeqStart<[SDTCisI64<0>]>;
 def SDT_SystemZCallSeqEnd   : SDCallSeqEnd<[SDTCisI64<0>, SDTCisI64<1>]>;
 def SDT_CmpTest             : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>;
-def SDT_BrCond              : SDTypeProfile<0, 2,
+def SDT_BrCond              : SDTypeProfile<0, 3,
                                            [SDTCisVT<0, OtherVT>,
-                                            SDTCisI8<1>]>;
-def SDT_SelectCC            : SDTypeProfile<1, 3,
+                                            SDTCisI8<1>, SDTCisVT<2, i64>]>;
+def SDT_SelectCC            : SDTypeProfile<1, 4,
                                            [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>,
-                                            SDTCisI8<3>]>;
+                                            SDTCisI8<3>, SDTCisVT<4, i64>]>;
 def SDT_Address             : SDTypeProfile<1, 1,
                                             [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>;
 
@@ -54,11 +54,11 @@ def SystemZcallseq_start :
 def SystemZcallseq_end :
                  SDNode<"ISD::CALLSEQ_END",   SDT_SystemZCallSeqEnd,
                         [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
-def SystemZcmp     : SDNode<"SystemZISD::CMP", SDT_CmpTest, [SDNPOutFlag]>;
-def SystemZucmp    : SDNode<"SystemZISD::UCMP", SDT_CmpTest, [SDNPOutFlag]>;
+def SystemZcmp     : SDNode<"SystemZISD::CMP", SDT_CmpTest>;
+def SystemZucmp    : SDNode<"SystemZISD::UCMP", SDT_CmpTest>;
 def SystemZbrcond  : SDNode<"SystemZISD::BRCOND", SDT_BrCond,
-                            [SDNPHasChain, SDNPInFlag]>;
-def SystemZselect  : SDNode<"SystemZISD::SELECT", SDT_SelectCC, [SDNPInFlag]>;
+                            [SDNPHasChain]>;
+def SystemZselect  : SDNode<"SystemZISD::SELECT", SDT_SelectCC>;
 def SystemZpcrelwrapper : SDNode<"SystemZISD::PCRelativeWrapper", SDT_Address, []>;
 
 
@@ -74,15 +74,15 @@ def ADJCALLSTACKUP   : Pseudo<(outs), (ins i64imm:$amt1, i64imm:$amt2),
                               "#ADJCALLSTACKUP",
                               [(SystemZcallseq_end timm:$amt1, timm:$amt2)]>;
 
-let usesCustomDAGSchedInserter = 1 in {
+let Uses = [PSW], usesCustomInserter = 1 in {
   def Select32 : Pseudo<(outs GR32:$dst), (ins GR32:$src1, GR32:$src2, i8imm:$cc),
                         "# Select32 PSEUDO",
                         [(set GR32:$dst,
-                              (SystemZselect GR32:$src1, GR32:$src2, imm:$cc))]>;
+                              (SystemZselect GR32:$src1, GR32:$src2, imm:$cc, PSW))]>;
   def Select64 : Pseudo<(outs GR64:$dst), (ins GR64:$src1, GR64:$src2, i8imm:$cc),
                         "# Select64 PSEUDO",
                         [(set GR64:$dst,
-                              (SystemZselect GR64:$src1, GR64:$src2, imm:$cc))]>;
+                              (SystemZselect GR64:$src1, GR64:$src2, imm:$cc, PSW))]>;
 }
 
 
@@ -106,46 +106,46 @@ let isBranch = 1, isTerminator = 1 in {
   let Uses = [PSW] in {
     def JO  : Pseudo<(outs), (ins brtarget:$dst),
                      "jo\t$dst",
-                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_O)]>;
+                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_O, PSW)]>;
     def JH  : Pseudo<(outs), (ins brtarget:$dst),
                      "jh\t$dst",
-                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_H)]>;
+                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_H, PSW)]>;
     def JNLE: Pseudo<(outs), (ins brtarget:$dst),
                      "jnle\t$dst",
-                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_NLE)]>;
+                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_NLE, PSW)]>;
     def JL  : Pseudo<(outs), (ins brtarget:$dst),
                      "jl\t$dst",
-                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_L)]>;
+                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_L, PSW)]>;
     def JNHE: Pseudo<(outs), (ins brtarget:$dst),
                      "jnhe\t$dst",
-                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_NHE)]>;
+                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_NHE, PSW)]>;
     def JLH : Pseudo<(outs), (ins brtarget:$dst),
                      "jlh\t$dst",
-                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_LH)]>;
+                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_LH, PSW)]>;
     def JNE : Pseudo<(outs), (ins brtarget:$dst),
                      "jne\t$dst",
-                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_NE)]>;
+                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_NE, PSW)]>;
     def JE  : Pseudo<(outs), (ins brtarget:$dst),
                      "je\t$dst",
-                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_E)]>;
+                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_E, PSW)]>;
     def JNLH: Pseudo<(outs), (ins brtarget:$dst),
                      "jnlh\t$dst",
-                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_NLH)]>;
+                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_NLH, PSW)]>;
     def JHE : Pseudo<(outs), (ins brtarget:$dst),
                      "jhe\t$dst",
-                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_HE)]>;
+                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_HE, PSW)]>;
     def JNL : Pseudo<(outs), (ins brtarget:$dst),
                      "jnl\t$dst",
-                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_NL)]>;
+                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_NL, PSW)]>;
     def JLE : Pseudo<(outs), (ins brtarget:$dst),
                      "jle\t$dst",
-                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_LE)]>;
+                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_LE, PSW)]>;
     def JNH : Pseudo<(outs), (ins brtarget:$dst),
                      "jnh\t$dst",
-                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_NH)]>;
+                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_NH, PSW)]>;
     def JNO : Pseudo<(outs), (ins brtarget:$dst),
                      "jno\t$dst",
-                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_NO)]>;
+                     [(SystemZbrcond bb:$dst, SYSTEMZ_COND_NO, PSW)]>;
   } // Uses = [PSW]
 } // isBranch = 1
 
@@ -324,6 +324,7 @@ def MOV8miy   : SIYI<0x52EB,
                      "mviy\t{$dst, $src}",
                      [(truncstorei8 (i32 i32immSExt8:$src), riaddr:$dst)]>;
 
+let AddedComplexity = 2 in {
 def MOV16mi   : SILI<0xE544,
                      (outs), (ins riaddr12:$dst, s16imm:$src),
                      "mvhhi\t{$dst, $src}",
@@ -339,6 +340,7 @@ def MOV64mi16 : SILI<0xE548,
                      "mvghi\t{$dst, $src}",
                      [(store (i64 immSExt16:$src), riaddr12:$dst)]>,
                      Requires<[IsZ10]>;
+}
 
 // sexts
 def MOVSX32rr8  : RREI<0xB926,
@@ -505,6 +507,16 @@ def BSWAP64rm : RXYI<0x0FE3, (outs GR64:$dst), (ins rriaddr:$src),
                      "lrvg\t{$dst, $src}",
                      [(set GR64:$dst, (bswap (load rriaddr:$src)))]>;
 
+//def BSWAP16mr : RXYI<0xE33F, (outs), (ins rriaddr:$dst, GR32:$src),
+//                     "strvh\t{$src, $dst}",
+//                     [(truncstorei16 (bswap GR32:$src), rriaddr:$dst)]>;
+def BSWAP32mr : RXYI<0xE33E, (outs), (ins rriaddr:$dst, GR32:$src),
+                     "strv\t{$src, $dst}",
+                     [(store (bswap GR32:$src), rriaddr:$dst)]>;
+def BSWAP64mr : RXYI<0xE32F, (outs), (ins rriaddr:$dst, GR64:$src),
+                     "strvg\t{$src, $dst}",
+                     [(store (bswap GR64:$src), rriaddr:$dst)]>;
+
 //===----------------------------------------------------------------------===//
 // Arithmetic Instructions
 
@@ -530,15 +542,29 @@ let Defs = [PSW] in {
 
 let isCommutable = 1 in { // X = ADD Y, Z  == X = ADD Z, Y
 def ADD32rr : RRI<0x1A, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
-                     "ar\t{$dst, $src2}",
-                     [(set GR32:$dst, (add GR32:$src1, GR32:$src2)),
-                      (implicit PSW)]>;
+                  "ar\t{$dst, $src2}",
+                  [(set GR32:$dst, (add GR32:$src1, GR32:$src2)),
+                   (implicit PSW)]>;
 def ADD64rr : RREI<0xB908, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2),
-                     "agr\t{$dst, $src2}",
-                     [(set GR64:$dst, (add GR64:$src1, GR64:$src2)),
-                      (implicit PSW)]>;
+                   "agr\t{$dst, $src2}",
+                   [(set GR64:$dst, (add GR64:$src1, GR64:$src2)),
+                    (implicit PSW)]>;
 }
 
+def ADD32rm   : RXI<0x5A, (outs GR32:$dst), (ins GR32:$src1, rriaddr12:$src2),
+                    "a\t{$dst, $src2}",
+                    [(set GR32:$dst, (add GR32:$src1, (load rriaddr12:$src2))),
+                     (implicit PSW)]>;
+def ADD32rmy  : RXYI<0xE35A, (outs GR32:$dst), (ins GR32:$src1, rriaddr:$src2),
+                     "ay\t{$dst, $src2}",
+                     [(set GR32:$dst, (add GR32:$src1, (load rriaddr:$src2))),
+                      (implicit PSW)]>;
+def ADD64rm   : RXYI<0xE308, (outs GR64:$dst), (ins GR64:$src1, rriaddr:$src2),
+                     "ag\t{$dst, $src2}",
+                     [(set GR64:$dst, (add GR64:$src1, (load rriaddr:$src2))),
+                      (implicit PSW)]>;
+
+
 def ADD32ri16 : RII<0xA7A,
                     (outs GR32:$dst), (ins GR32:$src1, s16imm:$src2),
                     "ahi\t{$dst, $src2}",
@@ -560,6 +586,35 @@ def ADD64ri32 : RILI<0xC28,
                      [(set GR64:$dst, (add GR64:$src1, immSExt32:$src2)),
                       (implicit PSW)]>;
 
+let isCommutable = 1 in { // X = ADC Y, Z  == X = ADC Z, Y
+def ADC32rr : RRI<0x1E, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
+                  "alr\t{$dst, $src2}",
+                  [(set GR32:$dst, (addc GR32:$src1, GR32:$src2))]>;
+def ADC64rr : RREI<0xB90A, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2),
+                   "algr\t{$dst, $src2}",
+                   [(set GR64:$dst, (addc GR64:$src1, GR64:$src2))]>;
+}
+
+def ADC32ri   : RILI<0xC2B,
+                     (outs GR32:$dst), (ins GR32:$src1, s32imm:$src2),
+                     "alfi\t{$dst, $src2}",
+                     [(set GR32:$dst, (addc GR32:$src1, imm:$src2))]>;
+def ADC64ri32 : RILI<0xC2A,
+                     (outs GR64:$dst), (ins GR64:$src1, s32imm64:$src2),
+                     "algfi\t{$dst, $src2}",
+                     [(set GR64:$dst, (addc GR64:$src1, immSExt32:$src2))]>;
+
+let Uses = [PSW] in {
+def ADDE32rr : RREI<0xB998, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
+                    "alcr\t{$dst, $src2}",
+                    [(set GR32:$dst, (adde GR32:$src1, GR32:$src2)),
+                     (implicit PSW)]>;
+def ADDE64rr : RREI<0xB988, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2),
+                    "alcgr\t{$dst, $src2}",
+                    [(set GR64:$dst, (adde GR64:$src1, GR64:$src2)),
+                     (implicit PSW)]>;
+}
+
 let isCommutable = 1 in { // X = AND Y, Z  == X = AND Z, Y
 def AND32rr : RRI<0x14,
                   (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
@@ -571,6 +626,19 @@ def AND64rr : RREI<0xB980,
                    [(set GR64:$dst, (and GR64:$src1, GR64:$src2))]>;
 }
 
+def AND32rm   : RXI<0x54, (outs GR32:$dst), (ins GR32:$src1, rriaddr12:$src2),
+                    "n\t{$dst, $src2}",
+                    [(set GR32:$dst, (and GR32:$src1, (load rriaddr12:$src2))),
+                     (implicit PSW)]>;
+def AND32rmy  : RXYI<0xE354, (outs GR32:$dst), (ins GR32:$src1, rriaddr:$src2),
+                     "ny\t{$dst, $src2}",
+                     [(set GR32:$dst, (and GR32:$src1, (load rriaddr:$src2))),
+                      (implicit PSW)]>;
+def AND64rm   : RXYI<0xE360, (outs GR64:$dst), (ins GR64:$src1, rriaddr:$src2),
+                     "ng\t{$dst, $src2}",
+                     [(set GR64:$dst, (and GR64:$src1, (load rriaddr:$src2))),
+                      (implicit PSW)]>;
+
 def AND32rill16 : RII<0xA57,
                       (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2),
                       "nill\t{$dst, $src2}",
@@ -622,6 +690,20 @@ def OR64rr : RREI<0xB981,
                   [(set GR64:$dst, (or GR64:$src1, GR64:$src2))]>;
 }
 
+def OR32rm   : RXI<0x56, (outs GR32:$dst), (ins GR32:$src1, rriaddr12:$src2),
+                   "o\t{$dst, $src2}",
+                   [(set GR32:$dst, (or GR32:$src1, (load rriaddr12:$src2))),
+                    (implicit PSW)]>;
+def OR32rmy  : RXYI<0xE356, (outs GR32:$dst), (ins GR32:$src1, rriaddr:$src2),
+                    "oy\t{$dst, $src2}",
+                    [(set GR32:$dst, (or GR32:$src1, (load rriaddr:$src2))),
+                     (implicit PSW)]>;
+def OR64rm   : RXYI<0xE381, (outs GR64:$dst), (ins GR64:$src1, rriaddr:$src2),
+                    "og\t{$dst, $src2}",
+                    [(set GR64:$dst, (or GR64:$src1, (load rriaddr:$src2))),
+                     (implicit PSW)]>;
+
+ // FIXME: Provide proper encoding!
 def OR32ri16  : RII<0xA5B,
                     (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2),
                     "oill\t{$dst, $src2}",
@@ -670,6 +752,47 @@ def SUB64rr : RREI<0xB909,
                    "sgr\t{$dst, $src2}",
                    [(set GR64:$dst, (sub GR64:$src1, GR64:$src2))]>;
 
+def SUB32rm   : RXI<0x5B, (outs GR32:$dst), (ins GR32:$src1, rriaddr12:$src2),
+                    "s\t{$dst, $src2}",
+                    [(set GR32:$dst, (sub GR32:$src1, (load rriaddr12:$src2))),
+                     (implicit PSW)]>;
+def SUB32rmy  : RXYI<0xE35B, (outs GR32:$dst), (ins GR32:$src1, rriaddr:$src2),
+                     "sy\t{$dst, $src2}",
+                     [(set GR32:$dst, (sub GR32:$src1, (load rriaddr:$src2))),
+                      (implicit PSW)]>;
+def SUB64rm   : RXYI<0xE309, (outs GR64:$dst), (ins GR64:$src1, rriaddr:$src2),
+                     "sg\t{$dst, $src2}",
+                     [(set GR64:$dst, (sub GR64:$src1, (load rriaddr:$src2))),
+                      (implicit PSW)]>;
+def SBC32rr : RRI<0x1F,
+                  (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
+                  "slr\t{$dst, $src2}",
+                  [(set GR32:$dst, (subc GR32:$src1, GR32:$src2))]>;
+def SBC64rr : RREI<0xB90B,
+                   (outs GR64:$dst), (ins GR64:$src1, GR64:$src2),
+                   "slgr\t{$dst, $src2}",
+                   [(set GR64:$dst, (subc GR64:$src1, GR64:$src2))]>;
+
+def SBC32ri   : RILI<0xC25,
+                     (outs GR32:$dst), (ins GR32:$src1, s32imm:$src2),
+                     "sllfi\t{$dst, $src2}",
+                     [(set GR32:$dst, (subc GR32:$src1, imm:$src2))]>;
+def SBC64ri32 : RILI<0xC24,
+                     (outs GR64:$dst), (ins GR64:$src1, s32imm64:$src2),
+                     "slgfi\t{$dst, $src2}",
+                     [(set GR64:$dst, (subc GR64:$src1, immSExt32:$src2))]>;
+
+let Uses = [PSW] in {
+def SUBE32rr : RREI<0xB999, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2),
+                    "slbr\t{$dst, $src2}",
+                    [(set GR32:$dst, (sube GR32:$src1, GR32:$src2)),
+                     (implicit PSW)]>;
+def SUBE64rr : RREI<0xB989, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2),
+                    "slbgr\t{$dst, $src2}",
+                    [(set GR64:$dst, (sube GR64:$src1, GR64:$src2)),
+                     (implicit PSW)]>;
+}
 
 let isCommutable = 1 in { // X = XOR Y, Z  == X = XOR Z, Y
 def XOR32rr : RRI<0x17,
@@ -682,6 +805,19 @@ def XOR64rr : RREI<0xB982,
                    [(set GR64:$dst, (xor GR64:$src1, GR64:$src2))]>;
 }
 
+def XOR32rm   : RXI<0x57,(outs GR32:$dst), (ins GR32:$src1, rriaddr12:$src2),
+                    "x\t{$dst, $src2}",
+                    [(set GR32:$dst, (xor GR32:$src1, (load rriaddr12:$src2))),
+                     (implicit PSW)]>;
+def XOR32rmy  : RXYI<0xE357, (outs GR32:$dst), (ins GR32:$src1, rriaddr:$src2),
+                     "xy\t{$dst, $src2}",
+                     [(set GR32:$dst, (xor GR32:$src1, (load rriaddr:$src2))),
+                      (implicit PSW)]>;
+def XOR64rm   : RXYI<0xE382, (outs GR64:$dst), (ins GR64:$src1, rriaddr:$src2),
+                     "xg\t{$dst, $src2}",
+                     [(set GR64:$dst, (xor GR64:$src1, (load rriaddr:$src2))),
+                      (implicit PSW)]>;
+
 def XOR32ri : RILI<0xC07,
                    (outs GR32:$dst), (ins GR32:$src1, i32imm:$src2),
                    "xilf\t{$dst, $src2}",
@@ -722,6 +858,7 @@ def MUL64ri16   : RII<0xA7D,
                       "mghi\t{$dst, $src2}",
                       [(set GR64:$dst, (mul GR64:$src1, immSExt16:$src2))]>;
 
+let AddedComplexity = 2 in {
 def MUL32ri     : RILI<0xC21,
                        (outs GR32:$dst), (ins GR32:$src1, s32imm:$src2),
                        "msfi\t{$dst, $src2}",
@@ -732,6 +869,7 @@ def MUL64ri32   : RILI<0xC20,
                        "msgfi\t{$dst, $src2}",
                        [(set GR64:$dst, (mul GR64:$src1, i64immSExt32:$src2))]>,
                        Requires<[IsZ10]>;
+}
 
 def MUL32rm : RXI<0x71,
                   (outs GR32:$dst), (ins GR32:$src1, rriaddr12:$src2),
@@ -941,6 +1079,15 @@ def UCMPZX64rm32  : RXYI<0xE331,
 
 } // Defs = [PSW]
 
+//===----------------------------------------------------------------------===//
+// Other crazy stuff
+let Defs = [PSW] in {
+def FLOGR64 : RREI<0xB983,
+                   (outs GR128:$dst), (ins GR64:$src),
+                   "flogr\t{$dst, $src}",
+                   []>;
+} // Defs = [PSW]
+
 //===----------------------------------------------------------------------===//
 // Non-Instruction Patterns.
 //===----------------------------------------------------------------------===//
@@ -1003,3 +1150,6 @@ def : Pat<(mulhu GR64:$src1, GR64:$src2),
                                                      GR64:$src1, subreg_odd),
                                       GR64:$src2),
                           subreg_even)>;
+
+def : Pat<(ctlz GR64:$src),
+          (EXTRACT_SUBREG (FLOGR64 GR64:$src), subreg_even)>;