S/390: Merge compare of compare results
authorAndreas Krebbel <krebbel@linux.vnet.ibm.com>
Fri, 2 Dec 2016 08:22:34 +0000 (08:22 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Fri, 2 Dec 2016 08:22:34 +0000 (08:22 +0000)
With this patch EQ and NE compares on CC mode reader patterns are
folded.  This allows using the result of the vec_all_* and vec_any_*
builtins directly in a conditional jump instruction as in the attached
testcase.

gcc/ChangeLog:

2016-12-02  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>

* config/s390/s390-protos.h (s390_reverse_condition): New
prototype.
* config/s390/s390.c (s390_canonicalize_comparison): Fold compares
of CC mode values.
(s390_reverse_condition): New function.
* config/s390/s390.h (REVERSE_CC_MODE, REVERSE_CONDITION): Define
target macros.

gcc/testsuite/ChangeLog:

2016-12-02  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>

* gcc.target/s390/zvector/vec-cmp-2.c: New test.

From-SVN: r243155

gcc/ChangeLog
gcc/config/s390/s390-protos.h
gcc/config/s390/s390.c
gcc/config/s390/s390.h
gcc/testsuite/ChangeLog

index 2d5540907009f9e82cb68710f4a6a69fd6ff9c43..d06661e26c4fd7d1d83ad61f673b3ac2f7310c81 100644 (file)
@@ -1,3 +1,13 @@
+2016-12-02  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
+
+       * config/s390/s390-protos.h (s390_reverse_condition): New
+       prototype.
+       * config/s390/s390.c (s390_canonicalize_comparison): Fold compares
+       of CC mode values.
+       (s390_reverse_condition): New function.
+       * config/s390/s390.h (REVERSE_CC_MODE, REVERSE_CONDITION): Define
+       target macros.
+
 2016-12-02  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
 
        * config/s390/s390-modes.def (CCVEQANY, CCVH, CCVHANY, CCVHU)
index 7ae98d49cd59facdf1026a938496b3196dfb19f9..000a6771c6827082775e1285489f707a7cbbc402 100644 (file)
@@ -119,6 +119,7 @@ extern void s390_expand_atomic (machine_mode, enum rtx_code,
 extern void s390_expand_tbegin (rtx, rtx, rtx, bool);
 extern void s390_expand_vec_compare (rtx, enum rtx_code, rtx, rtx);
 extern void s390_expand_vec_compare_cc (rtx, enum rtx_code, rtx, rtx, bool);
+extern enum rtx_code s390_reverse_condition (machine_mode, enum rtx_code);
 extern void s390_expand_vcond (rtx, rtx, rtx, enum rtx_code, rtx, rtx);
 extern void s390_expand_vec_init (rtx, rtx);
 extern rtx s390_return_addr_rtx (int, rtx);
index 445c147f3dcdcade6f82102d3fe7d1e10ca37098..dab4f43e37a33f1848f88d78f376d0a602bc9dde 100644 (file)
@@ -1722,6 +1722,31 @@ s390_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
        }
       tmp = *op0; *op0 = *op1; *op1 = tmp;
     }
+
+  /* A comparison result is compared against zero.  Replace it with
+     the (perhaps inverted) original comparison.
+     This probably should be done by simplify_relational_operation.  */
+  if ((*code == EQ || *code == NE)
+      && *op1 == const0_rtx
+      && COMPARISON_P (*op0)
+      && CC_REG_P (XEXP (*op0, 0)))
+    {
+      enum rtx_code new_code;
+
+      if (*code == EQ)
+       new_code = reversed_comparison_code_parts (GET_CODE (*op0),
+                                                  XEXP (*op0, 0),
+                                                  XEXP (*op1, 0), NULL);
+      else
+       new_code = GET_CODE (*op0);
+
+      if (new_code != UNKNOWN)
+       {
+         *code = new_code;
+         *op1 = XEXP (*op0, 1);
+         *op0 = XEXP (*op0, 0);
+       }
+    }
 }
 
 /* Helper function for s390_emit_compare.  If possible emit a 64 bit
@@ -6343,6 +6368,23 @@ s390_expand_vec_compare_cc (rtx target, enum rtx_code code,
                                        tmp_reg, target));
 }
 
+/* Invert the comparison CODE applied to a CC mode.  This is only safe
+   if we know whether there result was created by a floating point
+   compare or not.  For the CCV modes this is encoded as part of the
+   mode.  */
+enum rtx_code
+s390_reverse_condition (machine_mode mode, enum rtx_code code)
+{
+  /* Reversal of FP compares takes care -- an ordered compare
+     becomes an unordered compare and vice versa.  */
+  if (mode == CCVFALLmode || mode == CCVFANYmode)
+    return reverse_condition_maybe_unordered (code);
+  else if (mode == CCVIALLmode || mode == CCVIANYmode)
+    return reverse_condition (code);
+  else
+    gcc_unreachable ();
+}
+
 /* Generate a vector comparison expression loading either elements of
    THEN or ELS into TARGET depending on the comparison COND of CMP_OP1
    and CMP_OP2.  */
index 6be4d34ce13a74365efa8af17f8f481550852809..1d6d7b25594ecf41a8478faefa56c45bb830f946 100644 (file)
@@ -513,6 +513,18 @@ extern const char *s390_host_detect_local_cpu (int argc, const char **argv);
 #define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS)                      \
   s390_cannot_change_mode_class ((FROM), (TO), (CLASS))
 
+/* We can reverse a CC mode safely if we know whether it comes from a
+   floating point compare or not.  With the vector modes it is encoded
+   as part of the mode.
+   FIXME: It might make sense to do this for other cc modes as well.  */
+#define REVERSIBLE_CC_MODE(MODE)                               \
+  ((MODE) == CCVIALLmode || (MODE) == CCVIANYmode              \
+   || (MODE) == CCVFALLmode || (MODE) == CCVFANYmode)
+
+/* Given a condition code and a mode, return the inverse condition.  */
+#define REVERSE_CONDITION(CODE, MODE) s390_reverse_condition (MODE, CODE)
+
+
 /* Register classes.  */
 
 /* We use the following register classes:
index 2ecf8f95de9bdb043b76d2d077c99521aff544c8..dc269ef178ffd9de93f552e3a9ea6ba95382e335 100644 (file)
@@ -1,3 +1,7 @@
+2016-12-02  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
+
+       * gcc.target/s390/zvector/vec-cmp-2.c: New test.
+
 2016-12-02  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
 
        * gcc.target/s390/vector/vec-scalar-cmp-1.c: Fix and harden the