OSDN Git Service

* config/m68k/m68k.h (REGISTER_NAMES): Prefix each name with
[pf3gnuchains/gcc-fork.git] / gcc / doloop.c
index f3b3029..6d4840a 100644 (file)
@@ -1,5 +1,6 @@
 /* Perform doloop optimizations
-   Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+   Free Software Foundation, Inc.
    Contributed by Michael P. Hayes (m.hayes@elec.canterbury.ac.nz)
 
 This file is part of GCC.
@@ -21,6 +22,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "rtl.h"
 #include "flags.h"
 #include "expr.h"
@@ -29,6 +32,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "basic-block.h"
 #include "toplev.h"
 #include "tm_p.h"
+#include "cfgloop.h"
 
 
 /* This module is used to modify loops with a determinable number of
@@ -56,23 +60,19 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #ifdef HAVE_doloop_end
 
-static rtx doloop_condition_get
-  PARAMS ((rtx));
-static unsigned HOST_WIDE_INT doloop_iterations_max
-  PARAMS ((const struct loop_info *, enum machine_mode, int));
-static int doloop_valid_p
-  PARAMS ((const struct loop *, rtx));
-static int doloop_modify
-  PARAMS ((const struct loop *, rtx, rtx, rtx, rtx, rtx));
-static int doloop_modify_runtime
-  PARAMS ((const struct loop *, rtx, rtx, rtx, enum machine_mode, rtx));
+static rtx doloop_condition_get (rtx);
+static unsigned HOST_WIDE_INT doloop_iterations_max (const struct loop_info *,
+                                                    enum machine_mode, int);
+static int doloop_valid_p (const struct loop *, rtx);
+static int doloop_modify (const struct loop *, rtx, rtx, rtx, rtx, rtx);
+static int doloop_modify_runtime (const struct loop *, rtx, rtx, rtx,
+                                 enum machine_mode, rtx);
 
 
 /* Return the loop termination condition for PATTERN or zero
    if it is not a decrement and branch jump insn.  */
 static rtx
