+ /* FIXME: no point to verify flow info after bundling on ia64. Use this
+ hack for achieving this. */
+ if (!reload_completed)
+ verify_flow_info ();
+#endif
+}
+
+\f
+/* Gate for the RTL loop superpass. The actual passes are subpasses.
+ See passes.c for more on that. */
+
+static bool
+gate_handle_loop2 (void)
+{
+ return (optimize > 0
+ && (flag_move_loop_invariants
+ || flag_unswitch_loops
+ || flag_peel_loops
+ || flag_unroll_loops
+#ifdef HAVE_doloop_end
+ || (flag_branch_on_count_reg && HAVE_doloop_end)
+#endif
+ ));
+}
+
+struct rtl_opt_pass pass_loop2 =
+{
+ {
+ RTL_PASS,
+ "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 */
+ }
+};
+
+\f
+/* Initialization of the RTL loop passes. */
+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);
+
+ loop_optimizer_init (LOOPS_NORMAL);
+ return 0;
+}
+
+struct rtl_opt_pass pass_rtl_loop_init =
+{
+ {
+ RTL_PASS,
+ "loop2_init", /* 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_verify_rtl_sharing /* todo_flags_finish */
+ }
+};
+
+\f
+/* Finalization of the RTL loop passes. */
+
+static unsigned int
+rtl_loop_done (void)
+{
+ loop_optimizer_finalize ();
+ free_dominance_info (CDI_DOMINATORS);
+
+ cleanup_cfg (0);
+ if (dump_file)
+ dump_flow_info (dump_file, dump_flags);
+
+ return 0;
+}
+
+struct rtl_opt_pass pass_rtl_loop_done =
+{
+ {
+ RTL_PASS,
+ "loop2_done", /* name */
+ NULL, /* gate */
+ rtl_loop_done, /* 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_verify_rtl_sharing /* todo_flags_finish */
+ }
+};
+
+\f
+/* Loop invariant code motion. */
+static bool
+gate_rtl_move_loop_invariants (void)
+{
+ return flag_move_loop_invariants;
+}
+
+static unsigned int
+rtl_move_loop_invariants (void)
+{
+ if (number_of_loops () > 1)
+ move_loop_invariants ();
+ return 0;
+}
+
+struct rtl_opt_pass pass_rtl_move_loop_invariants =
+{
+ {
+ RTL_PASS,
+ "loop2_invariant", /* name */
+ gate_rtl_move_loop_invariants, /* gate */
+ rtl_move_loop_invariants, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_LOOP_MOVE_INVARIANTS, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_df_verify |
+ TODO_df_finish | TODO_verify_rtl_sharing |
+ TODO_dump_func /* todo_flags_finish */
+ }
+};
+
+\f
+/* Loop unswitching for RTL. */
+static bool
+gate_rtl_unswitch (void)
+{
+ return flag_unswitch_loops;
+}
+
+static unsigned int
+rtl_unswitch (void)
+{
+ if (number_of_loops () > 1)
+ unswitch_loops ();
+ return 0;
+}
+
+struct rtl_opt_pass pass_rtl_unswitch =
+{
+ {
+ RTL_PASS,
+ "loop2_unswitch", /* name */
+ gate_rtl_unswitch, /* gate */
+ rtl_unswitch, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_LOOP_UNSWITCH, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_dump_func | TODO_verify_rtl_sharing, /* todo_flags_finish */
+ }
+};
+
+\f
+/* Loop unswitching for RTL. */
+static bool
+gate_rtl_unroll_and_peel_loops (void)
+{
+ return (flag_peel_loops || flag_unroll_loops || flag_unroll_all_loops);
+}
+
+static unsigned int
+rtl_unroll_and_peel_loops (void)
+{
+ if (number_of_loops () > 1)
+ {
+ int flags = 0;
+ if (dump_file)
+ df_dump (dump_file);
+
+ 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 (flags);
+ }
+ return 0;
+}
+
+struct rtl_opt_pass pass_rtl_unroll_and_peel_loops =
+{
+ {
+ RTL_PASS,
+ "loop2_unroll", /* name */
+ gate_rtl_unroll_and_peel_loops, /* gate */
+ rtl_unroll_and_peel_loops, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_LOOP_UNROLL, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_dump_func | TODO_verify_rtl_sharing, /* todo_flags_finish */
+ }
+};
+
+\f
+/* The doloop optimization. */
+static bool
+gate_rtl_doloop (void)
+{
+#ifdef HAVE_doloop_end
+ return (flag_branch_on_count_reg && HAVE_doloop_end);
+#else
+ return 0;