X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Floop-init.c;h=303c2da1b72fdb2fb9c1831b779dba7c15a1d19a;hb=db1c99deee13fafacd47e6dda0ecdc5c7c80aa83;hp=bf13fd0948d3847b8d29316ffd89386e2031efb0;hpb=562d71e815ab06366be965829e291b264cfdd7b5;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/loop-init.c b/gcc/loop-init.c index bf13fd0948d..303c2da1b72 100644 --- a/gcc/loop-init.c +++ b/gcc/loop-init.c @@ -1,5 +1,5 @@ /* Loop optimizer initialization routines and RTL loop optimization passes. - Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of GCC. @@ -31,94 +31,91 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "tree-pass.h" #include "timevar.h" #include "flags.h" +#include "df.h" +#include "ggc.h" -/* Initialize loop optimizer. This is used by the tree and RTL loop +/* Initialize loop structures. This is used by the tree and RTL loop optimizers. FLAGS specify what properties to compute and/or ensure for loops. */ -struct loops * +void loop_optimizer_init (unsigned flags) { - struct loops *loops = XCNEW (struct loops); - edge e; - edge_iterator ei; - static bool first_time = true; - - if (first_time) - { - first_time = false; - init_set_costs (); - } + struct loops *loops; - /* Avoid annoying special cases of edges going to exit - block. */ - - for (ei = ei_start (EXIT_BLOCK_PTR->preds); (e = ei_safe_edge (ei)); ) - if ((e->flags & EDGE_FALLTHRU) && !single_succ_p (e->src)) - split_edge (e); - else - ei_next (&ei); + gcc_assert (!current_loops); + loops = GGC_CNEW (struct loops); /* Find the loops. */ - if (flow_loops_find (loops) <= 1) - { - /* No loops. */ - flow_loops_free (loops); - free (loops); + flow_loops_find (loops); + current_loops = loops; - return NULL; + if (flags & LOOPS_MAY_HAVE_MULTIPLE_LATCHES) + { + /* If the loops may have multiple latches, we cannot canonicalize + them further (and most of the loop manipulation functions will + not work). However, we avoid modifying cfg, which some + passes may want. */ + gcc_assert ((flags & ~(LOOPS_MAY_HAVE_MULTIPLE_LATCHES + | LOOPS_HAVE_RECORDED_EXITS)) == 0); + current_loops->state = LOOPS_MAY_HAVE_MULTIPLE_LATCHES; } - - /* Not going to update these. */ - free (loops->cfg.rc_order); - loops->cfg.rc_order = NULL; - free (loops->cfg.dfs_order); - loops->cfg.dfs_order = NULL; + else + disambiguate_loops_with_multiple_latches (); /* Create pre-headers. */ if (flags & LOOPS_HAVE_PREHEADERS) - create_preheaders (loops, CP_SIMPLE_PREHEADERS); + create_preheaders (CP_SIMPLE_PREHEADERS); /* Force all latches to have only single successor. */ if (flags & LOOPS_HAVE_SIMPLE_LATCHES) - force_single_succ_latches (loops); + force_single_succ_latches (); /* Mark irreducible loops. */ if (flags & LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS) - mark_irreducible_loops (loops); + mark_irreducible_loops (); - if (flags & LOOPS_HAVE_MARKED_SINGLE_EXITS) - mark_single_exit_loops (loops); + if (flags & LOOPS_HAVE_RECORDED_EXITS) + record_loop_exits (); /* Dump loops. */ - flow_loops_dump (loops, dump_file, NULL, 1); + flow_loops_dump (dump_file, NULL, 1); #ifdef ENABLE_CHECKING verify_dominators (CDI_DOMINATORS); - verify_loop_structure (loops); + verify_loop_structure (); #endif - - return loops; } -/* Finalize loop optimizer. */ +/* Finalize loop structures. */ + void -loop_optimizer_finalize (struct loops *loops) +loop_optimizer_finalize (void) { - unsigned i; + loop_iterator li; + struct loop *loop; + basic_block bb; - if (!loops) - return; + gcc_assert (current_loops != NULL); - for (i = 1; i < loops->num; i++) - if (loops->parray[i]) - free_simple_loop_desc (loops->parray[i]); + FOR_EACH_LOOP (li, loop, 0) + { + free_simple_loop_desc (loop); + } /* Clean up. */ - flow_loops_free (loops); - free (loops); + if (current_loops->state & LOOPS_HAVE_RECORDED_EXITS) + release_recorded_exits (); + flow_loops_free (current_loops); + ggc_free (current_loops); + current_loops = NULL; + + FOR_ALL_BB (bb) + { + bb->loop_father = NULL; + } /* Checking. */ #ifdef ENABLE_CHECKING @@ -164,16 +161,16 @@ struct tree_opt_pass pass_loop2 = /* Initialization of the RTL loop passes. */ -static void +static unsigned int rtl_loop_init (void) { + gcc_assert (current_ir_type () == IR_RTL_CFGLAYOUT); + if (dump_file) dump_flow_info (dump_file, dump_flags); - /* Initialize structures for layout changes. */ - cfg_layout_initialize (0); - - current_loops = loop_optimizer_init (LOOPS_NORMAL); + loop_optimizer_init (LOOPS_NORMAL); + return 0; } struct tree_opt_pass pass_rtl_loop_init = @@ -195,29 +192,18 @@ struct tree_opt_pass pass_rtl_loop_init = /* Finalization of the RTL loop passes. */ -static void + +static unsigned int rtl_loop_done (void) { - basic_block bb; - - if (current_loops) - loop_optimizer_finalize (current_loops); - + loop_optimizer_finalize (); free_dominance_info (CDI_DOMINATORS); - /* Finalize layout changes. */ - FOR_EACH_BB (bb) - if (bb->next_bb != EXIT_BLOCK_PTR) - bb->aux = bb->next_bb; - cfg_layout_finalize (); - - cleanup_cfg (CLEANUP_EXPENSIVE); - delete_trivially_dead_insns (get_insns (), max_reg_num ()); - reg_scan (get_insns (), max_reg_num ()); + cleanup_cfg (0); if (dump_file) dump_flow_info (dump_file, dump_flags); - current_loops = NULL; + return 0; } struct tree_opt_pass pass_rtl_loop_done = @@ -245,16 +231,17 @@ gate_rtl_move_loop_invariants (void) return flag_move_loop_invariants; } -static void +static unsigned int rtl_move_loop_invariants (void) { - if (current_loops) - move_loop_invariants (current_loops); + if (number_of_loops () > 1) + move_loop_invariants (); + return 0; } struct tree_opt_pass pass_rtl_move_loop_invariants = { - "loop2_invariant", /* name */ + "loop2_invariant", /* name */ gate_rtl_move_loop_invariants, /* gate */ rtl_move_loop_invariants, /* execute */ NULL, /* sub */ @@ -264,7 +251,8 @@ struct tree_opt_pass pass_rtl_move_loop_invariants = 0, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ - 0, /* todo_flags_start */ + 0, /* todo_flags_start */ + TODO_df_finish | /* This is shutting down the instance in loop_invariant.c */ TODO_dump_func, /* todo_flags_finish */ 'L' /* letter */ }; @@ -277,11 +265,12 @@ gate_rtl_unswitch (void) return flag_unswitch_loops; } -static void +static unsigned int rtl_unswitch (void) { - if (current_loops) - unswitch_loops (current_loops); + if (number_of_loops () > 1) + unswitch_loops (); + return 0; } struct tree_opt_pass pass_rtl_unswitch = @@ -309,12 +298,14 @@ gate_rtl_unroll_and_peel_loops (void) return (flag_peel_loops || flag_unroll_loops || flag_unroll_all_loops); } -static void +static unsigned int rtl_unroll_and_peel_loops (void) { - if (current_loops) + if (number_of_loops () > 1) { int flags = 0; + if (dump_file) + df_dump (dump_file); if (flag_peel_loops) flags |= UAP_PEEL; @@ -323,8 +314,9 @@ rtl_unroll_and_peel_loops (void) if (flag_unroll_all_loops) flags |= UAP_UNROLL_ALL; - unroll_and_peel_loops (current_loops, flags); + unroll_and_peel_loops (flags); } + return 0; } struct tree_opt_pass pass_rtl_unroll_and_peel_loops = @@ -356,13 +348,14 @@ gate_rtl_doloop (void) #endif } -static void +static unsigned int rtl_doloop (void) { #ifdef HAVE_doloop_end - if (current_loops) - doloop_optimize_loops (current_loops); + if (number_of_loops () > 1) + doloop_optimize_loops (); #endif + return 0; } struct tree_opt_pass pass_rtl_doloop =