-doloop_condition_get (pattern)
-     rtx pattern;
+doloop_condition_get (rtx pattern)
 {
   rtx cmp;
   rtx inc;
@@ -140,13 +140,11 @@ doloop_condition_get (pattern)
 
 /* Return an estimate of the maximum number of loop iterations for the
    loop specified by LOOP or zero if the loop is not normal.
-   MODE is the mode of the iteration count and NONNEG is non-zero if
+   MODE is the mode of the iteration count and NONNEG is nonzero if
    the iteration count has been proved to be non-negative.  */
 static unsigned HOST_WIDE_INT
-doloop_iterations_max (loop_info, mode, nonneg)
-     const struct loop_info *loop_info;
-     enum machine_mode mode;
-     int nonneg;
+doloop_iterations_max (const struct loop_info *loop_info,
+                      enum machine_mode mode, int nonneg)
 {
   unsigned HOST_WIDE_INT n_iterations_max;
   enum rtx_code code;
@@ -249,12 +247,10 @@ doloop_iterations_max (loop_info, mode, nonneg)
 }
 
 
-/* Return non-zero if the loop specified by LOOP is suitable for
+/* Return nonzero if the loop specified by LOOP is suitable for
    the use of special low-overhead looping instructions.  */
 static int
-doloop_valid_p (loop, jump_insn)
-     const struct loop *loop;
-     rtx jump_insn;
+doloop_valid_p (const struct loop *loop, rtx jump_insn)
 {
   const struct loop_info *loop_info = LOOP_INFO (loop);
 
@@ -339,6 +335,7 @@ doloop_valid_p (loop, jump_insn)
      condition at run-time and have an additional jump around the loop
      to ensure an infinite loop.  */
   if (loop_info->comparison_code == NE
+      && !loop_info->preconditioned
       && INTVAL (loop_info->increment) != -1
       && INTVAL (loop_info->increment) != 1)
     {
@@ -399,16 +396,10 @@ doloop_valid_p (loop, jump_insn)
    number of loop iterations, ITERATIONS_MAX is a CONST_INT specifying
    the maximum number of loop iterations, and DOLOOP_INSN is the
    low-overhead looping insn to emit at the end of the loop.  This
-   returns non-zero if it was successful.  */
+   returns nonzero if it was successful.  */
 static int
-doloop_modify (loop, iterations, iterations_max,
-              doloop_seq, start_label, condition)
-     const struct loop *loop;
-     rtx iterations;
-     rtx iterations_max;
-     rtx doloop_seq;
-     rtx start_label;
-     rtx condition;
+doloop_modify (const struct loop *loop, rtx iterations, rtx iterations_max,
+              rtx doloop_seq, rtx start_label, rtx condition)
 {
   rtx counter_reg;
   rtx count;
@@ -484,7 +475,7 @@ doloop_modify (loop, iterations, iterations_max,
        count = GEN_INT (INTVAL (count) - 1);
       else
        count = expand_simple_binop (GET_MODE (counter_reg), MINUS,
-                                    count, GEN_INT (1),
+                                    count, const1_rtx,
                                     0, 0, OPTAB_LIB_WIDEN);
     }
 
@@ -539,16 +530,11 @@ doloop_modify (loop, iterations, iterations_max,
    not present, we emit one.  The loop to modify is described by LOOP.
    ITERATIONS_MAX is a CONST_INT specifying the estimated maximum
    number of loop iterations.  DOLOOP_INSN is the low-overhead looping
-   insn to insert.  Returns non-zero if loop successfully modified.  */
+   insn to insert.  Returns nonzero if loop successfully modified.  */
 static int
-doloop_modify_runtime (loop, iterations_max,
-                      doloop_seq, start_label, mode, condition)
-     const struct loop *loop;
-     rtx iterations_max;
-     rtx doloop_seq;
-     rtx start_label;
-     enum machine_mode mode;
-     rtx condition;
+doloop_modify_runtime (const struct loop *loop, rtx iterations_max,
+                      rtx doloop_seq, rtx start_label,
+                      enum machine_mode mode, rtx condition)
 {
   const struct loop_info *loop_info = LOOP_INFO (loop);
   HOST_WIDE_INT abs_inc;
@@ -598,16 +584,19 @@ doloop_modify_runtime (loop, iterations_max,
 
      If the loop has been unrolled, the full calculation is
 
-       t1 = abs_inc * unroll_number;           increment per loop
-       n = abs (final - initial) / t1;         full loops
-       n += (abs (final - initial) % t1) != 0; partial loop
+       t1 = abs_inc * unroll_number;                   increment per loop
+       n = (abs (final - initial) + abs_inc - 1) / t1;    full loops
+       n += (abs (final - initial) + abs_inc - 1) % t1) >= abs_inc;
+                                                          partial loop
+     which works out to be equivalent to
 
-     However, in certain cases the unrolled loop will be preconditioned
-     by emitting copies of the loop body with conditional branches,
-     so that the unrolled loop is always a full loop and thus needs
-     no exit tests.  In this case we don't want to add the partial
-     loop count.  As above, when t1 is a power of two we don't need to
-     worry about overflow.
+       n = (abs (final - initial) + t1 - 1) / t1;
+
+     In the case where the loop was preconditioned, a few iterations
+     may have been executed earlier; but 'initial' was adjusted as they
+     were executed, so we don't need anything special for that case here.
+     As above, when t1 is a power of two we don't need to worry about
+     overflow.
 
      The division and modulo operations can be avoided by requiring
      that the increment is a power of 2 (precondition_loop_p enforces
@@ -668,8 +657,8 @@ doloop_modify_runtime (loop, iterations_max,
            fprintf (loop_dump_stream,
                 "Doloop: Basic induction var skips initial incr.\n");
 
-         diff = expand_simple_binop (mode, PLUS, diff, increment, diff,
-                                     unsigned_p, OPTAB_LIB_WIDEN);
+         diff = expand_simple_binop (mode, PLUS, diff, GEN_INT (abs_inc),
+                                     diff, unsigned_p, OPTAB_LIB_WIDEN);
        }
     }
 
@@ -682,10 +671,10 @@ doloop_modify_runtime (loop, iterations_max,
       if (shift_count < 0)
        abort ();
 
-      if (!loop_info->preconditioned)
-       diff = expand_simple_binop (GET_MODE (diff), PLUS,
-                                   diff, GEN_INT (abs_loop_inc - 1),
-                                   diff, 1, OPTAB_LIB_WIDEN);
+      /* (abs (final - initial) + abs_inc * unroll_number - 1) */
+      diff = expand_simple_binop (GET_MODE (diff), PLUS,
+                                 diff, GEN_INT (abs_loop_inc - 1),
+                                 diff, 1, OPTAB_LIB_WIDEN);
 
       /* (abs (final - initial) + abs_inc * unroll_number - 1)
         / (abs_inc * unroll_number)  */
@@ -749,11 +738,10 @@ doloop_modify_runtime (loop, iterations_max,
    suitable.  We distinguish between loops with compile-time bounds
    and those with run-time bounds.  Information from LOOP is used to
    compute the number of iterations and to determine whether the loop
-   is a candidate for this optimization.  Returns non-zero if loop
+   is a candidate for this optimization.  Returns nonzero if loop
    successfully modified.  */
 int
-doloop_optimize (loop)
-     const struct loop *loop;
+doloop_optimize (const struct loop *loop)
 {
   struct loop_info *loop_info = LOOP_INFO (loop);
   rtx initial_value;