From eca9803844ddf459d3f5992aa88353603f0cb731 Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Fri, 2 Dec 2016 08:22:34 +0000 Subject: [PATCH] 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 * 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 * gcc.target/s390/zvector/vec-cmp-2.c: New test. From-SVN: r243155 --- gcc/ChangeLog | 10 +++++++++ gcc/config/s390/s390-protos.h | 1 + gcc/config/s390/s390.c | 42 +++++++++++++++++++++++++++++++++++ gcc/config/s390/s390.h | 12 ++++++++++ gcc/testsuite/ChangeLog | 4 ++++ 5 files changed, 69 insertions(+) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2d554090700..d06661e26c4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2016-12-02 Andreas Krebbel + + * 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 * config/s390/s390-modes.def (CCVEQANY, CCVH, CCVHANY, CCVHU) diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index 7ae98d49cd5..000a6771c68 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 445c147f3dc..dab4f43e37a 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 6be4d34ce13..1d6d7b25594 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 2ecf8f95de9..dc269ef178f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2016-12-02 Andreas Krebbel + + * gcc.target/s390/zvector/vec-cmp-2.c: New test. + 2016-12-02 Andreas Krebbel * gcc.target/s390/vector/vec-scalar-cmp-1.c: Fix and harden the -- 2.30.2