OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / gcse.c
index af10db6..477d4d3 100644 (file)
@@ -1,7 +1,7 @@
 /* Global common subexpression elimination/Partial redundancy elimination
    and global constant/copy propagation for GNU compiler.
    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-   2006, 2007 Free Software Foundation, Inc.
+   2006, 2007, 2008 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -380,12 +380,6 @@ static int max_uid;
 /* Number of cuids.  */
 static int max_cuid;
 
-/* Mapping of cuids to insns.  */
-static rtx *cuid_insn;
-
-/* Get insn from cuid.  */
-#define CUID_INSN(CUID) (cuid_insn[CUID])
-
 /* Maximum register number in function prior to doing gcse + 1.
    Registers created during this pass have regno >= max_gcse_regno.
    This is named with "gcse" to not collide with global of same name.  */
@@ -664,7 +658,7 @@ gcse_main (rtx f ATTRIBUTE_UNUSED)
 
   /* We do not construct an accurate cfg in functions which call
      setjmp, so just punt to be safe.  */
-  if (current_function_calls_setjmp)
+  if (cfun->calls_setjmp)
     return 0;
 
   /* Assume that we do not need to run jump optimizations after gcse.  */
@@ -724,9 +718,12 @@ gcse_main (rtx f ATTRIBUTE_UNUSED)
 
       /* Don't allow constant propagation to modify jumps
         during this pass.  */
-      timevar_push (TV_CPROP1);
-      changed = one_cprop_pass (pass + 1, false, false);
-      timevar_pop (TV_CPROP1);
+      if (dbg_cnt (cprop1))
+       {
+         timevar_push (TV_CPROP1);
+         changed = one_cprop_pass (pass + 1, false, false);
+         timevar_pop (TV_CPROP1);
+       }
 
       if (optimize_size)
        /* Do nothing.  */ ;
@@ -789,13 +786,17 @@ gcse_main (rtx f ATTRIBUTE_UNUSED)
   /* Do one last pass of copy propagation, including cprop into
      conditional jumps.  */
 
-  max_gcse_regno = max_reg_num ();
-  alloc_gcse_mem ();
-  /* This time, go ahead and allow cprop to alter jumps.  */
-  timevar_push (TV_CPROP2);
-  one_cprop_pass (pass + 1, true, true);
-  timevar_pop (TV_CPROP2);
-  free_gcse_mem ();
+  if (dbg_cnt (cprop2))
+    {
+      max_gcse_regno = max_reg_num ();
+      alloc_gcse_mem ();
+
+      /* This time, go ahead and allow cprop to alter jumps.  */
+      timevar_push (TV_CPROP2);
+      one_cprop_pass (pass + 1, true, true);
+      timevar_pop (TV_CPROP2);
+      free_gcse_mem ();
+    }
 
   if (dump_file)
     {
@@ -942,15 +943,7 @@ alloc_gcse_mem (void)
          uid_cuid[INSN_UID (insn)] = i;
       }
 
-  /* Create a table mapping cuids to insns.  */
-
   max_cuid = i;
-  cuid_insn = gcalloc (max_cuid + 1, sizeof (rtx));
-  i = 0;
-  FOR_EACH_BB (bb)
-    FOR_BB_INSNS (bb, insn)
-      if (INSN_P (insn))
-       CUID_INSN (i++) = insn;
 
   /* Allocate vars to track sets of regs.  */
   reg_set_bitmap = BITMAP_ALLOC (NULL);
