OSDN Git Service

* cse.c (cse_reg_info_free_list, cse_reg_info_used_list,
[pf3gnuchains/gcc-fork.git] / gcc / passes.c
index 1386ff1..3d4c679 100644 (file)
@@ -1,6 +1,6 @@
 /* Top level of GCC compilers (cc1, cc1plus, etc.)
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -60,7 +60,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "intl.h"
 #include "ggc.h"
 #include "graph.h"
-#include "loop.h"
 #include "regs.h"
 #include "timevar.h"
 #include "diagnostic.h"
@@ -121,8 +120,8 @@ open_dump_file (enum tree_dump_index index, tree decl)
 
   timevar_push (TV_DUMP);
 
-  gcc_assert (!dump_file);
-  gcc_assert (!dump_file_name);
+  if (dump_file != NULL || dump_file_name != NULL)
+    abort ();
 
   dump_file_name = get_dump_file_name (index);
   initializing_dump = !dump_initialized_p (index);
@@ -230,14 +229,7 @@ rest_of_decl_compilation (tree decl,
          && !DECL_EXTERNAL (decl))
        {
          if (flag_unit_at_a_time && !cgraph_global_info_ready
-             && TREE_CODE (decl) != FUNCTION_DECL && top_level
-             /* If we defer processing of decls that have had their
-                DECL_RTL set above (say, in make_decl_rtl),
-                check_global_declarations() will clear it before
-                assemble_variable has a chance to act on it.  This
-                would remove all traces of the register name in a
-                global register variable, for example.  */
-             && !DECL_RTL_SET_P (decl))
+             && TREE_CODE (decl) != FUNCTION_DECL && top_level)
            cgraph_varpool_finalize_decl (decl);
          else
            assemble_variable (decl, top_level, at_end, 0);
@@ -289,9 +281,11 @@ rest_of_handle_final (void)
        different from the DECL_NAME name used in the source file.  */
 
     x = DECL_RTL (current_function_decl);
-    gcc_assert (MEM_P (x));
+    if (!MEM_P (x))
+      abort ();
     x = XEXP (x, 0);
-    gcc_assert (GET_CODE (x) == SYMBOL_REF);
+    if (GET_CODE (x) != SYMBOL_REF)
+      abort ();
     fnname = XSTR (x, 0);
 
     assemble_start_function (current_function_decl, fnname);
@@ -319,9 +313,6 @@ rest_of_handle_final (void)
 
     /* Release all memory allocated by flow.  */
     free_basic_block_vars ();
-
-    /* Release all memory held by regsets now.  */
-    regset_release_memory ();
   }
 
   /* Write DBX symbols if requested.  */
@@ -405,7 +396,7 @@ rest_of_handle_stack_regs (void)
 }
 #endif
 
-/* Track the variables, ie. compute where the variable is stored at each position in function.  */
+/* Track the variables, i.e. compute where the variable is stored at each position in function.  */
 static void
 rest_of_handle_variable_tracking (void)
 {
@@ -434,49 +425,6 @@ rest_of_handle_machine_reorg (void)
 }
 
 
-/* Run new register allocator.  Return TRUE if we must exit
-   rest_of_compilation upon return.  */
-static bool
-rest_of_handle_new_regalloc (void)
-{
-  int failure;
-
-  timevar_push (TV_LOCAL_ALLOC);
-  open_dump_file (DFI_lreg, current_function_decl);
-
-  delete_trivially_dead_insns (get_insns (), max_reg_num ());
-  reg_alloc ();
-
-  timevar_pop (TV_LOCAL_ALLOC);
-  close_dump_file (DFI_lreg, NULL, NULL);
-
-  /* XXX clean up the whole mess to bring live info in shape again.  */
-  timevar_push (TV_GLOBAL_ALLOC);
-  open_dump_file (DFI_greg, current_function_decl);
-
-  build_insn_chain (get_insns ());
-  failure = reload (get_insns (), 0);
-
-  timevar_pop (TV_GLOBAL_ALLOC);
-
-  ggc_collect ();
-
-  if (dump_enabled_p (DFI_greg))
-    {
-      timevar_push (TV_DUMP);
-      dump_global_regs (dump_file);
-      timevar_pop (TV_DUMP);
-      close_dump_file (DFI_greg, print_rtl_with_bb, get_insns ());
-    }
-
-  if (failure)
-    return true;
-
-  reload_completed = 1;
-
-  return false;
-}
-
 /* Run old register allocator.  Return TRUE if we must exit
    rest_of_compilation upon return.  */
 static bool
@@ -511,6 +459,7 @@ rest_of_handle_old_regalloc (void)
 
       rebuild_jump_labels (get_insns ());
       purge_all_dead_edges (0);
