+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)
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);
}
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
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. */
#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:
+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