OSDN Git Service

* gcc.dg/torture/pr26565.c: Expect warning on packed field for
[pf3gnuchains/gcc-fork.git] / gcc / flow.c
index 94595da..78c2328 100644 (file)
@@ -1,6 +1,7 @@
 /* Data flow analysis for GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+   Inc.
 
 This file is part of GCC.
 
@@ -181,7 +182,7 @@ int max_regno;
 
 /* Indexed by n, giving various register information */
 
-varray_type reg_n_info;
+VEC(reg_info_p,heap) *reg_n_info;
 
 /* Regset of regs live when calls to `setjmp'-like functions happen.  */
 /* ??? Does this exist only for the setjmp-clobbered warning message?  */
@@ -353,7 +354,7 @@ first_insn_after_basic_block_note (basic_block block)
    FLAGS is a set of PROP_* flags to be used in accumulating flow info.  */
 
 void
-life_analysis (FILE *file, int flags)
+life_analysis (int flags)
 {
 #ifdef ELIMINABLE_REGS
   int i;
@@ -436,8 +437,8 @@ life_analysis (FILE *file, int flags)
   if (optimize && (flags & PROP_SCAN_DEAD_STORES))
     end_alias_analysis ();
 
-  if (file)
-    dump_flow_info (file);
+  if (dump_file)
+    dump_flow_info (dump_file, dump_flags);
 
   /* Removing dead insns should have made jumptables really dead.  */
   delete_dead_jumptables ();
@@ -489,7 +490,7 @@ verify_wide_reg (int regno, basic_block bb)
       fprintf (dump_file, "Register %d died unexpectedly.\n", regno);
       dump_bb (bb, dump_file, 0);
     }
-  fatal_error ("internal consistency failure");
+  internal_error ("internal consistency failure");
 }
 
 /* A subroutine of update_life_info.  Verify that there are no untoward
@@ -514,7 +515,7 @@ verify_local_live_at_start (regset new_live_at_start, basic_block bb)
              fputs ("Old:\n", dump_file);
              dump_bb (bb, dump_file, 0);
            }
-         fatal_error ("internal consistency failure");
+         internal_error ("internal consistency failure");
        }
     }
   else
@@ -536,7 +537,7 @@ verify_local_live_at_start (regset new_live_at_start, basic_block bb)
                           "Register %d died unexpectedly.\n", i);
                  dump_bb (bb, dump_file, 0);
                }
-             fatal_error ("internal consistency failure");
+             internal_error ("internal consistency failure");
            }
          /* Verify that the now-live register is wider than word_mode.  */
          verify_wide_reg (i, bb);
@@ -577,7 +578,7 @@ update_life_info (sbitmap blocks, enum update_life_extent extent,
   ndead = 0;
 
   if ((prop_flags & PROP_REG_INFO) && !reg_deaths)
-    reg_deaths = xcalloc (sizeof (*reg_deaths), max_regno);
+    reg_deaths = XCNEWVEC (int, max_regno);
 
   timevar_push ((extent == UPDATE_LIFE_LOCAL || blocks)
                ? TV_LIFE_UPDATE : TV_LIFE);
@@ -646,6 +647,17 @@ update_life_info (sbitmap blocks, enum update_life_extent extent,
        count_or_remove_death_notes (blocks,
                                     prop_flags & PROP_POST_REGSTACK ? -1 : 1);
     }
+  else
+    {
+      /* FIXME: This can go when the dataflow branch has been merged in.  */
+      /* For a local update, if we are creating new REG_DEAD notes, then we
+        must delete the old ones first to avoid conflicts if they are
+        different.  */
+      if (prop_flags & PROP_DEATH_NOTES)
+       count_or_remove_death_notes (blocks,
+                                    prop_flags & PROP_POST_REGSTACK ? -1 : 1);
+    }
+                                    
 
   /* Clear log links in case we are asked to (re)compute them.  */
   if (prop_flags & PROP_LOG_LINKS)
@@ -814,8 +826,10 @@ delete_noop_moves (void)
            }
        }
     }