+      delete_unreachable_blocks ();
 
       timevar_pop (TV_JUMP);
     }
@@ -742,7 +691,7 @@ rest_of_handle_tracer (void)
     dump_flow_info (dump_file);
   tracer (0);
   cleanup_cfg (CLEANUP_EXPENSIVE);
-  reg_scan (get_insns (), max_reg_num (), 0);
+  reg_scan (get_insns (), max_reg_num ());
   close_dump_file (DFI_tracer, print_rtl_with_bb, get_insns ());
 }
 
@@ -758,13 +707,13 @@ rest_of_handle_if_conversion (void)
       if (dump_file)
        dump_flow_info (dump_file);
       cleanup_cfg (CLEANUP_EXPENSIVE);
-      reg_scan (get_insns (), max_reg_num (), 0);
+      reg_scan (get_insns (), max_reg_num ());
       if_convert (0);
     }
 
   timevar_push (TV_JUMP);
   cleanup_cfg (CLEANUP_EXPENSIVE);
-  reg_scan (get_insns (), max_reg_num (), 0);
+  reg_scan (get_insns (), max_reg_num ());
   timevar_pop (TV_JUMP);
 
   close_dump_file (DFI_ce1, print_rtl_with_bb, get_insns ());
@@ -815,7 +764,7 @@ rest_of_handle_web (void)
 
   timevar_pop (TV_WEB);
   close_dump_file (DFI_web, print_rtl_with_bb, get_insns ());
-  reg_scan (get_insns (), max_reg_num (), 0);
+  reg_scan (get_insns (), max_reg_num ());
 }
 
 /* Do branch profiling and static profile estimation passes.  */
@@ -879,12 +828,19 @@ rest_of_handle_cfg (void)
      it as constant, otherwise -fbranch-probabilities will not read data back.
 
      life_analysis rarely eliminates modification of external memory.
-   */
-  if (optimize)
+
+     FIXME: now with tree based profiling we are in the trap described above
+     again.  It seems to be easiest to disable the optimization for time
+     being before the problem is either solved by moving the transformation
+     to the IPA level (we need the CFG for this) or the very early optimization
+     passes are made to ignore the const/pure flags so code does not change.  */
+  if (optimize
+      && (!flag_tree_based_profiling
+         || (!profile_arc_flag && !flag_branch_probabilities)))
     {
       /* Alias analysis depends on this information and mark_constant_function
        depends on alias analysis.  */
-      reg_scan (get_insns (), max_reg_num (), 1);
+      reg_scan (get_insns (), max_reg_num ());
       mark_constant_function ();
     }
 
@@ -899,7 +855,7 @@ rest_of_handle_jump_bypass (void)
   open_dump_file (DFI_bypass, current_function_decl);
 
   cleanup_cfg (CLEANUP_EXPENSIVE);
-  reg_scan (get_insns (), max_reg_num (), 1);
+  reg_scan (get_insns (), max_reg_num ());
 
   if (bypass_jumps (dump_file))
     {
@@ -960,8 +916,7 @@ rest_of_handle_life (void)
 #endif
   life_analysis (dump_file, PROP_FINAL);
   if (optimize)
-    cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_UPDATE_LIFE
-                | CLEANUP_LOG_LINKS
+    cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE | CLEANUP_LOG_LINKS
                 | (flag_thread_jumps ? CLEANUP_THREADING : 0));
 
   if (extra_warnings)
