aboutsummaryrefslogtreecommitdiff
path: root/gcc/optabs.c
diff options
context:
space:
mode:
authorMichael Hayes <m.hayes@elec.canterbury.ac.nz>1999-01-03 20:43:14 +0000
committerJeff Law <law@gcc.gnu.org>1999-01-03 13:43:14 -0700
commit362cc3d434b402148d579551c6f3ff4d4798a296 (patch)
treef3bee78195ed2ea424f2fed1ca5659020bca3406 /gcc/optabs.c
parent1cd0a8edcaa31b8e1b76fc17ae41f3aa268fd5af (diff)
downloadgcc-362cc3d434b402148d579551c6f3ff4d4798a296.zip
gcc-362cc3d434b402148d579551c6f3ff4d4798a296.tar.gz
gcc-362cc3d434b402148d579551c6f3ff4d4798a296.tar.bz2
optabs.c (emit_cmp_insn): Abort if asked to emit non-canonical RTL for a target with HAVE_cc0 defined.
* optabs.c (emit_cmp_insn): Abort if asked to emit non-canonical RTL for a target with HAVE_cc0 defined. (emit_cmp_and_jump_insns): New function. * expr.h (emit_cmp_and_jump_insns): Prototype it. * loop.c (check_dbra_loop): Use it to replace calls to emit_cmp_insn and emit_jump_insn and to canonicalise the comparison if necessary. * unroll.c (unroll_loop): Likewise. From-SVN: r24471
Diffstat (limited to 'gcc/optabs.c')
-rw-r--r--gcc/optabs.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/gcc/optabs.c b/gcc/optabs.c
index eb5f72a..e57a8fc 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -2722,6 +2722,14 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y, COMPARE) > 2)
y = force_reg (mode, y);
+#ifdef HAVE_cc0
+ /* Abort if we have a non-canonical comparison. The RTL documentation
+ states that canonical comparisons are required only for targets which
+ have cc0. */
+ if (CONSTANT_P (x) && ! CONSTANT_P (y))
+ abort();
+#endif
+
/* Don't let both operands fail to indicate the mode. */
if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
x = force_reg (mode, x);
@@ -2913,6 +2921,52 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
abort ();
}
+/* Generate code to compare X with Y so that the condition codes are
+ set and to jump to LABEL if the condition is true. If X is a
+ constant and Y is not a constant, then the comparison is swapped to
+ ensure that the comparison RTL has the canonical form.
+
+ MODE is the mode of the inputs (in case they are const_int).
+ UNSIGNEDP nonzero says that X and Y are unsigned;
+ this matters if they need to be widened.
+
+ If they have mode BLKmode, then SIZE specifies the size of both X and Y,
+ and ALIGN specifies the known shared alignment of X and Y.
+
+ COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
+ It is ignored for fixed-point and block comparisons;
+ it is used only for floating-point comparisons. */
+
+void
+emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, align, label)
+ rtx x, y;
+ enum rtx_code comparison;
+ rtx size;
+ enum machine_mode mode;
+ int unsignedp;
+ int align;
+ rtx label;
+{
+ rtx op0;
+ rtx op1;
+
+ if (GET_CODE (x) == CONST_INT)
+ {
+ /* Swap operands and condition to ensure canonical RTL. */
+ op0 = y;
+ op1 = x;
+ comparison = swap_condition (comparison);
+ }
+ else
+ {
+ op0 = x;
+ op1 = y;
+ }
+ emit_cmp_insn (op0, op1, comparison, size, mode, unsignedp, align);
+ emit_jump_insn ((*bcc_gen_fctn[(int) comparison]) (label));
+}
+
+
/* Nonzero if a compare of mode MODE can be done straightforwardly
(without splitting it into pieces). */