The BLX instruction is encoded differently than the BL, because why not? In
[oota-llvm.git] / lib / Target / SystemZ / SystemZInstrFP.td
index 0c9a239972fe91b097e3bff73cfcaf55d7f85ac0..a65828061d3bc02066e8671c184c45af56580069 100644 (file)
 
 // FIXME: multiclassify!
 
-let usesCustomDAGSchedInserter = 1 in {
+//===----------------------------------------------------------------------===//
+// FP Pattern fragments
+
+def fpimm0 : PatLeaf<(fpimm), [{
+  return N->isExactlyValue(+0.0);
+}]>;
+
+def fpimmneg0 : PatLeaf<(fpimm), [{
+  return N->isExactlyValue(-0.0);
+}]>;
+
+let Uses = [PSW], usesCustomInserter = 1 in {
   def SelectF32 : Pseudo<(outs FP32:$dst), (ins FP32:$src1, FP32:$src2, i8imm:$cc),
                         "# SelectF32 PSEUDO",
                         [(set FP32:$dst,
-                              (SystemZselect FP32:$src1, FP32:$src2, imm:$cc))]>;
+                              (SystemZselect FP32:$src1, FP32:$src2, imm:$cc, PSW))]>;
   def SelectF64 : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2, i8imm:$cc),
                         "# SelectF64 PSEUDO",
                         [(set FP64:$dst,
-                              (SystemZselect FP64:$src1, FP64:$src2, imm:$cc))]>;
+                              (SystemZselect FP64:$src1, FP64:$src2, imm:$cc, PSW))]>;
 }
 
 //===----------------------------------------------------------------------===//
 // Move Instructions
 
+// Floating point constant loads.
+let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
+def LD_Fp032 : Pseudo<(outs FP32:$dst), (ins),
+                      "lzer\t{$dst}",
+                      [(set FP32:$dst, fpimm0)]>;
+def LD_Fp064 : Pseudo<(outs FP64:$dst), (ins),
+                      "lzdr\t{$dst}",
+                      [(set FP64:$dst, fpimm0)]>;
+}
+
 let neverHasSideEffects = 1 in {
 def FMOV32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src),
                       "ler\t{$dst, $src}",
@@ -37,7 +58,7 @@ def FMOV64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src),
                       []>;
 }
 
-let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in {
+let canFoldAsLoad = 1, isReMaterializable = 1 in {
 def FMOV32rm  : Pseudo<(outs FP32:$dst), (ins rriaddr12:$src),
                       "le\t{$dst, $src}",
                       [(set FP32:$dst, (load rriaddr12:$src))]>;
@@ -65,6 +86,13 @@ def FMOV64mry : Pseudo<(outs), (ins rriaddr:$dst, FP64:$src),
                        "stdy\t{$src, $dst}",
                        [(store FP64:$src, rriaddr:$dst)]>;
 
+def FCOPYSIGN32 : Pseudo<(outs FP32:$dst), (ins FP32:$src1, FP32:$src2),
+                         "cpsdr\t{$dst, $src2, $src1}",
+                         [(set FP32:$dst, (fcopysign FP32:$src1, FP32:$src2))]>;
+def FCOPYSIGN64 : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2),
+                         "cpsdr\t{$dst, $src2, $src1}",
+                         [(set FP64:$dst, (fcopysign FP64:$src1, FP64:$src2))]>;
+
 //===----------------------------------------------------------------------===//
 // Arithmetic Instructions
 
@@ -78,21 +106,28 @@ def FNEG64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src),
                        "lcdbr\t{$dst, $src}",
                        [(set FP64:$dst, (fneg FP64:$src)),
                         (implicit PSW)]>;
-}
-
-let isTwoAddress = 1 in {
-let Defs = [PSW] in {
-// FIXME: Add peephole for fneg(fabs) => load negative
 
 def FABS32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src),
-                       "lpebr\t{$dst}",
+                       "lpebr\t{$dst, $src}",
                        [(set FP32:$dst, (fabs FP32:$src)),
                         (implicit PSW)]>;
 def FABS64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src),
-                       "lpdbr\t{$dst}",
+                       "lpdbr\t{$dst, $src}",
                        [(set FP64:$dst, (fabs FP64:$src)),
                         (implicit PSW)]>;
 
