OSDN Git Service

PR middle-end/22239
[pf3gnuchains/gcc-fork.git] / gcc / loop.c
index 2b765c8..ae06307 100644 (file)
@@ -17,8 +17,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 /* This is the loop optimization pass of the compiler.
    It finds invariant computations within loops and moves them
@@ -66,6 +66,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "optabs.h"
 #include "cfgloop.h"
 #include "ggc.h"
+#include "timevar.h"
+#include "tree-pass.h"
 
 /* Get the loop info pointer of a loop.  */
 #define LOOP_INFO(LOOP) ((struct loop_info *) (LOOP)->aux)
@@ -83,8 +85,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    of an insn added during loop, since these don't have LUIDs.  */
 
 #define INSN_LUID(INSN)                        \
-  (INSN_UID (INSN) < max_uid_for_loop ? uid_luid[INSN_UID (INSN)] \
-   : (abort (), -1))
+  (gcc_assert (INSN_UID (INSN) < max_uid_for_loop), uid_luid[INSN_UID (INSN)])
 
 #define REGNO_FIRST_LUID(REGNO)                        \
   (REGNO_FIRST_UID (REGNO) < max_uid_for_loop  \
@@ -425,7 +426,7 @@ struct loop_info
 #ifndef HAVE_prefetch
 #define HAVE_prefetch 0
 #define CODE_FOR_prefetch 0
-#define gen_prefetch(a,b,c) (abort(), NULL_RTX)
+#define gen_prefetch(a,b,c) (gcc_unreachable (), NULL_RTX)
 #endif
 
 /* Give up the prefetch optimizations once we exceed a given threshold.
@@ -869,8 +870,7 @@ loop_optimize (rtx f, FILE *dumpfile, int flags)
 
   /* See if we went too far.  Note that get_max_uid already returns
      one more that the maximum uid of all insn.  */
-  if (get_max_uid () > max_uid_for_loop)
-    abort ();
+  gcc_assert (get_max_uid () <= max_uid_for_loop);
   /* Now reset it to the actual size we need.  See above.  */
   max_uid_for_loop = get_max_uid ();
 
@@ -1137,6 +1137,7 @@ scan_loop (struct loop *loop, int flags)
          if (! in_libcall
              && (set = single_set (p))
              && REG_P (SET_DEST (set))
+             && SET_DEST (set) != frame_pointer_rtx
 #ifdef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
              && SET_DEST (set) != pic_offset_table_rtx
 #endif
@@ -2117,7 +2118,7 @@ rtx_equal_for_loop_p (rtx x, rtx y, struct loop_movables *movables,
             contain anything but integers and other rtx's,
             except for within LABEL_REFs and SYMBOL_REFs.  */
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
   return 1;
@@ -2310,21 +2311,26 @@ move_movables (struct loop *loop, struct loop_movables *movables,
 
                  for (count = m->consec; count >= 0; count--)
                    {
-                     /* If this is the first insn of a library call sequence,
-                        something is very wrong.  */
-                     if (!NOTE_P (p)
-                         && (temp = find_reg_note (p, REG_LIBCALL, NULL_RTX)))
-                       abort ();
-
-                     /* If this is the last insn of a libcall sequence, then
-                        delete every insn in the sequence except the last.
-                        The last insn is handled in the normal manner.  */
-                     if (!NOTE_P (p)
-                         && (temp = find_reg_note (p, REG_RETVAL, NULL_RTX)))
+                     if (!NOTE_P (p))
                        {
-                         temp = XEXP (temp, 0);
-                         while (temp != p)
-                           temp = delete_insn (temp);
+                         /* If this is the first insn of a library
+                            call sequence, something is very
+                            wrong.  */
+                         gcc_assert (!find_reg_note
+                                     (p, REG_LIBCALL, NULL_RTX));
+
+                         /* If this is the last insn of a libcall
+                            sequence, then delete every insn in the
+                            sequence except the last.  The last insn
+                            is handled in the normal manner.  */
+                         temp = find_reg_note (p, REG_RETVAL, NULL_RTX);
+                         
+                         if (temp)
+                           {
+                             temp = XEXP (temp, 0);
+                             while (temp != p)
+                               temp = delete_insn (temp);
+                           }
                        }
 
                      temp = p;
@@ -2488,8 +2494,7 @@ move_movables (struct loop *loop, struct loop_movables *movables,
                                        << GET_MODE_BITSIZE (m->savemode)))
                                      - 1),
                             reg, 1, OPTAB_LIB_WIDEN);
-                         if (tem == 0)
-                           abort ();
+                         gcc_assert (tem);
                          if (tem != reg)
                            emit_move_insn (reg, tem);
                          sequence = get_insns ();
@@ -2777,8 +2782,7 @@ replace_call_address (rtx x, rtx reg, rtx addr)
     case MEM:
       /* If this MEM uses a reg other than the one we expected,
         something is wrong.  */
-      if (XEXP (x, 0) != reg)
-       abort ();
+      gcc_assert (XEXP (x, 0) == reg);
       XEXP (x, 0) = addr;
       return;
 
@@ -3091,8 +3095,7 @@ find_and_verify_loops (rtx f, struct loops *loops)
            break;
 
          case NOTE_INSN_LOOP_END:
-           if (! current_loop)
-             abort ();
+           gcc_assert (current_loop);
 
            current_loop->end = insn;
            current_loop = current_loop->outer;
@@ -3280,6 +3283,7 @@ find_and_verify_loops (rtx f, struct loops *loops)
                    if (invert_jump (p, new_label, 1))
                      {
                        rtx q, r;
+                       bool only_notes;
 
                        /* If no suitable BARRIER was found, create a suitable
                           one before TARGET.  Since TARGET is a fall through
@@ -3304,8 +3308,10 @@ find_and_verify_loops (rtx f, struct loops *loops)
 
                        /* Include the BARRIER after INSN and copy the
                           block after LOC.  */
-                       if (squeeze_notes (&new_label, &last_insn_to_move))
-                         abort ();
+                       only_notes = squeeze_notes (&new_label,
+                                                   &last_insn_to_move);
+                       gcc_assert (!only_notes);
+                       
                        reorder_insns (new_label, last_insn_to_move, loc);
 
                        /* All those insns are now in TARGET_LOOP.  */
@@ -3340,8 +3346,7 @@ find_and_verify_loops (rtx f, struct loops *loops)
 
                            /* If we didn't find it, then something is
                               wrong.  */
-                           if (! r)
-                             abort ();
+                           gcc_assert (r);
                          }
 
                        /* P is now a jump outside the loop, so it must be put
@@ -4038,7 +4043,7 @@ rtx_equal_for_prefetch_p (rtx x, rtx y)
             contain anything but integers and other rtx's,
             except for within LABEL_REFs and SYMBOL_REFs.  */
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
   return 1;
@@ -4655,12 +4660,18 @@ for_each_insn_in_loop (struct loop *loop, loop_insn_callback fncall)
   int not_every_iteration = 0;
   int maybe_multiple = 0;
   int past_loop_latch = 0;
+  bool exit_test_is_entry = false;
   rtx p;
 
-  /* If loop_scan_start points to the loop exit test, we have to be wary of
-     subversive use of gotos inside expression statements.  */
+  /* If loop_scan_start points to the loop exit test, the loop body
+     cannot be counted on running on every iteration, and we have to
+     be wary of subversive use of gotos inside expression
+     statements.  */
   if (prev_nonnote_insn (loop->scan_start) != prev_nonnote_insn (loop->start))
-    maybe_multiple = back_branch_in_range_p (loop, loop->scan_start);
+    {
+      exit_test_is_entry = true;
+      maybe_multiple = back_branch_in_range_p (loop, loop->scan_start);
+    }
 
   /* Scan through loop and update NOT_EVERY_ITERATION and MAYBE_MULTIPLE.  */
   for (p = next_insn_in_loop (loop, loop->scan_start);
@@ -4718,10 +4729,12 @@ for_each_insn_in_loop (struct loop *loop, loop_insn_callback fncall)
          beginning, don't set not_every_iteration for that.
          This can be any kind of jump, since we want to know if insns
          will be executed if the loop is executed.  */
-         && !(JUMP_LABEL (p) == loop->top
-              && ((NEXT_INSN (NEXT_INSN (p)) == loop->end
-                   && any_uncondjump_p (p))
-                  || (NEXT_INSN (p) == loop->end && any_condjump_p (p)))))
+         && (exit_test_is_entry
+             || !(JUMP_LABEL (p) == loop->top
+                  && ((NEXT_INSN (NEXT_INSN (p)) == loop->end
+                       && any_uncondjump_p (p))
+                      || (NEXT_INSN (p) == loop->end
+                          && any_condjump_p (p))))))
        {
          rtx label = 0;
 
@@ -4964,10 +4977,9 @@ fold_rtx_mult_add (rtx mult1, rtx mult2, rtx add1, enum machine_mode mode)
 
   /* The modes must all be the same.  This should always be true.  For now,
      check to make sure.  */
-  if ((GET_MODE (mult1) != mode && GET_MODE (mult1) != VOIDmode)
-      || (GET_MODE (mult2) != mode && GET_MODE (mult2) != VOIDmode)
-      || (GET_MODE (add1) != mode && GET_MODE (add1) != VOIDmode))
-    abort ();
+  gcc_assert (GET_MODE (mult1) == mode || GET_MODE (mult1) == VOIDmode);
+  gcc_assert (GET_MODE (mult2) == mode || GET_MODE (mult2) == VOIDmode);
+  gcc_assert (GET_MODE (add1) == mode || GET_MODE (add1) == VOIDmode);
 
   /* Ensure that if at least one of mult1/mult2 are constant, then mult2
      will be a constant.  */
@@ -5065,7 +5077,7 @@ reg_dead_after_loop (const struct loop *loop, rtx reg)
   /* HACK: Must also search the loop fall through exit, create a label_ref
      here which points to the loop->end, and append the loop_number_exit_labels
      list to it.  */
-  label = gen_rtx_LABEL_REF (VOIDmode, loop->end);
+  label = gen_rtx_LABEL_REF (Pmode, loop->end);
   LABEL_NEXTREF (label) = loop->exit_labels;
 
   for (; label; label = LABEL_NEXTREF (label))
@@ -5470,9 +5482,45 @@ loop_givs_rescan (struct loop *loop, struct iv_class *bl, rtx *reg_map)
        mark_reg_pointer (v->new_reg, 0);
 
       if (v->giv_type == DEST_ADDR)
-       /* Store reduced reg as the address in the memref where we found
-          this giv.  */
-       validate_change (v->insn, v->location, v->new_reg, 0);
+       {
+         /* Store reduced reg as the address in the memref where we found
+            this giv.  */
+         if (validate_change_maybe_volatile (v->insn, v->location,
+                                             v->new_reg))
+           /* Yay, it worked!  */;
+         /* Not replaceable; emit an insn to set the original
+            giv reg from the reduced giv.  */
+         else if (REG_P (*v->location))
+           loop_insn_emit_before (loop, 0, v->insn,
+                                  gen_move_insn (*v->location,
+                                                 v->new_reg));
+         else if (GET_CODE (*v->location) == PLUS
+                  && REG_P (XEXP (*v->location, 0))
+                  && CONSTANT_P (XEXP (*v->location, 1)))
+           {
+             rtx tem;
+             start_sequence ();
+             tem = expand_simple_binop (GET_MODE (*v->location), MINUS,
+                                        v->new_reg, XEXP (*v->location, 1),
+                                        NULL_RTX, 0, OPTAB_LIB_WIDEN);
+             emit_move_insn (XEXP (*v->location, 0), tem);
+             tem = get_insns ();
+             end_sequence ();
+             loop_insn_emit_before (loop, 0, v->insn, tem);
+           }
+         else
+           {
+             /* If it wasn't a reg, create a pseudo and use that.  */
+             rtx reg, seq;
+             start_sequence ();
+             reg = force_reg (v->mode, *v->location);
+             seq = get_insns ();
+             end_sequence ();
+             loop_insn_emit_before (loop, 0, v->insn, seq);
+             if (!validate_change_maybe_volatile (v->insn, v->location, reg))
+               gcc_unreachable ();
+           }
+       }
       else if (v->replaceable)
        {
          reg_map[REGNO (v->dest_reg)] = v->new_reg;
@@ -5802,9 +5850,8 @@ loop_iterations (struct loop *loop)
      will propagate a new pseudo into the old iteration register but
      this will be marked by having the REG_USERVAR_P bit set.  */
 
-  if ((unsigned) REGNO (iteration_var) >= ivs->n_regs
-      && ! REG_USERVAR_P (iteration_var))
-    abort ();
+  gcc_assert ((unsigned) REGNO (iteration_var) < ivs->n_regs
+             || REG_USERVAR_P (iteration_var));
 
   /* Determine the initial value of the iteration variable, and the amount
      that it is incremented each loop.  Use the tables constructed by
@@ -5861,8 +5908,7 @@ loop_iterations (struct loop *loop)
 
   if (REG_IV_TYPE (ivs, REGNO (iteration_var)) == BASIC_INDUCT)
     {
-      if (REGNO (iteration_var) >= ivs->n_regs)
-       abort ();
+      gcc_assert (REGNO (iteration_var) < ivs->n_regs);
 
       /* Grab initial value, only useful if it is a constant.  */
       bl = REG_IV_CLASS (ivs, REGNO (iteration_var));
@@ -5883,8 +5929,7 @@ loop_iterations (struct loop *loop)
       struct induction *v = REG_IV_INFO (ivs, REGNO (iteration_var));
       rtx biv_initial_value;
 
-      if (REGNO (v->src_reg) >= ivs->n_regs)
-       abort ();
+      gcc_assert (REGNO (v->src_reg) < ivs->n_regs);
 
       if (!v->always_executed || v->maybe_multiple)
        {
@@ -5991,7 +6036,7 @@ loop_iterations (struct loop *loop)
       compare_dir = 0;
       break;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   /* If the comparison value is an invariant register, then try to find
@@ -6243,18 +6288,17 @@ loop_iterations (struct loop *loop)
      unsigned, because they can be as large as 2^n - 1.  */
 
   inc = INTVAL (increment);
+  gcc_assert (inc);
   if (inc > 0)
     {
       abs_diff = INTVAL (final_value) - INTVAL (initial_value);
       abs_inc = inc;
     }
-  else if (inc < 0)
+  else
     {
       abs_diff = INTVAL (initial_value) - INTVAL (final_value);
       abs_inc = -inc;
     }
-  else
-    abort ();
 
   /* Given that iteration_var is going to iterate over its own mode,
      not HOST_WIDE_INT, disregard higher bits that might have come
@@ -6683,7 +6727,7 @@ valid_initial_value_p (rtx x, rtx insn, int call_seen, rtx loop_start)
      some machines, don't use any hard registers at all.  */
   if (REGNO (x) < FIRST_PSEUDO_REGISTER
       && (SMALL_REGISTER_CLASSES
-         || (call_used_regs[REGNO (x)] && call_seen)))
+         || (call_seen && call_used_regs[REGNO (x)])))
     return 0;
 
   /* Don't use registers that have been clobbered before the start of the
@@ -6964,19 +7008,15 @@ record_giv (const struct loop *loop, struct induction *v, rtx insn,
   /* Add the giv to the class of givs computed from one biv.  */
 
   bl = REG_IV_CLASS (ivs, REGNO (src_reg));
-  if (bl)
-    {
-      v->next_iv = bl->giv;
-      bl->giv = v;
-      /* Don't count DEST_ADDR.  This is supposed to count the number of
-        insns that calculate givs.  */
-      if (type == DEST_REG)
-       bl->giv_count++;
-      bl->total_benefit += benefit;
-    }
-  else
-    /* Fatal error, biv missing for this giv?  */
-    abort ();
+  gcc_assert (bl);
+  v->next_iv = bl->giv;
+  bl->giv = v;
+  
+  /* Don't count DEST_ADDR.  This is supposed to count the number of
+     insns that calculate givs.  */
+  if (type == DEST_REG)
+    bl->giv_count++;
+  bl->total_benefit += benefit;
 
   if (type == DEST_ADDR)
     {
@@ -7191,8 +7231,7 @@ final_giv_value (const struct loop *loop, struct induction *v)
     }
 
   /* Replaceable giv's should never reach here.  */
-  if (v->replaceable)
-    abort ();
+  gcc_assert (!v->replaceable);
 
   /* Check to see if the biv is dead at all loop exits.  */
   if (reg_dead_after_loop (loop, v->dest_reg))
@@ -7621,9 +7660,9 @@ basic_induction_var (const struct loop *loop, rtx x, enum machine_mode mode,
     case CONST_INT:
     case SYMBOL_REF:
     case CONST:
-      /* convert_modes aborts if we try to convert to or from CCmode, so just
+      /* convert_modes dies if we try to convert to or from CCmode, so just
          exclude that case.  It is very unlikely that a condition code value
-        would be a useful iterator anyways.  convert_modes aborts if we try to
+        would be a useful iterator anyways.  convert_modes dies if we try to
         convert a float mode to non-float or vice versa too.  */
       if (loop->level == 1
          && GET_MODE_CLASS (mode) == GET_MODE_CLASS (GET_MODE (dest_reg))
@@ -7756,7 +7795,7 @@ general_induction_var (const struct loop *loop, rtx x, rtx *src_reg,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   /* Remove any enclosing USE from ADD_VAL and MULT_VAL (there will be
@@ -7875,7 +7914,7 @@ simplify_giv_expr (const struct loop *loop, rtx x, rtx *ext_val, int *benefit)
                                 ext_val, benefit);
 
          default:
-           abort ();
+           gcc_unreachable ();
          }
 
       /* Each argument must be either REG, PLUS, or MULT.  Convert REG to
@@ -8016,7 +8055,7 @@ simplify_giv_expr (const struct loop *loop, rtx x, rtx *ext_val, int *benefit)
                                    ext_val, benefit);
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
 
     case ASHIFT:
@@ -8775,7 +8814,7 @@ extension_within_bounds_p (const struct loop *loop, struct iv_class *bl,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   return ((!signedp || biv_fits_mode_p (loop, bl, incr, mode, false))
@@ -8904,7 +8943,7 @@ combine_givs (struct loop_regs *regs, struct iv_class *bl)
       /* If a DEST_REG GIV is used only once, do not allow it to combine
         with anything, for in doing so we will gain nothing that cannot
         be had by simply letting the GIV with which we would have combined
-        to be reduced on its own.  The losage shows up in particular with
+        to be reduced on its own.  The lossage shows up in particular with
         DEST_ADDR targets on hosts with reg+reg addressing, though it can
         be seen elsewhere as well.  */
       if (g1->giv_type == DEST_REG
@@ -11112,8 +11151,7 @@ try_copy_prop (const struct loop *loop, rtx replacement, unsigned int regno)
          && REG_P (SET_DEST (set))
          && REGNO (SET_DEST (set)) == regno)
        {
-         if (init_insn)
-           abort ();
+         gcc_assert (!init_insn);
 
          init_insn = insn;
          if (REGNO_FIRST_UID (regno) == INSN_UID (insn))
@@ -11146,8 +11184,7 @@ try_copy_prop (const struct loop *loop, rtx replacement, unsigned int regno)
            }
        }
     }
-  if (! init_insn)
-    abort ();
+  gcc_assert (init_insn);
   if (apply_change_group ())
     {
       if (loop_dump_stream)
@@ -11648,7 +11685,7 @@ loop_giv_dump (const struct induction *v, FILE *file, int verbose)
          fprintf (file, " ext tr");
          break;
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
 
@@ -11777,3 +11814,66 @@ debug_loops (const struct loops *loops)
 {
   flow_loops_dump (loops, stderr, loop_dump_aux, 1);
 }
+\f
+static bool
+gate_handle_loop_optimize (void)
+{
+  return (optimize > 0 && flag_loop_optimize);
+}
+
+/* Move constant computations out of loops.  */
+static void
+rest_of_handle_loop_optimize (void)
+{
+  int do_prefetch;
+
+  /* CFG is no longer maintained up-to-date.  */
+  free_bb_for_insn ();
+  profile_status = PROFILE_ABSENT;
+  
+  do_prefetch = flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0;
+  
+  if (flag_rerun_loop_opt)
+    {
+      cleanup_barriers ();
+      
+      /* We only want to perform unrolling once.  */
+      loop_optimize (get_insns (), dump_file, 0);
+      
+      /* The first call to loop_optimize makes some instructions
+         trivially dead.  We delete those instructions now in the
+         hope that doing so will make the heuristics in loop work
+         better and possibly speed up compilation.  */
+      delete_trivially_dead_insns (get_insns (), max_reg_num ());
+  
+      /* The regscan pass is currently necessary as the alias
+         analysis code depends on this information.  */
+      reg_scan (get_insns (), max_reg_num ());
+    } 
+  cleanup_barriers ();
+  loop_optimize (get_insns (), dump_file, do_prefetch);
+      
+  /* Loop can create trivially dead instructions.  */
+  delete_trivially_dead_insns (get_insns (), max_reg_num ());
+  find_basic_blocks (get_insns ());
+}
+
+struct tree_opt_pass pass_loop_optimize =
+{
+  "old-loop",                           /* name */
+  gate_handle_loop_optimize,            /* gate */   
+  rest_of_handle_loop_optimize,         /* execute */       
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  TV_LOOP,                              /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  0,                                    /* todo_flags_start */
+  TODO_dump_func |
+  TODO_ggc_collect,                     /* todo_flags_finish */
+  'L'                                   /* letter */
+};
+
+