@@ -972,7 +927,7 @@ rest_of_handle_life (void)
 
   if (optimize)
     {
-      if (!flag_new_regalloc && initialize_uninitialized_subregs ())
+      if (initialize_uninitialized_subregs ())
        {
          /* Insns were inserted, and possibly pseudos created, so
             things might look a bit different.  */
@@ -1002,7 +957,7 @@ rest_of_handle_cse (void)
     dump_flow_info (dump_file);
   timevar_push (TV_CSE);
 
-  reg_scan (get_insns (), max_reg_num (), 1);
+  reg_scan (get_insns (), max_reg_num ());
 
   tem = cse_main (get_insns (), max_reg_num (), dump_file);
   if (tem)
@@ -1054,7 +1009,7 @@ rest_of_handle_cse2 (void)
       cleanup_cfg (CLEANUP_EXPENSIVE);
       timevar_pop (TV_JUMP);
     }
-  reg_scan (get_insns (), max_reg_num (), 0);
+  reg_scan (get_insns (), max_reg_num ());
   close_dump_file (DFI_cse2, print_rtl_with_bb, get_insns ());
   timevar_pop (TV_CSE2);
 
@@ -1084,7 +1039,7 @@ rest_of_handle_gcse (void)
   if (flag_expensive_optimizations)
     {
       timevar_push (TV_CSE);
-      reg_scan (get_insns (), max_reg_num (), 1);
+      reg_scan (get_insns (), max_reg_num ());
       tem2 = cse_main (get_insns (), max_reg_num (), dump_file);
       purge_all_dead_edges (0);
       delete_trivially_dead_insns (get_insns (), max_reg_num ());
@@ -1105,7 +1060,7 @@ rest_of_handle_gcse (void)
       if (flag_expensive_optimizations)
        {
          timevar_push (TV_CSE);
-         reg_scan (get_insns (), max_reg_num (), 1);
+         reg_scan (get_insns (), max_reg_num ());
          tem2 = cse_main (get_insns (), max_reg_num (), dump_file);
          purge_all_dead_edges (0);
          delete_trivially_dead_insns (get_insns (), max_reg_num ());
@@ -1128,7 +1083,7 @@ rest_of_handle_gcse (void)
 static void
 rest_of_handle_loop_optimize (void)
 {
-  int do_unroll, do_prefetch;
+  int do_prefetch;
 
   timevar_push (TV_LOOP);
   delete_dead_jumptables ();
@@ -1137,11 +1092,8 @@ rest_of_handle_loop_optimize (void)
 
   /* CFG is no longer maintained up-to-date.  */
   free_bb_for_insn ();
+  profile_status = PROFILE_ABSENT;
 
-  if (flag_unroll_loops)
-    do_unroll = LOOP_AUTO_UNROLL;      /* Having two unrollers is useless.  */
-  else
-    do_unroll = flag_old_unroll_loops ? LOOP_UNROLL : LOOP_AUTO_UNROLL;
   do_prefetch = flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0;
 
   if (flag_rerun_loop_opt)
@@ -1149,8 +1101,7 @@ rest_of_handle_loop_optimize (void)
       cleanup_barriers ();
 
       /* We only want to perform unrolling once.  */
-      loop_optimize (get_insns (), dump_file, do_unroll);
-      do_unroll = 0;
+      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
@@ -1160,10 +1111,10 @@ rest_of_handle_loop_optimize (void)
 
       /* The regscan pass is currently necessary as the alias
         analysis code depends on this information.  */
-      reg_scan (get_insns (), max_reg_num (), 1);
+      reg_scan (get_insns (), max_reg_num ());
     }
   cleanup_barriers ();
-  loop_optimize (get_insns (), dump_file, do_unroll | do_prefetch);
+  loop_optimize (get_insns (), dump_file, do_prefetch);
 
   /* Loop can create trivially dead instructions.  */
   delete_trivially_dead_insns (get_insns (), max_reg_num ());
@@ -1233,7 +1184,7 @@ rest_of_handle_loop2 (void)
 
   cleanup_cfg (CLEANUP_EXPENSIVE);
   delete_trivially_dead_insns (get_insns (), max_reg_num ());
-  reg_scan (get_insns (), max_reg_num (), 0);
+  reg_scan (get_insns (), max_reg_num ());
   if (dump_file)
     dump_flow_info (dump_file);
   close_dump_file (DFI_loop2, print_rtl_with_bb, get_insns ());
@@ -1287,27 +1238,6 @@ rest_of_handle_jump (void)
   timevar_push (TV_JUMP);
   open_dump_file (DFI_sibling, current_function_decl);
 
-  /* ??? We may get caled either via tree_rest_of_compilation when the CFG
-     is already built or directly (for instance from coverage code).
-     The direct callers shall be updated.  */
-  if (!basic_block_info)
-    {
-      init_flow ();
-      rebuild_jump_labels (get_insns ());
-      find_exception_handler_labels ();
-      find_basic_blocks (get_insns (), max_reg_num (), dump_file);
-    }
-
-  /* ??? We may get called either via tree_rest_of_compilation when the CFG
-     is already built or directly (for instance from coverage code).
-     The direct callers shall be updated.  */
-  if (!basic_block_info)
-    {
-      init_flow ();
-      rebuild_jump_labels (get_insns ());
-      find_exception_handler_labels ();
-      find_basic_blocks (get_insns (), max_reg_num (), dump_file);
-    }
   delete_unreachable_blocks ();
 #ifdef ENABLE_CHECKING
   verify_flow_info ();
@@ -1341,24 +1271,6 @@ rest_of_handle_eh (void)
     }
 }
 
-
-static void
-rest_of_handle_prologue_epilogue (void)
-{
-  if (optimize && !flow2_completed)
-    cleanup_cfg (CLEANUP_EXPENSIVE);
-
-  /* On some machines, the prologue and epilogue code, or parts thereof,
-     can be represented as RTL.  Doing so lets us schedule insns between
-     it and the rest of the code and also allows delayed branch
-     scheduling to operate in the epilogue.  */
-  thread_prologue_and_epilogue_insns (get_insns ());
-  epilogue_completed = 1;
-
-  if (optimize && flow2_completed)
-    life_analysis (dump_file, PROP_POSTRELOAD);
-}
-
 static void
 rest_of_handle_stack_adjustments (void)
 {
@@ -1394,10 +1306,21 @@ rest_of_handle_flow2 (void)
     split_all_insns (0);
 
   if (flag_branch_target_load_optimize)
-    rest_of_handle_branch_target_load_optimize ();
+    {
+      close_dump_file (DFI_flow2, print_rtl_with_bb, get_insns ());
+      rest_of_handle_branch_target_load_optimize ();
+      open_dump_file (DFI_flow2, current_function_decl);
+    }
 
-  if (!targetm.late_rtl_prologue_epilogue)
-    rest_of_handle_prologue_epilogue ();
+  if (optimize)
+    cleanup_cfg (CLEANUP_EXPENSIVE);
+
+  /* On some machines, the prologue and epilogue code, or parts thereof,
+     can be represented as RTL.  Doing so lets us schedule insns between
+     it and the rest of the code and also allows delayed branch
+     scheduling to operate in the epilogue.  */
+  thread_prologue_and_epilogue_insns (get_insns ());
+  epilogue_completed = 1;
 
   if (optimize)
     rest_of_handle_stack_adjustments ();
@@ -1427,7 +1350,7 @@ rest_of_handle_jump2 (void)
     expected_value_to_br_prob ();
 
   delete_trivially_dead_insns (get_insns (), max_reg_num ());
-  reg_scan (get_insns (), max_reg_num (), 0);
+  reg_scan (get_insns (), max_reg_num ());
   if (dump_file)
     dump_flow_info (dump_file);
   cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_PRE_LOOP
@@ -1540,8 +1463,7 @@ rest_of_clean_state (void)
   if (targetm.binds_local_p (current_function_decl))
     {
       int pref = cfun->preferred_stack_boundary;
-      if (cfun->recursive_call_emit
-          && cfun->stack_alignment_needed > cfun->preferred_stack_boundary)
+      if (cfun->stack_alignment_needed > cfun->preferred_stack_boundary)
        pref = cfun->stack_alignment_needed;
       cgraph_rtl_info (current_function_decl)->preferred_incoming_stack_boundary
         = pref;
@@ -1568,18 +1490,14 @@ rest_of_clean_state (void)
    after all tree passes have finished for a single function, and we
    have expanded the function body from trees to RTL.
    Once we are here, we have decided that we're supposed to output
-   that function, ie. that we should write assembler code for it.
+   that function, i.e. that we should write assembler code for it.
 
    We run a series of low-level passes here on the function's RTL
    representation.  Each pass is called via a rest_of_* function.  */
 
-void
+static void
 rest_of_compilation (void)
 {
-  /* Convert from NOTE_INSN_EH_REGION style notes, and do other
-     sorts of eh initialization.  */
-  convert_from_eh_region_ranges ();
-
   /* If we're emitting a nested function, make sure its parent gets
      emitted as well.  Doing otherwise confuses debug info.  */
   {
@@ -1720,7 +1638,7 @@ rest_of_compilation (void)
       && !user_defined_section_attribute)
     rest_of_handle_partition_blocks ();
 
-  if (optimize > 0 && (flag_regmove || flag_expensive_optimizations))
+  if (optimize > 0 && flag_regmove)
     rest_of_handle_regmove ();
 
   /* Do unconditional splitting before register allocation to allow machine
@@ -1749,16 +1667,8 @@ rest_of_compilation (void)
      epilogue thus changing register elimination offsets.  */
   current_function_is_leaf = leaf_function_p ();
 
-  if (flag_new_regalloc)
-    {
-      if (rest_of_handle_new_regalloc ())
-       goto exit_rest_of_compilation;
-    }
-  else
-    {
-      if (rest_of_handle_old_regalloc ())
-       goto exit_rest_of_compilation;
-    }
+  if (rest_of_handle_old_regalloc ())
+    goto exit_rest_of_compilation;
 
   if (optimize > 0)
     rest_of_handle_postreload ();
@@ -1792,9 +1702,6 @@ rest_of_compilation (void)
     = optimize > 0 && only_leaf_regs_used () && leaf_function_p ();
 #endif
 
-  if (targetm.late_rtl_prologue_epilogue)
-    rest_of_handle_prologue_epilogue ();
-
 #ifdef INSN_SCHEDULING
   if (optimize > 0 && flag_schedule_insns_after_reload)
     rest_of_handle_sched2 ();