This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
doloop.c fix for PR 6984
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 18 Jun 2002 14:38:50 +0930
- Subject: doloop.c fix for PR 6984
This patch fixes PR 6984, and optimizes emitted code for the
abs_inc != 1 case. bootstrapped and regression tested i686-linux.
powerpc-linux test still in progress. OK to apply assuming the ppc
test passes?
gcc/ChangeLog
* doloop.c (doloop_modify_runtime <abs_inc != 1>): Simplify.
(doloop_modify_runtime <do-while>): Increment initial value before
comparing. Don't emit code when NE.
Index: gcc/doloop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doloop.c,v
retrieving revision 1.19
diff -c -p -r1.19 doloop.c
*** gcc/doloop.c 17 Jun 2002 22:45:44 -0000 1.19
--- gcc/doloop.c 18 Jun 2002 04:53:50 -0000
*************** doloop_modify_runtime (loop, iterations_
*** 666,715 ****
if (abs_inc * loop_info->unroll_number != 1)
{
int shift_count;
- rtx extra;
- rtx label;
- unsigned HOST_WIDE_INT limit;
shift_count = exact_log2 (abs_inc * loop_info->unroll_number);
if (shift_count < 0)
abort ();
- /* abs (final - initial) / (abs_inc * unroll_number) */
- iterations = expand_simple_binop (GET_MODE (diff), LSHIFTRT,
- diff, GEN_INT (shift_count),
- NULL_RTX, 1,
- OPTAB_LIB_WIDEN);
-
if (abs_inc != 1)
! {
! /* abs (final - initial) % (abs_inc * unroll_number) */
! rtx count = GEN_INT (abs_inc * loop_info->unroll_number - 1);
! extra = expand_simple_binop (GET_MODE (iterations), AND,
! diff, count, NULL_RTX, 1,
! OPTAB_LIB_WIDEN);
!
! /* If (abs (final - initial) % (abs_inc * unroll_number)
! <= abs_inc * (unroll - 1)),
! jump past following increment instruction. */
! label = gen_label_rtx ();
! limit = abs_inc * (loop_info->unroll_number - 1);
! emit_cmp_and_jump_insns (extra, GEN_INT (limit),
! limit == 0 ? EQ : LEU, NULL_RTX,
! GET_MODE (extra), 0, label);
! JUMP_LABEL (get_last_insn ()) = label;
! LABEL_NUSES (label)++;
!
! /* Increment the iteration count by one. */
! iterations = expand_simple_binop (GET_MODE (iterations), PLUS,
! iterations, GEN_INT (1),
! iterations, 1,
! OPTAB_LIB_WIDEN);
!
! emit_label (label);
! }
}
! else
! iterations = diff;
/* If there is a NOTE_INSN_LOOP_VTOP, we have a `for' or `while'
style loop, with a loop exit test at the start. Thus, we can
--- 666,687 ----
if (abs_inc * loop_info->unroll_number != 1)
{
int shift_count;
shift_count = exact_log2 (abs_inc * loop_info->unroll_number);
if (shift_count < 0)
abort ();
if (abs_inc != 1)
! diff = expand_simple_binop (GET_MODE (diff), PLUS,
! diff, GEN_INT (abs_inc - 1),
! diff, 1, OPTAB_LIB_WIDEN);
!
! /* (abs (final - initial) + abs_inc - 1) / (abs_inc * unroll_number) */
! diff = expand_simple_binop (GET_MODE (diff), LSHIFTRT,
! diff, GEN_INT (shift_count),
! diff, 1, OPTAB_LIB_WIDEN);
}
! iterations = diff;
/* If there is a NOTE_INSN_LOOP_VTOP, we have a `for' or `while'
style loop, with a loop exit test at the start. Thus, we can
*************** doloop_modify_runtime (loop, iterations_
*** 722,742 ****
iteration count to one if necessary. */
if (! loop->vtop)
{
- rtx label;
-
if (loop_dump_stream)
fprintf (loop_dump_stream, "Doloop: Do-while loop.\n");
! /* A `do-while' loop must iterate at least once. If the
! iteration count is bogus, we set the iteration count to 1.
Note that if the loop has been unrolled, then the loop body
! is guaranteed to execute at least once. */
! if (loop_info->unroll_number == 1)
{
/* Emit insns to test if the loop will immediately
terminate and to set the iteration count to 1 if true. */
label = gen_label_rtx();
! emit_cmp_and_jump_insns (copy_rtx (initial_value),
copy_rtx (loop_info->comparison_value),
comparison_code, NULL_RTX, mode, 0,
label);
--- 694,721 ----
iteration count to one if necessary. */
if (! loop->vtop)
{
if (loop_dump_stream)
fprintf (loop_dump_stream, "Doloop: Do-while loop.\n");
! /* A `do-while' loop must iterate at least once. For code like
! i = initial; do { ... } while (++i < final);
! we will calculate a bogus iteration count if initial > final.
! So detect this and set the iteration count to 1.
Note that if the loop has been unrolled, then the loop body
! is guaranteed to execute at least once. Also, when the
! comparison is NE, our calculated count will be OK. */
! if (loop_info->unroll_number == 1 && comparison_code != NE)
{
+ rtx label;
+ rtx after_one;
+
/* Emit insns to test if the loop will immediately
terminate and to set the iteration count to 1 if true. */
label = gen_label_rtx();
! after_one = expand_simple_binop (mode, PLUS,
! initial_value, increment, NULL_RTX,
! unsigned_p, OPTAB_LIB_WIDEN);
! emit_cmp_and_jump_insns (after_one,
copy_rtx (loop_info->comparison_value),
comparison_code, NULL_RTX, mode, 0,
label);
--
Alan Modra
IBM OzLabs - Linux Technology Centre