@@ -971,7 +964,6 @@ static void
 free_gcse_mem (void)
 {
   free (uid_cuid);
-  free (cuid_insn);
 
   BITMAP_FREE (reg_set_bitmap);
 
@@ -1760,8 +1752,9 @@ hash_scan_set (rtx pat, rtx insn, struct hash_table *table)
                  modified.  Here we want to search from INSN+1 on, but
                  oprs_available_p searches from INSN on.  */
               && (insn == BB_END (BLOCK_FOR_INSN (insn))
-                  || ((tmp = next_nonnote_insn (insn)) != NULL_RTX
-                      && oprs_available_p (pat, tmp))))
+                  || (tmp = next_nonnote_insn (insn)) == NULL_RTX
+                  || BLOCK_FOR_INSN (tmp) != BLOCK_FOR_INSN (insn)
+                  || oprs_available_p (pat, tmp)))
        insert_set_in_table (pat, insn, table);
     }
   /* In case of store we want to consider the memory value as available in
@@ -2679,7 +2672,8 @@ try_replace_reg (rtx from, rtx to, rtx insn)
      with our replacement.  */
   if (note != 0 && REG_NOTE_KIND (note) == REG_EQUAL)
     set_unique_reg_note (insn, REG_EQUAL,
-                        simplify_replace_rtx (XEXP (note, 0), from, to));
+                        simplify_replace_rtx (XEXP (note, 0), from,
+                        copy_rtx (to)));
   if (!success && set && reg_mentioned_p (from, SET_SRC (set)))
     {
       /* If above failed and this is a single set, try to simplify the source of
@@ -2834,7 +2828,7 @@ cprop_jump (basic_block bb, rtx setcc, rtx jump, rtx from, rtx src)
          to one computed by setcc.  */
       if (setcc && modified_in_p (new, setcc))
        return 0;
-      if (! validate_change (jump, &SET_SRC (set), new, 0))
+      if (! validate_unshare_change (jump, &SET_SRC (set), new, 0))
        {
          /* When (some) constants are not valid in a comparison, and there
             are two registers to be replaced by constants before the entire
@@ -2874,6 +2868,24 @@ cprop_jump (basic_block bb, rtx setcc, rtx jump, rtx from, rtx src)
     }
   purge_dead_edges (bb);
 
+  /* If a conditional jump has been changed into unconditional jump, remove
+     the jump and make the edge fallthru - this is always called in
+     cfglayout mode.  */
+  if (new != pc_rtx && simplejump_p (jump))
+    {
+      edge e;
+      edge_iterator ei;
+
+      for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); ei_next (&ei))
+       if (e->dest != EXIT_BLOCK_PTR
+           && BB_HEAD (e->dest) == JUMP_LABEL (jump))
+         {
+           e->flags |= EDGE_FALLTHRU;
+           break;
+         }
+      delete_insn (jump);
+    }
+
   return 1;
 }
 
@@ -4451,8 +4463,7 @@ pre_delete (void)
                   expressions into.  Get the mode for the new pseudo from
                   the mode of the original destination pseudo.  */
                if (expr->reaching_reg == NULL)
-                 expr->reaching_reg
-                   = gen_reg_rtx (GET_MODE (SET_DEST (set)));
+                 expr->reaching_reg = gen_reg_rtx_and_attrs (SET_DEST (set));
 
                gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), insn);
                delete_insn (insn);
@@ -4584,14 +4595,15 @@ one_pre_gcse_pass (int pass)
   return changed;
 }
 \f
-/* If X contains any LABEL_REF's, add REG_LABEL notes for them to INSN.
-   If notes are added to an insn which references a CODE_LABEL, the
-   LABEL_NUSES count is incremented.  We have to add REG_LABEL notes,
-   because the following loop optimization pass requires them.  */
+/* If X contains any LABEL_REF's, add REG_LABEL_OPERAND notes for them
+   to INSN.  If such notes are added to an insn which references a
+   CODE_LABEL, the LABEL_NUSES count is incremented.  We have to add
+   that note, because the following loop optimization pass requires
+   them.  */
 
 /* ??? If there was a jump optimization pass after gcse and before loop,
    then we would not need to do this here, because jump would add the
-   necessary REG_LABEL notes.  */
+   necessary REG_LABEL_OPERAND and REG_LABEL_TARGET notes.  */
 
 static void
 add_label_notes (rtx x, rtx insn)
@@ -4608,10 +4620,16 @@ add_label_notes (rtx x, rtx insn)
         We no longer ignore such label references (see LABEL_REF handling in
         mark_jump_label for additional information).  */
 
-      REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, XEXP (x, 0),
-                                           REG_NOTES (insn));
+      /* There's no reason for current users to emit jump-insns with
+        such a LABEL_REF, so we don't have to handle REG_LABEL_TARGET
+        notes.  */
+      gcc_assert (!JUMP_P (insn));
+      REG_NOTES (insn)
+       = gen_rtx_INSN_LIST (REG_LABEL_OPERAND, XEXP (x, 0),
+                            REG_NOTES (insn));
       if (LABEL_P (XEXP (x, 0)))
        LABEL_NUSES (XEXP (x, 0))++;
+
       return;
     }
 
@@ -4744,10 +4762,14 @@ compute_code_hoist_vbeinout (void)
         the convergence.  */
       FOR_EACH_BB_REVERSE (bb)
        {
-         changed |= sbitmap_a_or_b_and_c_cg (hoist_vbein[bb->index], antloc[bb->index],
-                                             hoist_vbeout[bb->index], transp[bb->index]);
          if (bb->next_bb != EXIT_BLOCK_PTR)
-           sbitmap_intersection_of_succs (hoist_vbeout[bb->index], hoist_vbein, bb->index);
+           sbitmap_intersection_of_succs (hoist_vbeout[bb->index],
+                                          hoist_vbein, bb->index);
+
+         changed |= sbitmap_a_or_b_and_c_cg (hoist_vbein[bb->index],
+                                             antloc[bb->index],
+                                             hoist_vbeout[bb->index],
+                                             transp[bb->index]);
        }
 
       passes++;
