+Sun Jan 3 22:58:15 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * 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.
+
Sun Jan 3 21:01:04 1999 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
* fixincludes (sys/utsname.h): Provide forward declaration of
extern void emit_cmp_insn PROTO((rtx, rtx, enum rtx_code, rtx,
enum machine_mode, int, int));
+/* Emit a pair of rtl insns to compare two rtx's and to jump
+ to a label if the comparison is true. */
+extern void emit_cmp_and_jump_insns PROTO((rtx, rtx, enum rtx_code, rtx,
+ enum machine_mode, int, int, rtx));
+
/* Nonzero if a compare of mode MODE can be done straightforwardly
(without splitting it into pieces). */
extern int can_compare_p PROTO((enum machine_mode));
/* Add new compare/branch insn at end of loop. */
start_sequence ();
- emit_cmp_insn (reg, const0_rtx, cmp_code, NULL_RTX,
- GET_MODE (reg), 0, 0);
- emit_jump_insn ((*bcc_gen_fctn[(int) cmp_code])
- (XEXP (jump_label, 0)));
+ emit_cmp_and_jump_insns (reg, const0_rtx, cmp_code, NULL_RTX,
+ GET_MODE (reg), 0, 0,
+ XEXP (jump_label, 0));
tem = gen_sequence ();
end_sequence ();
emit_jump_insn_before (tem, loop_end);
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);
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). */
if (loop_info->comparison_code != NE)
{
- emit_cmp_insn (initial_value, final_value, neg_inc ? LE : GE,
- NULL_RTX, mode, 0, 0);
- if (neg_inc)
- emit_jump_insn (gen_ble (labels[1]));
- else
- emit_jump_insn (gen_bge (labels[1]));
+ emit_cmp_and_jump_insns (initial_value, final_value,
+ neg_inc ? LE : GE,
+ NULL_RTX, mode, 0, 0, labels[1]);
JUMP_LABEL (get_last_insn ()) = labels[1];
LABEL_NUSES (labels[1])++;
}
cmp_code = LE;
}
- emit_cmp_insn (diff, GEN_INT (abs_inc * cmp_const),
- cmp_code, NULL_RTX, mode, 0, 0);
-
- if (i == 0)
- emit_jump_insn (gen_beq (labels[i]));
- else if (neg_inc)
- emit_jump_insn (gen_bge (labels[i]));
- else
- emit_jump_insn (gen_ble (labels[i]));
+ emit_cmp_and_jump_insns (diff, GEN_INT (abs_inc * cmp_const),
+ cmp_code, NULL_RTX, mode, 0, 0,
+ labels[i]);
JUMP_LABEL (get_last_insn ()) = labels[i];
LABEL_NUSES (labels[i])++;
}
cmp_code = GE;
}
- emit_cmp_insn (diff, GEN_INT (cmp_const), cmp_code, NULL_RTX,
- mode, 0, 0);
-
- if (neg_inc)
- emit_jump_insn (gen_ble (labels[0]));
- else
- emit_jump_insn (gen_bge (labels[0]));
+ emit_cmp_and_jump_insns (diff, GEN_INT (cmp_const), cmp_code,
+ NULL_RTX, mode, 0, 0, labels[0]);
JUMP_LABEL (get_last_insn ()) = labels[0];
LABEL_NUSES (labels[0])++;
}