OSDN Git Service

* testsuite/lib/libgomp-dg.exp (libgomp_init): Compute multilib-related
[pf3gnuchains/gcc-fork.git] / gcc / loop-init.c
1 /* Loop optimizer initialization routines and RTL loop optimization passes.
2    Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING.  If not, write to the Free
18 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301, USA.  */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "rtl.h"
26 #include "hard-reg-set.h"
27 #include "obstack.h"
28 #include "basic-block.h"
29 #include "cfgloop.h"
30 #include "cfglayout.h"
31 #include "tree-pass.h"
32 #include "timevar.h"
33 #include "flags.h"
34
35 \f
36 /* Initialize loop optimizer.  This is used by the tree and RTL loop
37    optimizers.  FLAGS specify what properties to compute and/or ensure for
38    loops.  */
39
40 struct loops *
41 loop_optimizer_init (unsigned flags)
42 {
43   struct loops *loops = XCNEW (struct loops);
44   edge e;
45   edge_iterator ei;
46   static bool first_time = true;
47
48   if (first_time)
49     {
50       first_time = false;
51       init_set_costs ();
52     }
53
54   /* Avoid annoying special cases of edges going to exit
55      block.  */
56
57   for (ei = ei_start (EXIT_BLOCK_PTR->preds); (e = ei_safe_edge (ei)); )
58     if ((e->flags & EDGE_FALLTHRU) && !single_succ_p (e->src))
59       split_edge (e);
60     else
61       ei_next (&ei);
62
63   /* Find the loops.  */
64
65   if (flow_loops_find (loops) <= 1)
66     {
67       /* No loops.  */
68       flow_loops_free (loops);
69       free (loops);
70
71       return NULL;
72     }
73
74   /* Not going to update these.  */
75   free (loops->cfg.rc_order);
76   loops->cfg.rc_order = NULL;
77   free (loops->cfg.dfs_order);
78   loops->cfg.dfs_order = NULL;
79
80   /* Create pre-headers.  */
81   if (flags & LOOPS_HAVE_PREHEADERS)
82     create_preheaders (loops, CP_SIMPLE_PREHEADERS);
83
84   /* Force all latches to have only single successor.  */
85   if (flags & LOOPS_HAVE_SIMPLE_LATCHES)
86     force_single_succ_latches (loops);
87
88   /* Mark irreducible loops.  */
89   if (flags & LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)
90     mark_irreducible_loops (loops);
91
92   if (flags & LOOPS_HAVE_MARKED_SINGLE_EXITS)
93     mark_single_exit_loops (loops);
94
95   /* Dump loops.  */
96   flow_loops_dump (loops, dump_file, NULL, 1);
97
98 #ifdef ENABLE_CHECKING
99   verify_dominators (CDI_DOMINATORS);
100   verify_loop_structure (loops);
101 #endif
102
103   return loops;
104 }
105
106 /* Finalize loop optimizer.  */
107 void
108 loop_optimizer_finalize (struct loops *loops)
109 {
110   unsigned i;
111
112   if (!loops)
113     return;
114
115   for (i = 1; i < loops->num; i++)
116     if (loops->parray[i])
117       free_simple_loop_desc (loops->parray[i]);
118
119   /* Clean up.  */
120   flow_loops_free (loops);
121   free (loops);
122
123   /* Checking.  */
124 #ifdef ENABLE_CHECKING
125   verify_flow_info ();
126 #endif
127 }
128
129 \f
130 /* Gate for the RTL loop superpass.  The actual passes are subpasses.
131    See passes.c for more on that.  */
132
133 static bool
134 gate_handle_loop2 (void)
135 {
136   return (optimize > 0 && flag_loop_optimize2
137           && (flag_move_loop_invariants
138               || flag_unswitch_loops
139               || flag_peel_loops
140               || flag_unroll_loops
141               || flag_branch_on_count_reg));
142 }
143
144 struct tree_opt_pass pass_loop2 =
145 {
146   "loop2",                              /* name */
147   gate_handle_loop2,                    /* gate */
148   NULL,                                 /* execute */
149   NULL,                                 /* sub */
150   NULL,                                 /* next */
151   0,                                    /* static_pass_number */
152   TV_LOOP,                              /* tv_id */
153   0,                                    /* properties_required */
154   0,                                    /* properties_provided */
155   0,                                    /* properties_destroyed */
156   0,                                    /* todo_flags_start */
157   TODO_dump_func |
158   TODO_ggc_collect,                     /* todo_flags_finish */
159   'L'                                   /* letter */
160 };
161
162 \f
163 /* Initialization of the RTL loop passes.  */
164 static void
165 rtl_loop_init (void)
166 {
167   if (dump_file)
168     dump_flow_info (dump_file);
169
170   /* Initialize structures for layout changes.  */
171   cfg_layout_initialize (0);
172
173   current_loops = loop_optimizer_init (LOOPS_NORMAL);
174 }
175
176 struct tree_opt_pass pass_rtl_loop_init =
177 {
178   "loop2_init",                           /* name */
179   NULL,                                 /* gate */
180   rtl_loop_init,                        /* execute */
181   NULL,                                 /* sub */
182   NULL,                                 /* next */
183   0,                                    /* static_pass_number */
184   TV_LOOP,                              /* tv_id */
185   0,                                    /* properties_required */
186   0,                                    /* properties_provided */
187   0,                                    /* properties_destroyed */
188   0,                                    /* todo_flags_start */
189   TODO_dump_func,                       /* todo_flags_finish */
190   'L'                                   /* letter */
191 };
192
193 \f
194 /* Finalization of the RTL loop passes.  */
195 static void
196 rtl_loop_done (void)
197 {
198   basic_block bb;
199
200   if (current_loops)
201     loop_optimizer_finalize (current_loops);
202
203   free_dominance_info (CDI_DOMINATORS);
204
205   /* Finalize layout changes.  */
206   FOR_EACH_BB (bb)
207     if (bb->next_bb != EXIT_BLOCK_PTR)
208       bb->aux = bb->next_bb;
209   cfg_layout_finalize ();
210
211   cleanup_cfg (CLEANUP_EXPENSIVE);
212   delete_trivially_dead_insns (get_insns (), max_reg_num ());
213   reg_scan (get_insns (), max_reg_num ());
214   if (dump_file)
215     dump_flow_info (dump_file);
216
217   current_loops = NULL;
218 }
219
220 struct tree_opt_pass pass_rtl_loop_done =
221 {
222   "loop2_done",                          /* name */
223   NULL,                                 /* gate */
224   rtl_loop_done,                        /* execute */
225   NULL,                                 /* sub */
226   NULL,                                 /* next */
227   0,                                    /* static_pass_number */
228   TV_LOOP,                              /* tv_id */
229   0,                                    /* properties_required */
230   0,                                    /* properties_provided */
231   0,                                    /* properties_destroyed */
232   0,                                    /* todo_flags_start */
233   TODO_dump_func,                       /* todo_flags_finish */
234   'L'                                   /* letter */
235 };
236
237 \f
238 /* Loop invariant code motion.  */
239 static bool
240 gate_rtl_move_loop_invariants (void)
241 {
242   return flag_move_loop_invariants;
243 }
244
245 static void
246 rtl_move_loop_invariants (void)
247 {
248   if (current_loops)
249     move_loop_invariants (current_loops);
250 }
251
252 struct tree_opt_pass pass_rtl_move_loop_invariants =
253 {
254   "loop2_invariant",                     /* name */
255   gate_rtl_move_loop_invariants,        /* gate */
256   rtl_move_loop_invariants,             /* execute */
257   NULL,                                 /* sub */
258   NULL,                                 /* next */
259   0,                                    /* static_pass_number */
260   TV_LOOP,                              /* tv_id */
261   0,                                    /* properties_required */
262   0,                                    /* properties_provided */
263   0,                                    /* properties_destroyed */
264   0,                                    /* todo_flags_start */
265   TODO_dump_func,                       /* todo_flags_finish */
266   'L'                                   /* letter */
267 };
268
269 \f
270 /* Loop unswitching for RTL.  */
271 static bool
272 gate_rtl_unswitch (void)
273 {
274   return flag_unswitch_loops;
275 }
276
277 static void
278 rtl_unswitch (void)
279 {
280   if (current_loops)
281     unswitch_loops (current_loops);
282 }
283
284 struct tree_opt_pass pass_rtl_unswitch =
285 {
286   "loop2_unswitch",                      /* name */
287   gate_rtl_unswitch,                    /* gate */
288   rtl_unswitch,                         /* execute */
289   NULL,                                 /* sub */
290   NULL,                                 /* next */
291   0,                                    /* static_pass_number */
292   TV_LOOP,                              /* tv_id */
293   0,                                    /* properties_required */
294   0,                                    /* properties_provided */
295   0,                                    /* properties_destroyed */
296   0,                                    /* todo_flags_start */
297   TODO_dump_func,                       /* todo_flags_finish */
298   'L'                                   /* letter */
299 };
300
301 \f
302 /* Loop unswitching for RTL.  */
303 static bool
304 gate_rtl_unroll_and_peel_loops (void)
305 {
306   return (flag_peel_loops || flag_unroll_loops || flag_unroll_all_loops);
307 }
308
309 static void
310 rtl_unroll_and_peel_loops (void)
311 {
312   if (current_loops)
313     {
314       int flags = 0;
315
316       if (flag_peel_loops)
317         flags |= UAP_PEEL;
318       if (flag_unroll_loops)
319         flags |= UAP_UNROLL;
320       if (flag_unroll_all_loops)
321         flags |= UAP_UNROLL_ALL;
322
323       unroll_and_peel_loops (current_loops, flags);
324     }
325 }
326
327 struct tree_opt_pass pass_rtl_unroll_and_peel_loops =
328 {
329   "loop2_unroll",                        /* name */
330   gate_rtl_unroll_and_peel_loops,       /* gate */
331   rtl_unroll_and_peel_loops,            /* execute */
332   NULL,                                 /* sub */
333   NULL,                                 /* next */
334   0,                                    /* static_pass_number */
335   TV_LOOP,                              /* tv_id */
336   0,                                    /* properties_required */
337   0,                                    /* properties_provided */
338   0,                                    /* properties_destroyed */
339   0,                                    /* todo_flags_start */
340   TODO_dump_func,                       /* todo_flags_finish */
341   'L'                                   /* letter */
342 };
343
344 \f
345 /* The doloop optimization.  */
346 static bool
347 gate_rtl_doloop (void)
348 {
349 #ifdef HAVE_doloop_end
350   return (flag_branch_on_count_reg && HAVE_doloop_end);
351 #else
352   return 0;
353 #endif
354 }
355
356 static void
357 rtl_doloop (void)
358 {
359 #ifdef HAVE_doloop_end
360   if (current_loops)
361     doloop_optimize_loops (current_loops);
362 #endif
363 }
364
365 struct tree_opt_pass pass_rtl_doloop =
366 {
367   "loop2_doloop",                        /* name */
368   gate_rtl_doloop,                      /* gate */
369   rtl_doloop,                           /* execute */
370   NULL,                                 /* sub */
371   NULL,                                 /* next */
372   0,                                    /* static_pass_number */
373   TV_LOOP,                              /* tv_id */
374   0,                                    /* properties_required */
375   0,                                    /* properties_provided */
376   0,                                    /* properties_destroyed */
377   0,                                    /* todo_flags_start */
378   TODO_dump_func,                       /* todo_flags_finish */
379   'L'                                   /* letter */
380 };
381