+
   if (nnoops && dump_file)
-    fprintf (dump_file, "deleted %i noop moves", nnoops);
+    fprintf (dump_file, "deleted %i noop moves\n", nnoops);
+
   return nnoops;
 }
 
@@ -1026,7 +1040,7 @@ static void
 calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
 {
   basic_block *queue, *qhead, *qtail, *qend, bb;
-  regset tmp, new_live_at_end, invalidated_by_call;
+  regset tmp, new_live_at_end, invalidated_by_eh_edge;
   regset registers_made_dead;
   bool failure_strategy_required = false;
   int *block_accesses;
@@ -1049,21 +1063,32 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
 
   tmp = ALLOC_REG_SET (&reg_obstack);
   new_live_at_end = ALLOC_REG_SET (&reg_obstack);
-  invalidated_by_call = ALLOC_REG_SET (&reg_obstack);
+  invalidated_by_eh_edge = ALLOC_REG_SET (&reg_obstack);
   registers_made_dead = ALLOC_REG_SET (&reg_obstack);
 
   /* Inconveniently, this is only readily available in hard reg set form.  */
   for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
     if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
-      SET_REGNO_REG_SET (invalidated_by_call, i);
+      SET_REGNO_REG_SET (invalidated_by_eh_edge, i);
+
+  /* The exception handling registers die at eh edges.  */
+#ifdef EH_RETURN_DATA_REGNO
+  for (i = 0; ; ++i)
+    {
+      unsigned regno = EH_RETURN_DATA_REGNO (i);
+      if (regno == INVALID_REGNUM)
+       break;
+      SET_REGNO_REG_SET (invalidated_by_eh_edge, regno);
+    }
+#endif
 
   /* Allocate space for the sets of local properties.  */
-  local_sets = xcalloc (last_basic_block, sizeof (regset));
-  cond_local_sets = xcalloc (last_basic_block, sizeof (regset));
+  local_sets = XCNEWVEC (bitmap, last_basic_block);
+  cond_local_sets = XCNEWVEC (bitmap, last_basic_block);
 
   /* Create a worklist.  Allocate an extra slot for the `head == tail'
      style test for an empty queue doesn't work with a full queue.  */
-  queue = xmalloc ((n_basic_blocks + 1) * sizeof (*queue));
+  queue = XNEWVEC (basic_block, n_basic_blocks + 1);
   qtail = queue;
   qhead = qend = queue + n_basic_blocks;
 
@@ -1088,7 +1113,7 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
        }
     }
 