+def FNABS32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src),
+                       "lnebr\t{$dst, $src}",
+                       [(set FP32:$dst, (fneg(fabs FP32:$src))),
+                        (implicit PSW)]>;
+def FNABS64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src),
+                       "lndbr\t{$dst, $src}",
+                       [(set FP64:$dst, (fneg(fabs FP64:$src))),
+                        (implicit PSW)]>;
+}
+
+let Constraints = "$src1 = $dst" in {
+let Defs = [PSW] in {
 let isCommutable = 1 in { // X = ADD Y, Z  == X = ADD Z, Y
 def FADD32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src1, FP32:$src2),
                        "aebr\t{$dst, $src2}",
@@ -104,13 +139,13 @@ def FADD64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2),
                         (implicit PSW)]>;
 }
 
-def FADD32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr:$src2),
+def FADD32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr12:$src2),
                        "aeb\t{$dst, $src2}",
-                       [(set FP32:$dst, (fadd FP32:$src1, (load rriaddr:$src2))),
+                       [(set FP32:$dst, (fadd FP32:$src1, (load rriaddr12:$src2))),
                         (implicit PSW)]>;
-def FADD64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr:$src2),
+def FADD64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr12:$src2),
                        "adb\t{$dst, $src2}",
-                       [(set FP64:$dst, (fadd FP64:$src1, (load rriaddr:$src2))),
+                       [(set FP64:$dst, (fadd FP64:$src1, (load rriaddr12:$src2))),
                         (implicit PSW)]>;
 
 def FSUB32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src1, FP32:$src2),
@@ -122,13 +157,13 @@ def FSUB64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2),
                        [(set FP64:$dst, (fsub FP64:$src1, FP64:$src2)),
                         (implicit PSW)]>;
 
-def FSUB32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr:$src2),
+def FSUB32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr12:$src2),
                        "seb\t{$dst, $src2}",
-                       [(set FP32:$dst, (fsub FP32:$src1, (load rriaddr:$src2))),
+                       [(set FP32:$dst, (fsub FP32:$src1, (load rriaddr12:$src2))),
                         (implicit PSW)]>;
-def FSUB64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr:$src2),
+def FSUB64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr12:$src2),
                        "sdb\t{$dst, $src2}",
-                       [(set FP64:$dst, (fsub FP64:$src1, (load rriaddr:$src2))),
+                       [(set FP64:$dst, (fsub FP64:$src1, (load rriaddr12:$src2))),
                         (implicit PSW)]>;
 } // Defs = [PSW]
 
@@ -141,20 +176,20 @@ def FMUL64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2),
                        [(set FP64:$dst, (fmul FP64:$src1, FP64:$src2))]>;
 }
 
-def FMUL32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr:$src2),
+def FMUL32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr12:$src2),
                        "meeb\t{$dst, $src2}",
-                       [(set FP32:$dst, (fmul FP32:$src1, (load rriaddr:$src2)))]>;
-def FMUL64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr:$src2),
+                       [(set FP32:$dst, (fmul FP32:$src1, (load rriaddr12:$src2)))]>;
+def FMUL64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr12:$src2),
                        "mdb\t{$dst, $src2}",
-                       [(set FP64:$dst, (fmul FP64:$src1, (load rriaddr:$src2)))]>;
+                       [(set FP64:$dst, (fmul FP64:$src1, (load rriaddr12:$src2)))]>;
 
 def FMADD32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src1, FP32:$src2, FP32:$src3),
                        "maebr\t{$dst, $src3, $src2}",
                        [(set FP32:$dst, (fadd (fmul FP32:$src2, FP32:$src3),
                                               FP32:$src1))]>;
-def FMADD32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr:$src2, FP32:$src3),
+def FMADD32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr12:$src2, FP32:$src3),
                        "maeb\t{$dst, $src3, $src2}",
