This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: unroller bug
- To: Michael Hayes <m dot hayes at elec dot canterbury dot ac dot nz>
- Subject: Re: unroller bug
- From: Michael Hayes <m dot hayes at elec dot canterbury dot ac dot nz>
- Date: Sun, 03 Jan 1999 23:07:52 +1300 (NZDT)
- Cc: law at cygnus dot com, egcs-patches at cygnus dot com
- References: <2690.915327701@hurl.cygnus.com><13966.65239.301583.459539@ongaonga.elec.canterbury.ac.nz>
Michael Hayes writes:
> This patch ensures that a canonical comparison is generated.
> However, it doesn't appear to fix the problem you had :-(
This patch supercedes the previous patch. It fixes a dumb mistake
and the function you sent me appears to unroll OK now.
Michael.
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.
(emit_cmp_and_jump_insns): New function.
* epxr.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.
Index: optabs.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/optabs.c,v
retrieving revision 1.19
diff -c -3 -p -r1.19 optabs.c
*** optabs.c 1998/12/16 20:57:27 1.19
--- optabs.c 1999/01/03 09:59:38
*************** emit_cmp_insn (x, y, comparison, size, m
*** 2722,2727 ****
--- 2722,2731 ----
if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y, COMPARE) > 2)
y = force_reg (mode, y);
+ /* Abort if we have a non-canonical comparison. */
+ if (CONSTANT_P (x) && ! CONSTANT_P (y))
+ abort();
+
/* Don't let both operands fail to indicate the mode. */
if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
x = force_reg (mode, x);
*************** emit_cmp_insn (x, y, comparison, size, m
*** 2912,2917 ****
--- 2916,2967 ----
else
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). */
Index: expr.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/expr.h,v
retrieving revision 1.28
diff -c -3 -p -r1.28 expr.h
*** expr.h 1998/12/16 20:55:22 1.28
--- expr.h 1999/01/03 09:59:38
*************** extern void emit_0_to_1_insn PROTO((rtx)
*** 614,619 ****
--- 614,624 ----
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));
Index: loop.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/loop.c,v
retrieving revision 1.110
diff -c -3 -p -r1.110 loop.c
*** loop.c 1998/12/30 21:51:53 1.110
--- loop.c 1999/01/03 09:59:41
*************** check_dbra_loop (loop_end, insn_count, l
*** 7072,7081 ****
/* 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)));
tem = gen_sequence ();
end_sequence ();
emit_jump_insn_before (tem, loop_end);
--- 7072,7080 ----
/* Add new compare/branch insn at end of loop. */
start_sequence ();
! 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);
Index: unroll.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/unroll.c,v
retrieving revision 1.39
diff -c -3 -p -r1.39 unroll.c
*** unroll.c 1998/12/16 20:58:43 1.39
--- unroll.c 1999/01/03 09:59:42
*************** unroll_loop (loop_end, insn_count, loop_
*** 919,930 ****
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]));
JUMP_LABEL (get_last_insn ()) = labels[1];
LABEL_NUSES (labels[1])++;
}
--- 919,927 ----
if (loop_info->comparison_code != NE)
{
! 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])++;
}
*************** unroll_loop (loop_end, insn_count, loop_
*** 964,979 ****
cmp_const = i;
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]));
JUMP_LABEL (get_last_insn ()) = labels[i];
LABEL_NUSES (labels[i])++;
}
--- 961,970 ----
cmp_const = i;
cmp_code = LE;
}
! 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])++;
}
*************** unroll_loop (loop_end, insn_count, loop_
*** 1002,1015 ****
cmp_const = abs_inc * (unroll_number - 1) + 1;
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]));
JUMP_LABEL (get_last_insn ()) = labels[0];
LABEL_NUSES (labels[0])++;
}
--- 993,1001 ----
cmp_const = abs_inc * (unroll_number - 1) + 1;
cmp_code = GE;
}
! 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])++;
}