-  block_accesses = xcalloc (last_basic_block, sizeof (int));
+  block_accesses = XCNEWVEC (int, last_basic_block);
   
   /* We clean aux when we remove the initially-enqueued bbs, but we
      don't enqueue ENTRY and EXIT initially, so clean them upfront and
@@ -1188,7 +1213,7 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
            if (e->flags & EDGE_EH)
              bitmap_ior_and_compl_into (new_live_at_end,
                                         sb->il.rtl->global_live_at_start,
-                                        invalidated_by_call);
+                                        invalidated_by_eh_edge);
            else
              IOR_REG_SET (new_live_at_end, sb->il.rtl->global_live_at_start);
 
@@ -1393,6 +1418,9 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
       FOR_EACH_EDGE (e, ei, bb->preds)
        {
          basic_block pb = e->src;
+
+         gcc_assert ((e->flags & EDGE_FAKE) == 0);
+
          if (pb->aux == NULL)
            {
              *qtail++ = pb;
@@ -1405,7 +1433,7 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
 
   FREE_REG_SET (tmp);
   FREE_REG_SET (new_live_at_end);
-  FREE_REG_SET (invalidated_by_call);
+  FREE_REG_SET (invalidated_by_eh_edge);
   FREE_REG_SET (registers_made_dead);
 
   if (blocks_out)
@@ -1558,8 +1586,16 @@ allocate_bb_life_data (void)
 
   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
     {
-      bb->il.rtl->global_live_at_start = ALLOC_REG_SET (&reg_obstack);
-      bb->il.rtl->global_live_at_end = ALLOC_REG_SET (&reg_obstack);
+      if (bb->il.rtl->global_live_at_start)
+       {
+         CLEAR_REG_SET (bb->il.rtl->global_live_at_start);
+         CLEAR_REG_SET (bb->il.rtl->global_live_at_end);
+       }
+      else
+       {
+         bb->il.rtl->global_live_at_start = ALLOC_REG_SET (&reg_obstack);
+         bb->il.rtl->global_live_at_end = ALLOC_REG_SET (&reg_obstack);
+       }
     }
 
   regs_live_at_setjmp = ALLOC_REG_SET (&reg_obstack);
@@ -1572,7 +1608,7 @@ allocate_reg_life_data (void)
 
   max_regno = max_reg_num ();
   gcc_assert (!reg_deaths);
-  reg_deaths = xcalloc (sizeof (*reg_deaths), max_regno);
+  reg_deaths = XCNEWVEC (int, max_regno);
 
   /* Recalculate the register space, in case it has grown.  Old style
      vector oriented regsets would set regset_{size,bytes} here also.  */