-                       [(set FP32:$dst, (fadd (fmul (load rriaddr:$src2),
+                       [(set FP32:$dst, (fadd (fmul (load rriaddr12:$src2),
                                                      FP32:$src3),
                                               FP32:$src1))]>;
 
@@ -162,9 +197,9 @@ def FMADD64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2, FP64:$src3
                        "madbr\t{$dst, $src3, $src2}",
                        [(set FP64:$dst, (fadd (fmul FP64:$src2, FP64:$src3),
                                               FP64:$src1))]>;
-def FMADD64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr:$src2, FP64:$src3),
+def FMADD64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr12:$src2, FP64:$src3),
                        "madb\t{$dst, $src3, $src2}",
-                       [(set FP64:$dst, (fadd (fmul (load rriaddr:$src2),
+                       [(set FP64:$dst, (fadd (fmul (load rriaddr12:$src2),
                                                      FP64:$src3),
                                               FP64:$src1))]>;
 
@@ -172,9 +207,9 @@ def FMSUB32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src1, FP32:$src2, FP32:$src3
                        "msebr\t{$dst, $src3, $src2}",
                        [(set FP32:$dst, (fsub (fmul FP32:$src2, FP32:$src3),
                                               FP32:$src1))]>;
-def FMSUB32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr:$src2, FP32:$src3),
+def FMSUB32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr12:$src2, FP32:$src3),
                        "mseb\t{$dst, $src3, $src2}",
-                       [(set FP32:$dst, (fsub (fmul (load rriaddr:$src2),
+                       [(set FP32:$dst, (fsub (fmul (load rriaddr12:$src2),
                                                      FP32:$src3),
                                               FP32:$src1))]>;
 
@@ -182,9 +217,9 @@ def FMSUB64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2, FP64:$src3
                        "msdbr\t{$dst, $src3, $src2}",
                        [(set FP64:$dst, (fsub (fmul FP64:$src2, FP64:$src3),
                                               FP64:$src1))]>;
-def FMSUB64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr:$src2, FP64:$src3),
+def FMSUB64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr12:$src2, FP64:$src3),
                        "msdb\t{$dst, $src3, $src2}",
-                       [(set FP64:$dst, (fsub (fmul (load rriaddr:$src2),
+                       [(set FP64:$dst, (fsub (fmul (load rriaddr12:$src2),
                                                      FP64:$src3),
                                               FP64:$src1))]>;
 
@@ -195,14 +230,28 @@ def FDIV64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src1, FP64:$src2),
                        "ddbr\t{$dst, $src2}",
                        [(set FP64:$dst, (fdiv FP64:$src1, FP64:$src2))]>;
 
-def FDIV32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr:$src2),
+def FDIV32rm : Pseudo<(outs FP32:$dst), (ins FP32:$src1, rriaddr12:$src2),
                        "deb\t{$dst, $src2}",
-                       [(set FP32:$dst, (fdiv FP32:$src1, (load rriaddr:$src2)))]>;
-def FDIV64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr:$src2),
+                       [(set FP32:$dst, (fdiv FP32:$src1, (load rriaddr12:$src2)))]>;
+def FDIV64rm : Pseudo<(outs FP64:$dst), (ins FP64:$src1, rriaddr12:$src2),
                        "ddb\t{$dst, $src2}",
-                       [(set FP64:$dst, (fdiv FP64:$src1, (load rriaddr:$src2)))]>;
+                       [(set FP64:$dst, (fdiv FP64:$src1, (load rriaddr12:$src2)))]>;
+
+} // Constraints = "$src1 = $dst"
+
+def FSQRT32rr : Pseudo<(outs FP32:$dst), (ins FP32:$src),
+                       "sqebr\t{$dst, $src}",
+                       [(set FP32:$dst, (fsqrt FP32:$src))]>;
+def FSQRT64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src),
+                       "sqdbr\t{$dst, $src}",
+                       [(set FP64:$dst, (fsqrt FP64:$src))]>;
 
-} // isTwoAddress = 1
+def FSQRT32rm : Pseudo<(outs FP32:$dst), (ins rriaddr12:$src),
+                       "sqeb\t{$dst, $src}",
+                       [(set FP32:$dst, (fsqrt (load rriaddr12:$src)))]>;
+def FSQRT64rm : Pseudo<(outs FP64:$dst), (ins rriaddr12:$src),
+                       "sqdb\t{$dst, $src}",
+                       [(set FP64:$dst, (fsqrt (load rriaddr12:$src)))]>;
 
 def FROUND64r32 : Pseudo<(outs FP32:$dst), (ins FP64:$src),
                          "ledbr\t{$dst, $src}",
@@ -211,9 +260,9 @@ def FROUND64r32 : Pseudo<(outs FP32:$dst), (ins FP64:$src),
 def FEXT32r64   : Pseudo<(outs FP64:$dst), (ins FP32:$src),
                          "ldebr\t{$dst, $src}",
                          [(set FP64:$dst, (fextend FP32:$src))]>;
-def FEXT32m64   : Pseudo<(outs FP64:$dst), (ins rriaddr:$src),
+def FEXT32m64   : Pseudo<(outs FP64:$dst), (ins rriaddr12:$src),
                          "ldeb\t{$dst, $src}",
-                         [(set FP64:$dst, (fextend (load rriaddr:$src)))]>;
+                         [(set FP64:$dst, (fextend (load rriaddr12:$src)))]>;
 
 let Defs = [PSW] in {
 def FCONVFP32   : Pseudo<(outs FP32:$dst), (ins GR32:$src),
@@ -235,24 +284,31 @@ def FCONVFP64   : Pseudo<(outs FP64:$dst), (ins GR64:$src),
                           (implicit PSW)]>;
 
 def FCONVGR32   : Pseudo<(outs GR32:$dst), (ins FP32:$src),
-                         "cfebr\t{$dst, $src}",
+                         "cfebr\t{$dst, 5, $src}",
                          [(set GR32:$dst, (fp_to_sint FP32:$src)),
                           (implicit PSW)]>;
 def FCONVGR32r64: Pseudo<(outs GR32:$dst), (ins FP64:$src),
-                         "cgebr\t{$dst, $src}",
+                         "cfdbr\t{$dst, 5, $src}",
                          [(set GR32:$dst, (fp_to_sint FP64:$src)),
                           (implicit PSW)]>;
 
 def FCONVGR64r32: Pseudo<(outs GR64:$dst), (ins FP32:$src),
-                         "cfdbr\t{$dst, $src}",
+                         "cgebr\t{$dst, 5, $src}",
                          [(set GR64:$dst, (fp_to_sint FP32:$src)),
                           (implicit PSW)]>;
 def FCONVGR64   : Pseudo<(outs GR64:$dst), (ins FP64:$src),
-                         "cgdbr\t{$dst, $src}",
+                         "cgdbr\t{$dst, 5, $src}",
                          [(set GR64:$dst, (fp_to_sint FP64:$src)),
                           (implicit PSW)]>;
 } // Defs = [PSW]
 
+def FBCONVG64   : Pseudo<(outs GR64:$dst), (ins FP64:$src),
+                         "lgdr\t{$dst, $src}",
+                         [(set GR64:$dst, (bitconvert FP64:$src))]>;
+def FBCONVF64   : Pseudo<(outs FP64:$dst), (ins GR64:$src),
+                         "ldgr\t{$dst, $src}",
+                         [(set FP64:$dst, (bitconvert GR64:$src))]>;
+
 //===----------------------------------------------------------------------===//
 // Test instructions (like AND but do not produce any result)
 
@@ -260,17 +316,25 @@ def FCONVGR64   : Pseudo<(outs GR64:$dst), (ins FP64:$src),
 let Defs = [PSW] in {
 def FCMP32rr : Pseudo<(outs), (ins FP32:$src1, FP32:$src2),
                       "cebr\t$src1, $src2",
-                      [(SystemZcmp FP32:$src1, FP32:$src2), (implicit PSW)]>;
+                      [(set PSW, (SystemZcmp FP32:$src1, FP32:$src2))]>;
 def FCMP64rr : Pseudo<(outs), (ins FP64:$src1, FP64:$src2),
                       "cdbr\t$src1, $src2",
-                      [(SystemZcmp FP64:$src1, FP64:$src2), (implicit PSW)]>;
+                      [(set PSW, (SystemZcmp FP64:$src1, FP64:$src2))]>;
 
-def FCMP32rm : Pseudo<(outs), (ins FP32:$src1, rriaddr:$src2),
+def FCMP32rm : Pseudo<(outs), (ins FP32:$src1, rriaddr12:$src2),
                       "ceb\t$src1, $src2",
-                      [(SystemZcmp FP32:$src1, (load rriaddr:$src2)),
-                       (implicit PSW)]>;
-def FCMP64rm : Pseudo<(outs), (ins FP64:$src1, rriaddr:$src2),
+                      [(set PSW, (SystemZcmp FP32:$src1,
+                                             (load rriaddr12:$src2)))]>;
+def FCMP64rm : Pseudo<(outs), (ins FP64:$src1, rriaddr12:$src2),
                       "cdb\t$src1, $src2",
-                      [(SystemZcmp FP64:$src1, (load rriaddr:$src2)),
-                       (implicit PSW)]>;
+                      [(set PSW, (SystemZcmp FP64:$src1,
+                                             (load rriaddr12:$src2)))]>;
 } // Defs = [PSW]
+
+//===----------------------------------------------------------------------===//
+// Non-Instruction Patterns
+//===----------------------------------------------------------------------===//
+
+// Floating point constant -0.0
+def : Pat<(f32 fpimmneg0), (FNEG32rr (LD_Fp032))>;
+def : Pat<(f64 fpimmneg0), (FNEG64rr (LD_Fp064))>;