00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "system.h"
00023 #include "coretypes.h"
00024 #include "tm.h"
00025 #include "rtl.h"
00026 #include "hard-reg-set.h"
00027 #include "obstack.h"
00028 #include "basic-block.h"
00029 #include "cfgloop.h"
00030 #include "cfglayout.h"
00031 #include "tree-pass.h"
00032 #include "timevar.h"
00033 #include "flags.h"
00034
00035
00036
00037
00038
00039
00040 struct loops *
00041 loop_optimizer_init (unsigned flags)
00042 {
00043 struct loops *loops = XCNEW (struct loops);
00044 edge e;
00045 edge_iterator ei;
00046 static bool first_time = true;
00047
00048 if (first_time)
00049 {
00050 first_time = false;
00051 init_set_costs ();
00052 }
00053
00054
00055
00056
00057 for (ei = ei_start (EXIT_BLOCK_PTR->preds); (e = ei_safe_edge (ei)); )
00058 if ((e->flags & EDGE_FALLTHRU) && !single_succ_p (e->src))
00059 split_edge (e);
00060 else
00061 ei_next (&ei);
00062
00063
00064
00065 if (flow_loops_find (loops) <= 1)
00066 {
00067
00068 flow_loops_free (loops);
00069 free (loops);
00070
00071 return NULL;
00072 }
00073
00074
00075 free (loops->cfg.rc_order);
00076 loops->cfg.rc_order = NULL;
00077 free (loops->cfg.dfs_order);
00078 loops->cfg.dfs_order = NULL;
00079
00080
00081 if (flags & LOOPS_HAVE_PREHEADERS)
00082 create_preheaders (loops, CP_SIMPLE_PREHEADERS);
00083
00084
00085 if (flags & LOOPS_HAVE_SIMPLE_LATCHES)
00086 force_single_succ_latches (loops);
00087
00088
00089 if (flags & LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)
00090 mark_irreducible_loops (loops);
00091
00092 if (flags & LOOPS_HAVE_MARKED_SINGLE_EXITS)
00093 mark_single_exit_loops (loops);
00094
00095
00096 flow_loops_dump (loops, dump_file, NULL, 1);
00097
00098 #ifdef ENABLE_CHECKING
00099 verify_dominators (CDI_DOMINATORS);
00100 verify_loop_structure (loops);
00101 #endif
00102
00103 return loops;
00104 }
00105
00106
00107 void
00108 loop_optimizer_finalize (struct loops *loops)
00109 {
00110 unsigned i;
00111
00112 if (!loops)
00113 return;
00114
00115 for (i = 1; i < loops->num; i++)
00116 if (loops->parray[i])
00117 free_simple_loop_desc (loops->parray[i]);
00118
00119
00120 flow_loops_free (loops);
00121 free (loops);
00122
00123
00124 #ifdef ENABLE_CHECKING
00125 verify_flow_info ();
00126 #endif
00127 }
00128
00129
00130
00131
00132
00133 static bool
00134 gate_handle_loop2 (void)
00135 {
00136 return (optimize > 0
00137 && (flag_move_loop_invariants
00138 || flag_unswitch_loops
00139 || flag_peel_loops
00140 || flag_unroll_loops
00141 #ifdef HAVE_doloop_end
00142 || (flag_branch_on_count_reg && HAVE_doloop_end)
00143 #endif
00144 ));
00145 }
00146
00147 struct tree_opt_pass pass_loop2 =
00148 {
00149 "loop2",
00150 gate_handle_loop2,
00151 NULL,
00152 NULL,
00153 NULL,
00154 0,
00155 TV_LOOP,
00156 0,
00157 0,
00158 0,
00159 0,
00160 TODO_dump_func |
00161 TODO_ggc_collect,
00162 'L'
00163 };
00164
00165
00166
00167 static unsigned int
00168 rtl_loop_init (void)
00169 {
00170 if (dump_file)
00171 dump_flow_info (dump_file, dump_flags);
00172
00173
00174 cfg_layout_initialize (0);
00175
00176 current_loops = loop_optimizer_init (LOOPS_NORMAL);
00177 return 0;
00178 }
00179
00180 struct tree_opt_pass pass_rtl_loop_init =
00181 {
00182 "loop2_init",
00183 NULL,
00184 rtl_loop_init,
00185 NULL,
00186 NULL,
00187 0,
00188 TV_LOOP,
00189 0,
00190 0,
00191 0,
00192 0,
00193 TODO_dump_func,
00194 'L'
00195 };
00196
00197
00198
00199 static unsigned int
00200 rtl_loop_done (void)
00201 {
00202 basic_block bb;
00203
00204 if (current_loops)
00205 loop_optimizer_finalize (current_loops);
00206
00207 free_dominance_info (CDI_DOMINATORS);
00208
00209
00210 FOR_EACH_BB (bb)
00211 if (bb->next_bb != EXIT_BLOCK_PTR)
00212 bb->aux = bb->next_bb;
00213 cfg_layout_finalize ();
00214
00215 cleanup_cfg (CLEANUP_EXPENSIVE);
00216 delete_trivially_dead_insns (get_insns (), max_reg_num ());
00217 reg_scan (get_insns (), max_reg_num ());
00218 if (dump_file)
00219 dump_flow_info (dump_file, dump_flags);
00220
00221 current_loops = NULL;
00222 return 0;
00223 }
00224
00225 struct tree_opt_pass pass_rtl_loop_done =
00226 {
00227 "loop2_done",
00228 NULL,
00229 rtl_loop_done,
00230 NULL,
00231 NULL,
00232 0,
00233 TV_LOOP,
00234 0,
00235 0,
00236 0,
00237 0,
00238 TODO_dump_func,
00239 'L'
00240 };
00241
00242
00243
00244 static bool
00245 gate_rtl_move_loop_invariants (void)
00246 {
00247 return flag_move_loop_invariants;
00248 }
00249
00250 static unsigned int
00251 rtl_move_loop_invariants (void)
00252 {
00253 if (current_loops)
00254 move_loop_invariants (current_loops);
00255 return 0;
00256 }
00257
00258 struct tree_opt_pass pass_rtl_move_loop_invariants =
00259 {
00260 "loop2_invariant",
00261 gate_rtl_move_loop_invariants,
00262 rtl_move_loop_invariants,
00263 NULL,
00264 NULL,
00265 0,
00266 TV_LOOP,
00267 0,
00268 0,
00269 0,
00270 0,
00271 TODO_dump_func,
00272 'L'
00273 };
00274
00275
00276
00277 static bool
00278 gate_rtl_unswitch (void)
00279 {
00280 return flag_unswitch_loops;
00281 }
00282
00283 static unsigned int
00284 rtl_unswitch (void)
00285 {
00286 if (current_loops)
00287 unswitch_loops (current_loops);
00288 return 0;
00289 }
00290
00291 struct tree_opt_pass pass_rtl_unswitch =
00292 {
00293 "loop2_unswitch",
00294 gate_rtl_unswitch,
00295 rtl_unswitch,
00296 NULL,
00297 NULL,
00298 0,
00299 TV_LOOP,
00300 0,
00301 0,
00302 0,
00303 0,
00304 TODO_dump_func,
00305 'L'
00306 };
00307
00308
00309
00310 static bool
00311 gate_rtl_unroll_and_peel_loops (void)
00312 {
00313 return (flag_peel_loops || flag_unroll_loops || flag_unroll_all_loops);
00314 }
00315
00316 static unsigned int
00317 rtl_unroll_and_peel_loops (void)
00318 {
00319 if (current_loops)
00320 {
00321 int flags = 0;
00322
00323 if (flag_peel_loops)
00324 flags |= UAP_PEEL;
00325 if (flag_unroll_loops)
00326 flags |= UAP_UNROLL;
00327 if (flag_unroll_all_loops)
00328 flags |= UAP_UNROLL_ALL;
00329
00330 unroll_and_peel_loops (current_loops, flags);
00331 }
00332 return 0;
00333 }
00334
00335 struct tree_opt_pass pass_rtl_unroll_and_peel_loops =
00336 {
00337 "loop2_unroll",
00338 gate_rtl_unroll_and_peel_loops,
00339 rtl_unroll_and_peel_loops,
00340 NULL,
00341 NULL,
00342 0,
00343 TV_LOOP,
00344 0,
00345 0,
00346 0,
00347 0,
00348 TODO_dump_func,
00349 'L'
00350 };
00351
00352
00353
00354 static bool
00355 gate_rtl_doloop (void)
00356 {
00357 #ifdef HAVE_doloop_end
00358 return (flag_branch_on_count_reg && HAVE_doloop_end);
00359 #else
00360 return 0;
00361 #endif
00362 }
00363
00364 static unsigned int
00365 rtl_doloop (void)
00366 {
00367 #ifdef HAVE_doloop_end
00368 if (current_loops)
00369 doloop_optimize_loops (current_loops);
00370 #endif
00371 return 0;
00372 }
00373
00374 struct tree_opt_pass pass_rtl_doloop =
00375 {
00376 "loop2_doloop",
00377 gate_rtl_doloop,
00378 rtl_doloop,
00379 NULL,
00380 NULL,
00381 0,
00382 TV_LOOP,
00383 0,
00384 0,
00385 0,
00386 0,
00387 TODO_dump_func,
00388 'L'
00389 };
00390