summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/loop-init.c217
-rw-r--r--gcc/passes.c22
-rw-r--r--gcc/tree-pass.h16
-rw-r--r--gcc/tree-ssa-loop.c12
5 files changed, 233 insertions, 51 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9cd5cffac63..f599f04e594 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,20 @@
+2005-07-19 Steven Bosscher <stevenb@suse.de>
+
+ * loop-init.c (rest_of_handle_loop2): Remove.
+ (rtl_loop_init, rtl_loop_done, rtl_move_loop_invariants,
+ rtl_unswitch, rtl_unroll_and_peel_loops, rtl_doloop): New functions.
+ (pass_rtl_loop_init, pass_rtl_loop_done,
+ pass_rtl_move_loop_invariants, pass_rtl_unswitch,
+ pass_rtl_unroll_and_peel_loops, pass_rtl_doloop): New passes.
+ * tree-ssa-loop.c (pass_loop, pass_loop_init, pass_loop_done,
+ pass_unswitch): Rename to pass_tree_loop, pass_tree_loop_init,
+ pass_tree_loop_done, and pass_tree_unswitch.
+ (gate_loop): Rename to gate_tree_loop.
+ * passes.c (init_optimization_passes): Update for renamed tree
+ loop passes. Add the new loop2 passes as subpasses of loop2.
+ * tree-pass.h: Add extern declarations for the new loop2 subpasses.
+ Update for the renamed tree loop passes.
+
2005-07-18 Ian Lance Taylor <ian@airs.com>
PR middle-end/22057
diff --git a/gcc/loop-init.c b/gcc/loop-init.c
index 375b2bf23a5..0e0b0cf4c88 100644
--- a/gcc/loop-init.c
+++ b/gcc/loop-init.c
@@ -1,4 +1,4 @@
-/* Loop optimizer initialization routines.
+/* Loop optimizer initialization routines and RTL loop optimization passes.
Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -32,7 +32,9 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "timevar.h"
#include "flags.h"
-/* Initialize loop optimizer. */
+
+/* Initialize loop optimizer. This is used by the tree and RTL loop
+ optimizers. */
struct loops *
loop_optimizer_init (FILE *dumpfile)
@@ -119,7 +121,11 @@ loop_optimizer_finalize (struct loops *loops, FILE *dumpfile)
verify_flow_info ();
#endif
}
+
+/* Gate for the RTL loop superpass. The actual passes are subpasses.
+ See passes.c for more on that. */
+
static bool
gate_handle_loop2 (void)
{
@@ -131,45 +137,64 @@ gate_handle_loop2 (void)
|| flag_branch_on_count_reg));
}
-/* Perform loop optimizations. It might be better to do them a bit
- sooner, but we want the profile feedback to work more
- efficiently. */
-static void
-rest_of_handle_loop2 (void)
+struct tree_opt_pass pass_loop2 =
{
- struct loops *loops;
- basic_block bb;
+ "loop2", /* name */
+ gate_handle_loop2, /* gate */
+ NULL, /* 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 */
+};
+
+/* Initialization of the RTL loop passes. */
+static void
+rtl_loop_init (void)
+{
if (dump_file)
dump_flow_info (dump_file);
/* Initialize structures for layout changes. */
cfg_layout_initialize (0);
- loops = loop_optimizer_init (dump_file);
-
- if (loops)
- {
- /* The optimizations: */
- if (flag_move_loop_invariants)
- move_loop_invariants (loops);
-
- if (flag_unswitch_loops)
- unswitch_loops (loops);
+ current_loops = loop_optimizer_init (dump_file);
+}
- if (flag_peel_loops || flag_unroll_loops)
- unroll_and_peel_loops (loops,
- (flag_peel_loops ? UAP_PEEL : 0) |
- (flag_unroll_loops ? UAP_UNROLL : 0) |
- (flag_unroll_all_loops ? UAP_UNROLL_ALL : 0));
+struct tree_opt_pass pass_rtl_loop_init =
+{
+ "loopinit", /* name */
+ NULL, /* gate */
+ rtl_loop_init, /* 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_flags_finish */
+ 'L' /* letter */
+};
-#ifdef HAVE_doloop_end
- if (flag_branch_on_count_reg && HAVE_doloop_end)
- doloop_optimize_loops (loops);
-#endif /* HAVE_doloop_end */
+
+/* Finalization of the RTL loop passes. */
+static void
+rtl_loop_done (void)
+{
+ basic_block bb;
- loop_optimizer_finalize (loops, dump_file);
- }
+ if (current_loops)
+ loop_optimizer_finalize (current_loops, dump_file);
free_dominance_info (CDI_DOMINATORS);
@@ -184,13 +209,15 @@ rest_of_handle_loop2 (void)
reg_scan (get_insns (), max_reg_num ());
if (dump_file)
dump_flow_info (dump_file);
+
+ current_loops = NULL;
}
-struct tree_opt_pass pass_loop2 =
+struct tree_opt_pass pass_rtl_loop_done =
{
- "loop2", /* name */
- gate_handle_loop2, /* gate */
- rest_of_handle_loop2, /* execute */
+ "loopdone", /* name */
+ NULL, /* gate */
+ rtl_loop_done, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
@@ -199,8 +226,126 @@ struct tree_opt_pass pass_loop2 =
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func |
- TODO_ggc_collect, /* todo_flags_finish */
+ TODO_dump_func, /* todo_flags_finish */
+ 'L' /* letter */
+};
+
+
+/* Loop invariant code motion. */
+static void
+rtl_move_loop_invariants (void)
+{
+ if (current_loops && flag_move_loop_invariants)
+ move_loop_invariants (current_loops);
+}
+
+struct tree_opt_pass pass_rtl_move_loop_invariants =
+{
+ "loop_invariant", /* name */
+ NULL, /* gate */
+ rtl_move_loop_invariants, /* 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_flags_finish */
+ 'L' /* letter */
+};
+
+
+/* Loop unswitching for RTL. */
+static void
+rtl_unswitch (void)
+{
+ if (current_loops && flag_unswitch_loops)
+ unswitch_loops (current_loops);
+}
+
+struct tree_opt_pass pass_rtl_unswitch =
+{
+ "loop_unswitch", /* name */
+ NULL, /* gate */
+ rtl_unswitch, /* 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_flags_finish */
+ 'L' /* letter */
+};
+
+
+/* Loop unswitching for RTL. */
+static void
+rtl_unroll_and_peel_loops (void)
+{
+ if (current_loops
+ && (flag_peel_loops || flag_unroll_loops || flag_unroll_all_loops))
+ {
+ int flags = 0;
+
+ if (flag_peel_loops)
+ flags |= UAP_PEEL;
+ if (flag_unroll_loops)
+ flags |= UAP_UNROLL;
+ if (flag_unroll_all_loops)
+ flags |= UAP_UNROLL_ALL;
+
+ unroll_and_peel_loops (current_loops, flags);
+ }
+}
+
+struct tree_opt_pass pass_rtl_unroll_and_peel_loops =
+{
+ "loop_unroll", /* name */
+ NULL, /* gate */
+ rtl_unroll_and_peel_loops, /* 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_flags_finish */
+ 'L' /* letter */
+};
+
+
+/* The doloop optimization. */
+static void
+rtl_doloop (void)
+{
+#ifdef HAVE_doloop_end
+ if (current_loops
+ && (flag_branch_on_count_reg && HAVE_doloop_end))
+ doloop_optimize_loops (current_loops);
+#endif
+}
+
+struct tree_opt_pass pass_rtl_doloop =
+{
+ "loop_doloop", /* name */
+ NULL, /* gate */
+ rtl_doloop, /* 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_flags_finish */
'L' /* letter */
};
diff --git a/gcc/passes.c b/gcc/passes.c
index edc75f1e672..efe3e5b9421 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -525,7 +525,7 @@ init_optimization_passes (void)
NEXT_PASS (pass_reassoc);
NEXT_PASS (pass_pre);
NEXT_PASS (pass_sink_code);
- NEXT_PASS (pass_loop);
+ NEXT_PASS (pass_tree_loop);
NEXT_PASS (pass_dominator);
NEXT_PASS (pass_copy_prop);
NEXT_PASS (pass_cd_dce);
@@ -553,11 +553,11 @@ init_optimization_passes (void)
NEXT_PASS (pass_cleanup_cfg_post_optimizing);
*p = NULL;
- p = &pass_loop.sub;
- NEXT_PASS (pass_loop_init);
+ p = &pass_tree_loop.sub;
+ NEXT_PASS (pass_tree_loop_init);
NEXT_PASS (pass_copy_prop);
NEXT_PASS (pass_lim);
- NEXT_PASS (pass_unswitch);
+ NEXT_PASS (pass_tree_unswitch);
NEXT_PASS (pass_scev_cprop);
NEXT_PASS (pass_empty_loop);
NEXT_PASS (pass_record_bounds);
@@ -571,9 +571,18 @@ init_optimization_passes (void)
NEXT_PASS (pass_lower_vector_ssa);
NEXT_PASS (pass_complete_unroll);
NEXT_PASS (pass_iv_optimize);
- NEXT_PASS (pass_loop_done);
+ NEXT_PASS (pass_tree_loop_done);
*p = NULL;
+ p = &pass_loop2.sub;
+ NEXT_PASS (pass_rtl_loop_init);
+ NEXT_PASS (pass_rtl_move_loop_invariants);
+ NEXT_PASS (pass_rtl_unswitch);
+ NEXT_PASS (pass_rtl_unroll_and_peel_loops);
+ NEXT_PASS (pass_rtl_doloop);
+ NEXT_PASS (pass_rtl_loop_done);
+ *p = NULL;
+
p = &pass_rest_of_compilation.sub;
NEXT_PASS (pass_remove_unnecessary_notes);
NEXT_PASS (pass_init_function);
@@ -592,6 +601,9 @@ init_optimization_passes (void)
NEXT_PASS (pass_profiling);
NEXT_PASS (pass_rtl_ifcvt);
NEXT_PASS (pass_tracer);
+ /* Perform loop optimizations. It might be better to do them a bit
+ sooner, but we want the profile feedback to work more
+ efficiently. */
NEXT_PASS (pass_loop2);
NEXT_PASS (pass_web);
NEXT_PASS (pass_cse2);
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 7db3751952f..e5056377f92 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -222,10 +222,10 @@ extern struct tree_opt_pass pass_referenced_vars;
extern struct tree_opt_pass pass_sra;
extern struct tree_opt_pass pass_tail_recursion;
extern struct tree_opt_pass pass_tail_calls;
-extern struct tree_opt_pass pass_loop;
-extern struct tree_opt_pass pass_loop_init;
+extern struct tree_opt_pass pass_tree_loop;
+extern struct tree_opt_pass pass_tree_loop_init;
extern struct tree_opt_pass pass_lim;
-extern struct tree_opt_pass pass_unswitch;
+extern struct tree_opt_pass pass_tree_unswitch;
extern struct tree_opt_pass pass_iv_canon;
extern struct tree_opt_pass pass_scev_cprop;
extern struct tree_opt_pass pass_empty_loop;
@@ -234,7 +234,7 @@ extern struct tree_opt_pass pass_if_conversion;
extern struct tree_opt_pass pass_vectorize;
extern struct tree_opt_pass pass_complete_unroll;
extern struct tree_opt_pass pass_iv_optimize;
-extern struct tree_opt_pass pass_loop_done;
+extern struct tree_opt_pass pass_tree_loop_done;
extern struct tree_opt_pass pass_ch;
extern struct tree_opt_pass pass_ccp;
extern struct tree_opt_pass pass_build_ssa;
@@ -316,7 +316,15 @@ extern struct tree_opt_pass pass_cfg;
extern struct tree_opt_pass pass_profiling;
extern struct tree_opt_pass pass_rtl_ifcvt;
extern struct tree_opt_pass pass_tracer;
+
extern struct tree_opt_pass pass_loop2;
+extern struct tree_opt_pass pass_rtl_loop_init;
+extern struct tree_opt_pass pass_rtl_move_loop_invariants;
+extern struct tree_opt_pass pass_rtl_unswitch;
+extern struct tree_opt_pass pass_rtl_unroll_and_peel_loops;
+extern struct tree_opt_pass pass_rtl_doloop;
+extern struct tree_opt_pass pass_rtl_loop_done;
+
extern struct tree_opt_pass pass_web;
extern struct tree_opt_pass pass_cse2;
extern struct tree_opt_pass pass_life;
diff --git a/gcc/tree-ssa-loop.c b/gcc/tree-ssa-loop.c
index 1e7d73b8885..abfcf15bc76 100644
--- a/gcc/tree-ssa-loop.c
+++ b/gcc/tree-ssa-loop.c
@@ -61,15 +61,15 @@ tree_loop_optimizer_init (FILE *dump)
/* The loop superpass. */
static bool
-gate_loop (void)
+gate_tree_loop (void)
{
return flag_tree_loop_optimize != 0;
}
-struct tree_opt_pass pass_loop =
+struct tree_opt_pass pass_tree_loop =
{
"loop", /* name */
- gate_loop, /* gate */
+ gate_tree_loop, /* gate */
NULL, /* execute */
NULL, /* sub */
NULL, /* next */
@@ -98,7 +98,7 @@ tree_ssa_loop_init (void)
scev_initialize (current_loops);
}
-struct tree_opt_pass pass_loop_init =
+struct tree_opt_pass pass_tree_loop_init =
{
"loopinit", /* name */
NULL, /* gate */
@@ -166,7 +166,7 @@ gate_tree_ssa_loop_unswitch (void)
return flag_unswitch_loops != 0;
}
-struct tree_opt_pass pass_unswitch =
+struct tree_opt_pass pass_tree_unswitch =
{
"unswitch", /* name */
gate_tree_ssa_loop_unswitch, /* gate */
@@ -454,7 +454,7 @@ tree_ssa_loop_done (void)
current_loops = NULL;
}
-struct tree_opt_pass pass_loop_done =
+struct tree_opt_pass pass_tree_loop_done =
{
"loopdone", /* name */
NULL, /* gate */