aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Krebbel <krebbel@linux.vnet.ibm.com>2016-12-02 08:22:34 +0000
committerAndreas Krebbel <krebbel@gcc.gnu.org>2016-12-02 08:22:34 +0000
commiteca9803844ddf459d3f5992aa88353603f0cb731 (patch)
tree175e6e75fad8aa9948599146110c6f81308ef43d
parenta6a2b532f9c4e92277e390febc8c07f773becb1b (diff)
downloadgcc-eca9803844ddf459d3f5992aa88353603f0cb731.zip
gcc-eca9803844ddf459d3f5992aa88353603f0cb731.tar.gz
gcc-eca9803844ddf459d3f5992aa88353603f0cb731.tar.bz2
S/390: Merge compare of compare results
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
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/config/s390/s390-protos.h1
-rw-r--r--gcc/config/s390/s390.c42
-rw-r--r--gcc/config/s390/s390.h12
-rw-r--r--gcc/testsuite/ChangeLog4
5 files changed, 69 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2d55409..d06661e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,15 @@
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)
(CCVHUANY): Remove modes.
(CCVIH, CCVIHU, CCVIALL, CCVIANY, CCVFALL, CCVFANY): Add modes and
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index 7ae98d4..000a677 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -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);
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 445c147..dab4f43 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -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. */
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index 6be4d34..1d6d7b2 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -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:
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2ecf8f9..dc269ef 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
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
pattern checks.
* gcc.target/s390/zvector/vec-cmp-1.c: New test.