@@ -4965,7 +4987,7 @@ hoist_code (void)
                         from the mode of the original destination pseudo.  */
                      if (expr->reaching_reg == NULL)
                        expr->reaching_reg
-                         = gen_reg_rtx (GET_MODE (SET_DEST (set)));
+                         = gen_reg_rtx_and_attrs (SET_DEST (set));
 
                      gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), insn);
                      delete_insn (insn);
@@ -6098,7 +6120,7 @@ build_store_vectors (void)
             are any side effects.  */
          if (TEST_BIT (ae_gen[bb->index], ptr->index))
            {
-             rtx r = gen_reg_rtx (GET_MODE (ptr->pattern));
+             rtx r = gen_reg_rtx_and_attrs (ptr->pattern);
              if (dump_file)
                fprintf (dump_file, "Removing redundant store:\n");
              replace_store_insn (r, XEXP (st, 0), bb, ptr);
@@ -6421,7 +6443,7 @@ delete_store (struct ls_expr * expr, basic_block bb)
   rtx reg, i, del;
 
   if (expr->reaching_reg == NULL_RTX)
-    expr->reaching_reg = gen_reg_rtx (GET_MODE (expr->pattern));
+    expr->reaching_reg = gen_reg_rtx_and_attrs (expr->pattern);
 
   reg = expr->reaching_reg;
 
@@ -6553,7 +6575,7 @@ bypass_jumps (void)
 
   /* We do not construct an accurate cfg in functions which call
      setjmp, so just punt to be safe.  */
-  if (current_function_calls_setjmp)
+  if (cfun->calls_setjmp)
     return 0;
 
   /* Identify the basic block information for this function, including
@@ -6650,7 +6672,8 @@ is_too_expensive (const char *pass)
 static bool
 gate_handle_jump_bypass (void)
 {
-  return optimize > 0 && flag_gcse;
+  return optimize > 0 && flag_gcse
+    && dbg_cnt (jump_bypass);
 }
 
 /* Perform jump bypassing and control flow optimizations.  */
@@ -6667,8 +6690,10 @@ rest_of_handle_jump_bypass (void)
   return 0;
 }
 
-struct tree_opt_pass pass_jump_bypass =
+struct rtl_opt_pass pass_jump_bypass =
 {
+ {
+  RTL_PASS,
   "bypass",                             /* name */
   gate_handle_jump_bypass,              /* gate */   
   rest_of_handle_jump_bypass,           /* execute */       
@@ -6681,15 +6706,16 @@ struct tree_opt_pass pass_jump_bypass =
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
   TODO_dump_func |
-  TODO_ggc_collect | TODO_verify_flow,  /* todo_flags_finish */
-  'G'                                   /* letter */
+  TODO_ggc_collect | TODO_verify_flow   /* todo_flags_finish */
+ }
 };
 
 
 static bool
 gate_handle_gcse (void)
 {
-  return optimize > 0 && flag_gcse;
+  return optimize > 0 && flag_gcse
+    && dbg_cnt (gcse);
 }
 
 
@@ -6720,21 +6746,25 @@ rest_of_handle_gcse (void)
 
   /* If gcse or cse altered any jumps, rerun jump optimizations to clean
      things up.  */
-  if (tem || tem2)
+  if (tem || tem2 == 2)
     {
       timevar_push (TV_JUMP);
       rebuild_jump_labels (get_insns ());
       cleanup_cfg (0);
       timevar_pop (TV_JUMP);
     }
+  else if (tem2 == 1)
+    cleanup_cfg (0);
 
   flag_cse_skip_blocks = save_csb;
   flag_cse_follow_jumps = save_cfj;
   return 0;
 }
 
-struct tree_opt_pass pass_gcse =
+struct rtl_opt_pass pass_gcse =
 {
+ {
+  RTL_PASS,
   "gcse1",                              /* name */
   gate_handle_gcse,                     /* gate */   
   rest_of_handle_gcse,                 /* execute */       
@@ -6746,10 +6776,10 @@ struct tree_opt_pass pass_gcse =
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  TODO_df_finish |
+  TODO_df_finish | TODO_verify_rtl_sharing |
   TODO_dump_func |
-  TODO_verify_flow | TODO_ggc_collect,  /* todo_flags_finish */
-  'G'                                   /* letter */
+  TODO_verify_flow | TODO_ggc_collect   /* todo_flags_finish */
+ }
 };