@@ -1938,7 +1974,7 @@ struct propagate_block_info *
 init_propagate_block_info (basic_block bb, regset live, regset local_set,
                           regset cond_local_set, int flags)
 {
-  struct propagate_block_info *pbi = xmalloc (sizeof (*pbi));
+  struct propagate_block_info *pbi = XNEW (struct propagate_block_info);
 
   pbi->bb = bb;
   pbi->reg_live = live;
@@ -1951,7 +1987,7 @@ init_propagate_block_info (basic_block bb, regset live, regset local_set,
   pbi->insn_num = 0;
 
   if (flags & (PROP_LOG_LINKS | PROP_AUTOINC))
-    pbi->reg_next_use = xcalloc (max_reg_num (), sizeof (rtx));
+    pbi->reg_next_use = XCNEWVEC (rtx, max_reg_num ());
   else
     pbi->reg_next_use = NULL;
 
@@ -2041,7 +2077,7 @@ init_propagate_block_info (basic_block bb, regset live, regset local_set,
                  struct reg_cond_life_info *rcli;
                  rtx cond;
 
-                 rcli = xmalloc (sizeof (*rcli));
+                 rcli = XNEW (struct reg_cond_life_info);
 
                  if (REGNO_REG_SET_P (bb_true->il.rtl->global_live_at_start,
                                       i))
@@ -2189,6 +2225,28 @@ propagate_block (basic_block bb, regset live, regset local_set,
        break;
     }
 
+#ifdef EH_RETURN_DATA_REGNO
+  if (bb_has_eh_pred (bb))
+    {
+      unsigned int i;
+      for (i = 0; ; ++i)
+       {
+         unsigned regno = EH_RETURN_DATA_REGNO (i);
+         if (regno == INVALID_REGNUM)
+           break;
+         if (pbi->local_set)
+           {
+             CLEAR_REGNO_REG_SET (pbi->cond_local_set, regno);
+             SET_REGNO_REG_SET (pbi->local_set, regno);
+           }
+         if (REGNO_REG_SET_P (pbi->reg_live, regno))
+           SET_REGNO_REG_SET (pbi->new_set, regno);
+         
+         regs_ever_live[regno] = 1;
+       }
+    }
+#endif
+
   free_propagate_block_info (pbi);
 
   return changed;
@@ -2733,8 +2791,7 @@ mark_set_1 (struct propagate_block_info *pbi, enum rtx_code code, rtx reg, rtx c
              regno_first += subreg_regno_offset (regno_first, inner_mode,
                                                  SUBREG_BYTE (reg),
                                                  outer_mode);
-             regno_last = (regno_first
-                           + hard_regno_nregs[regno_first][outer_mode] - 1);
+             regno_last = regno_first + subreg_nregs (reg) - 1;
 
              /* Since we've just adjusted the register number ranges, make
                 sure REG matches.  Otherwise some_was_live will be clear
@@ -3056,7 +3113,7 @@ mark_regno_cond_dead (struct propagate_block_info *pbi, int regno, rtx cond)
          /* The register was unconditionally live previously.
             Record the current condition as the condition under
             which it is dead.  */
-         rcli = xmalloc (sizeof (*rcli));
+         rcli = XNEW (struct reg_cond_life_info);
          rcli->condition = cond;
          rcli->stores = cond;
          rcli->orig_condition = const0_rtx;
@@ -3856,7 +3913,7 @@ mark_used_reg (struct propagate_block_info *pbi, rtx reg,
            {
              /* The register was not previously live at all.  Record
                 the condition under which it is still dead.  */
-             rcli = xmalloc (sizeof (*rcli));
+             rcli = XNEW (struct reg_cond_life_info);
              rcli->condition = not_reg_cond (cond);
              rcli->stores = const0_rtx;
              rcli->orig_condition = const0_rtx;
@@ -4403,7 +4460,7 @@ debug_regset (regset r)
    It might be worthwhile to update REG_LIVE_LENGTH, REG_BASIC_BLOCK and
    possibly other information which is used by the register allocators.  */
 
-void
+static unsigned int
 recompute_reg_usage (void)
 {
   allocate_reg_life_data ();
@@ -4414,7 +4471,8 @@ recompute_reg_usage (void)
   update_life_info (NULL, UPDATE_LIFE_LOCAL, PROP_REG_INFO | PROP_DEATH_NOTES);
 
   if (dump_file)
-    dump_flow_info (dump_file);
+    dump_flow_info (dump_file, dump_flags);
+  return 0;
 }
 
 struct tree_opt_pass pass_recompute_reg_usage =
@@ -4602,10 +4660,11 @@ gate_remove_death_notes (void)
   return flag_profile_values;
 }
 
-static void
+static unsigned int
 rest_of_handle_remove_death_notes (void)
 {
   count_or_remove_death_notes (NULL, 1);
+  return 0;
 }
 
 struct tree_opt_pass pass_remove_death_notes =
@@ -4626,17 +4685,17 @@ struct tree_opt_pass pass_remove_death_notes =
 };
 
 /* Perform life analysis.  */
-static void
+static unsigned int
 rest_of_handle_life (void)
 {
   regclass_init ();
 
-  life_analysis (dump_file, PROP_FINAL);
+  life_analysis (PROP_FINAL);
   if (optimize)
     cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE | CLEANUP_LOG_LINKS
                  | (flag_thread_jumps ? CLEANUP_THREADING : 0));
 
-  if (extra_warnings)
+  if (warn_clobbered)
     {
       setjmp_vars_warning (DECL_INITIAL (current_function_decl));
       setjmp_args_warning ();
@@ -4655,6 +4714,7 @@ rest_of_handle_life (void)
     }
 
   no_new_pseudos = 1;
+  return 0;
 }
 
 struct tree_opt_pass pass_life =
@@ -4675,7 +4735,7 @@ struct tree_opt_pass pass_life =
   'f'                                   /* letter */
 };
 
-static void
+static unsigned int
 rest_of_handle_flow2 (void)
 {
   /* If optimizing, then go ahead and split insns now.  */
@@ -4697,6 +4757,7 @@ rest_of_handle_flow2 (void)
   thread_prologue_and_epilogue_insns (get_insns ());
   epilogue_completed = 1;
   flow2_completed = 1;
+  return 0;
 }
 
 struct tree_opt_pass pass_flow2 =