OSDN Git Service

* tree.c (protected_set_expr_location): New.
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-loop.c
1 /* Loop optimizations over tree-ssa.
2    Copyright (C) 2003, 2005, 2006, 2007 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
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any
9 later version.
10    
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY 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 COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
19
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "tm.h"
24 #include "tree.h"
25 #include "rtl.h"
26 #include "tm_p.h"
27 #include "hard-reg-set.h"
28 #include "basic-block.h"
29 #include "output.h"
30 #include "diagnostic.h"
31 #include "tree-flow.h"
32 #include "tree-dump.h"
33 #include "tree-pass.h"
34 #include "timevar.h"
35 #include "cfgloop.h"
36 #include "flags.h"
37 #include "tree-inline.h"
38 #include "tree-scalar-evolution.h"
39
40 /* The loop superpass.  */
41
42 static bool
43 gate_tree_loop (void)
44 {
45   return flag_tree_loop_optimize != 0;
46 }
47
48 struct gimple_opt_pass pass_tree_loop = 
49 {
50  {
51   GIMPLE_PASS,
52   "loop",                               /* name */
53   gate_tree_loop,                       /* gate */
54   NULL,                                 /* execute */
55   NULL,                                 /* sub */
56   NULL,                                 /* next */
57   0,                                    /* static_pass_number */
58   TV_TREE_LOOP,                         /* tv_id */
59   PROP_cfg,                             /* properties_required */
60   0,                                    /* properties_provided */
61   0,                                    /* properties_destroyed */
62   TODO_ggc_collect,                     /* todo_flags_start */
63   TODO_dump_func | TODO_verify_ssa | TODO_ggc_collect   /* todo_flags_finish */
64  }
65 };
66
67 /* Loop optimizer initialization.  */
68
69 static unsigned int
70 tree_ssa_loop_init (void)
71 {
72   loop_optimizer_init (LOOPS_NORMAL
73                        | LOOPS_HAVE_RECORDED_EXITS);
74   rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
75
76   if (number_of_loops () <= 1)
77     return 0;
78
79   scev_initialize ();
80   return 0;
81 }
82   
83 struct gimple_opt_pass pass_tree_loop_init = 
84 {
85  {
86   GIMPLE_PASS,
87   "loopinit",                           /* name */
88   NULL,                                 /* gate */
89   tree_ssa_loop_init,                   /* execute */
90   NULL,                                 /* sub */
91   NULL,                                 /* next */
92   0,                                    /* static_pass_number */
93   TV_TREE_LOOP_INIT,                    /* tv_id */
94   PROP_cfg,                             /* properties_required */
95   0,                                    /* properties_provided */
96   0,                                    /* properties_destroyed */
97   0,                                    /* todo_flags_start */
98   TODO_dump_func | TODO_verify_loops    /* todo_flags_finish */
99  }
100 };
101
102 /* Loop invariant motion pass.  */
103
104 static unsigned int
105 tree_ssa_loop_im (void)
106 {
107   if (number_of_loops () <= 1)
108     return 0;
109
110   tree_ssa_lim ();
111   return 0;
112 }
113
114 static bool
115 gate_tree_ssa_loop_im (void)
116 {
117   return flag_tree_loop_im != 0;
118 }
119
120 struct gimple_opt_pass pass_lim = 
121 {
122  {
123   GIMPLE_PASS,
124   "lim",                                /* name */
125   gate_tree_ssa_loop_im,                /* gate */
126   tree_ssa_loop_im,                     /* execute */
127   NULL,                                 /* sub */
128   NULL,                                 /* next */
129   0,                                    /* static_pass_number */
130   TV_LIM,                               /* tv_id */
131   PROP_cfg,                             /* properties_required */
132   0,                                    /* properties_provided */
133   0,                                    /* properties_destroyed */
134   0,                                    /* todo_flags_start */
135   TODO_dump_func | TODO_verify_loops    /* todo_flags_finish */
136  }
137 };
138
139 /* Loop unswitching pass.  */
140
141 static unsigned int
142 tree_ssa_loop_unswitch (void)
143 {
144   if (number_of_loops () <= 1)
145     return 0;
146
147   return tree_ssa_unswitch_loops ();
148 }
149
150 static bool
151 gate_tree_ssa_loop_unswitch (void)
152 {
153   return flag_unswitch_loops != 0;
154 }
155
156 struct gimple_opt_pass pass_tree_unswitch = 
157 {
158  {
159   GIMPLE_PASS,
160   "unswitch",                           /* name */
161   gate_tree_ssa_loop_unswitch,          /* gate */
162   tree_ssa_loop_unswitch,               /* execute */
163   NULL,                                 /* sub */
164   NULL,                                 /* next */
165   0,                                    /* static_pass_number */
166   TV_TREE_LOOP_UNSWITCH,                /* tv_id */
167   PROP_cfg,                             /* properties_required */
168   0,                                    /* properties_provided */
169   0,                                    /* properties_destroyed */
170   0,                                    /* todo_flags_start */
171   TODO_ggc_collect | TODO_dump_func
172     | TODO_verify_loops                 /* todo_flags_finish */
173  }
174 };
175
176 /* Predictive commoning.  */
177
178 static unsigned
179 run_tree_predictive_commoning (void)
180 {
181   if (!current_loops)
182     return 0;
183
184   tree_predictive_commoning ();
185   return 0;
186 }
187
188 static bool
189 gate_tree_predictive_commoning (void)
190 {
191   return flag_predictive_commoning != 0;
192 }
193
194 struct gimple_opt_pass pass_predcom = 
195 {
196  {
197   GIMPLE_PASS,
198   "pcom",                               /* name */
199   gate_tree_predictive_commoning,       /* gate */
200   run_tree_predictive_commoning,        /* execute */
201   NULL,                                 /* sub */
202   NULL,                                 /* next */
203   0,                                    /* static_pass_number */
204   TV_PREDCOM,                           /* tv_id */
205   PROP_cfg,                             /* properties_required */
206   0,                                    /* properties_provided */
207   0,                                    /* properties_destroyed */
208   0,                                    /* todo_flags_start */
209   TODO_dump_func | TODO_verify_loops
210     | TODO_update_ssa_only_virtuals     /* todo_flags_finish */
211  }
212 };
213
214 /* Loop autovectorization.  */
215
216 static unsigned int
217 tree_vectorize (void)
218 {
219   if (number_of_loops () <= 1)
220     return 0;
221
222   return vectorize_loops ();
223 }
224
225 static bool
226 gate_tree_vectorize (void)
227 {
228   return flag_tree_vectorize;
229 }
230
231 struct gimple_opt_pass pass_vectorize =
232 {
233  {
234   GIMPLE_PASS,
235   "vect",                               /* name */
236   gate_tree_vectorize,                  /* gate */
237   tree_vectorize,                       /* execute */
238   NULL,                                 /* sub */
239   NULL,                                 /* next */
240   0,                                    /* static_pass_number */
241   TV_TREE_VECTORIZATION,                /* tv_id */
242   PROP_cfg | PROP_ssa,                  /* properties_required */
243   0,                                    /* properties_provided */
244   0,                                    /* properties_destroyed */
245   TODO_verify_loops,                    /* todo_flags_start */
246   TODO_dump_func | TODO_update_ssa
247     | TODO_ggc_collect                  /* todo_flags_finish */
248  }
249 };
250
251 /* Loop nest optimizations.  */
252
253 static unsigned int
254 tree_linear_transform (void)
255 {
256   if (number_of_loops () <= 1)
257     return 0;
258
259   linear_transform_loops ();
260   return 0;
261 }
262
263 static bool
264 gate_tree_linear_transform (void)
265 {
266   return flag_tree_loop_linear != 0;
267 }
268
269 struct gimple_opt_pass pass_linear_transform =
270 {
271  {
272   GIMPLE_PASS,
273   "ltrans",                             /* name */
274   gate_tree_linear_transform,           /* gate */
275   tree_linear_transform,                /* execute */
276   NULL,                                 /* sub */
277   NULL,                                 /* next */
278   0,                                    /* static_pass_number */
279   TV_TREE_LINEAR_TRANSFORM,             /* tv_id */
280   PROP_cfg | PROP_ssa,                  /* properties_required */
281   0,                                    /* properties_provided */
282   0,                                    /* properties_destroyed */
283   0,                                    /* todo_flags_start */
284   TODO_dump_func | TODO_verify_loops
285     | TODO_update_ssa_only_virtuals
286     | TODO_ggc_collect                  /* todo_flags_finish */
287  }
288 };
289
290 /* Check the correctness of the data dependence analyzers.  */
291
292 static unsigned int
293 check_data_deps (void)
294 {
295   if (number_of_loops () <= 1)
296     return 0;
297
298   tree_check_data_deps ();
299   return 0;
300 }
301
302 static bool
303 gate_check_data_deps (void)
304 {
305   return flag_check_data_deps != 0;
306 }
307
308 struct gimple_opt_pass pass_check_data_deps =
309 {
310  {
311   GIMPLE_PASS,
312   "ckdd",                               /* name */
313   gate_check_data_deps,                 /* gate */
314   check_data_deps,                      /* execute */
315   NULL,                                 /* sub */
316   NULL,                                 /* next */
317   0,                                    /* static_pass_number */
318   TV_CHECK_DATA_DEPS,                   /* tv_id */
319   PROP_cfg | PROP_ssa,                  /* properties_required */
320   0,                                    /* properties_provided */
321   0,                                    /* properties_destroyed */
322   0,                                    /* todo_flags_start */
323   TODO_dump_func                        /* todo_flags_finish */
324  }
325 };
326
327 /* Canonical induction variable creation pass.  */
328
329 static unsigned int
330 tree_ssa_loop_ivcanon (void)
331 {
332   if (number_of_loops () <= 1)
333     return 0;
334
335   return canonicalize_induction_variables ();
336 }
337
338 static bool
339 gate_tree_ssa_loop_ivcanon (void)
340 {
341   return flag_tree_loop_ivcanon != 0;
342 }
343
344 struct gimple_opt_pass pass_iv_canon =
345 {
346  {
347   GIMPLE_PASS,
348   "ivcanon",                            /* name */
349   gate_tree_ssa_loop_ivcanon,           /* gate */
350   tree_ssa_loop_ivcanon,                /* execute */
351   NULL,                                 /* sub */
352   NULL,                                 /* next */
353   0,                                    /* static_pass_number */
354   TV_TREE_LOOP_IVCANON,                 /* tv_id */
355   PROP_cfg | PROP_ssa,                  /* properties_required */
356   0,                                    /* properties_provided */
357   0,                                    /* properties_destroyed */
358   0,                                    /* todo_flags_start */
359   TODO_dump_func | TODO_verify_loops    /* todo_flags_finish */
360  }
361 };
362
363 /* Propagation of constants using scev.  */
364
365 static bool
366 gate_scev_const_prop (void)
367 {
368   return flag_tree_scev_cprop;
369 }
370
371 struct gimple_opt_pass pass_scev_cprop =
372 {
373  {
374   GIMPLE_PASS,
375   "sccp",                               /* name */
376   gate_scev_const_prop,                 /* gate */
377   scev_const_prop,                      /* execute */
378   NULL,                                 /* sub */
379   NULL,                                 /* next */
380   0,                                    /* static_pass_number */
381   TV_SCEV_CONST,                        /* tv_id */
382   PROP_cfg | PROP_ssa,                  /* properties_required */
383   0,                                    /* properties_provided */
384   0,                                    /* properties_destroyed */
385   0,                                    /* todo_flags_start */
386   TODO_dump_func | TODO_cleanup_cfg
387     | TODO_update_ssa_only_virtuals
388                                         /* todo_flags_finish */
389  }
390 };
391
392 /* Remove empty loops.  */
393
394 static unsigned int
395 tree_ssa_empty_loop (void)
396 {
397   if (number_of_loops () <= 1)
398     return 0;
399
400   return remove_empty_loops ();
401 }
402
403 struct gimple_opt_pass pass_empty_loop =
404 {
405  {
406   GIMPLE_PASS,
407   "empty",                              /* name */
408   NULL,                                 /* gate */
409   tree_ssa_empty_loop,                  /* execute */
410   NULL,                                 /* sub */
411   NULL,                                 /* next */
412   0,                                    /* static_pass_number */
413   TV_COMPLETE_UNROLL,                   /* tv_id */
414   PROP_cfg | PROP_ssa,                  /* properties_required */
415   0,                                    /* properties_provided */
416   0,                                    /* properties_destroyed */
417   0,                                    /* todo_flags_start */
418   TODO_dump_func | TODO_verify_loops 
419     | TODO_ggc_collect                  /* todo_flags_finish */
420  }
421 };
422
423 /* Record bounds on numbers of iterations of loops.  */
424
425 static unsigned int
426 tree_ssa_loop_bounds (void)
427 {
428   if (number_of_loops () <= 1)
429     return 0;
430
431   estimate_numbers_of_iterations ();
432   scev_reset ();
433   return 0;
434 }
435
436 struct gimple_opt_pass pass_record_bounds =
437 {
438  {
439   GIMPLE_PASS,
440   NULL,                                 /* name */
441   NULL,                                 /* gate */
442   tree_ssa_loop_bounds,                 /* execute */
443   NULL,                                 /* sub */
444   NULL,                                 /* next */
445   0,                                    /* static_pass_number */
446   TV_TREE_LOOP_BOUNDS,                  /* tv_id */
447   PROP_cfg | PROP_ssa,                  /* properties_required */
448   0,                                    /* properties_provided */
449   0,                                    /* properties_destroyed */
450   0,                                    /* todo_flags_start */
451   0                                     /* todo_flags_finish */
452  }
453 };
454
455 /* Complete unrolling of loops.  */
456
457 static unsigned int
458 tree_complete_unroll (void)
459 {
460   if (number_of_loops () <= 1)
461     return 0;
462
463   return tree_unroll_loops_completely (flag_unroll_loops
464                                        || flag_peel_loops
465                                        || optimize >= 3, true);
466 }
467
468 static bool
469 gate_tree_complete_unroll (void)
470 {
471   return true;
472 }
473
474 struct gimple_opt_pass pass_complete_unroll =
475 {
476  {
477   GIMPLE_PASS,
478   "cunroll",                            /* name */
479   gate_tree_complete_unroll,            /* gate */
480   tree_complete_unroll,                 /* execute */
481   NULL,                                 /* sub */
482   NULL,                                 /* next */
483   0,                                    /* static_pass_number */
484   TV_COMPLETE_UNROLL,                   /* tv_id */
485   PROP_cfg | PROP_ssa,                  /* properties_required */
486   0,                                    /* properties_provided */
487   0,                                    /* properties_destroyed */
488   0,                                    /* todo_flags_start */
489   TODO_dump_func | TODO_verify_loops
490     | TODO_ggc_collect                  /* todo_flags_finish */
491  }
492 };
493
494 /* Complete unrolling of inner loops.  */
495
496 static unsigned int
497 tree_complete_unroll_inner (void)
498 {
499   unsigned ret = 0;
500
501   loop_optimizer_init (LOOPS_NORMAL
502                        | LOOPS_HAVE_RECORDED_EXITS);
503   if (number_of_loops () > 1)
504     {
505       scev_initialize ();
506       ret = tree_unroll_loops_completely (optimize >= 3, false);
507       free_numbers_of_iterations_estimates ();
508       scev_finalize ();
509     }
510   loop_optimizer_finalize ();
511
512   return ret;
513 }
514
515 static bool
516 gate_tree_complete_unroll_inner (void)
517 {
518   return optimize >= 2;
519 }
520
521 struct gimple_opt_pass pass_complete_unrolli =
522 {
523  {
524   GIMPLE_PASS,
525   "cunrolli",                           /* name */
526   gate_tree_complete_unroll_inner,      /* gate */
527   tree_complete_unroll_inner,           /* execute */
528   NULL,                                 /* sub */
529   NULL,                                 /* next */
530   0,                                    /* static_pass_number */
531   TV_COMPLETE_UNROLL,                   /* tv_id */
532   PROP_cfg | PROP_ssa,                  /* properties_required */
533   0,                                    /* properties_provided */
534   0,                                    /* properties_destroyed */
535   0,                                    /* todo_flags_start */
536   TODO_dump_func | TODO_verify_loops
537     | TODO_ggc_collect                  /* todo_flags_finish */
538  }
539 };
540
541 /* Parallelization.  */
542
543 static bool
544 gate_tree_parallelize_loops (void)
545 {
546   return flag_tree_parallelize_loops > 1;
547 }
548
549 static unsigned
550 tree_parallelize_loops (void)
551 {
552   if (number_of_loops () <= 1)
553     return 0;
554
555   if (parallelize_loops ())
556     return TODO_cleanup_cfg | TODO_rebuild_alias;
557   return 0;
558 }
559
560 struct gimple_opt_pass pass_parallelize_loops =
561 {
562  {
563   GIMPLE_PASS,
564   "parloops",                           /* name */
565   gate_tree_parallelize_loops,          /* gate */
566   tree_parallelize_loops,               /* execute */
567   NULL,                                 /* sub */
568   NULL,                                 /* next */
569   0,                                    /* static_pass_number */
570   TV_TREE_PARALLELIZE_LOOPS,            /* tv_id */
571   PROP_cfg | PROP_ssa,                  /* properties_required */
572   0,                                    /* properties_provided */
573   0,                                    /* properties_destroyed */
574   0,                                    /* todo_flags_start */
575   TODO_dump_func | TODO_verify_loops    /* todo_flags_finish */
576  }
577 };
578
579 /* Prefetching.  */
580
581 static unsigned int
582 tree_ssa_loop_prefetch (void)
583 {
584   if (number_of_loops () <= 1)
585     return 0;
586
587   return tree_ssa_prefetch_arrays ();
588 }
589
590 static bool
591 gate_tree_ssa_loop_prefetch (void)
592 {
593   return flag_prefetch_loop_arrays != 0;
594 }
595
596 struct gimple_opt_pass pass_loop_prefetch =
597 {
598  {
599   GIMPLE_PASS,
600   "aprefetch",                          /* name */
601   gate_tree_ssa_loop_prefetch,          /* gate */
602   tree_ssa_loop_prefetch,               /* execute */
603   NULL,                                 /* sub */
604   NULL,                                 /* next */
605   0,                                    /* static_pass_number */
606   TV_TREE_PREFETCH,                     /* tv_id */
607   PROP_cfg | PROP_ssa,                  /* properties_required */
608   0,                                    /* properties_provided */
609   0,                                    /* properties_destroyed */
610   0,                                    /* todo_flags_start */
611   TODO_dump_func | TODO_verify_loops    /* todo_flags_finish */
612  }
613 };
614
615 /* Induction variable optimizations.  */
616
617 static unsigned int
618 tree_ssa_loop_ivopts (void)
619 {
620   if (number_of_loops () <= 1)
621     return 0;
622
623   tree_ssa_iv_optimize ();
624   return 0;
625 }
626
627 static bool
628 gate_tree_ssa_loop_ivopts (void)
629 {
630   return flag_ivopts != 0;
631 }
632
633 struct gimple_opt_pass pass_iv_optimize =
634 {
635  {
636   GIMPLE_PASS,
637   "ivopts",                             /* name */
638   gate_tree_ssa_loop_ivopts,            /* gate */
639   tree_ssa_loop_ivopts,                 /* execute */
640   NULL,                                 /* sub */
641   NULL,                                 /* next */
642   0,                                    /* static_pass_number */
643   TV_TREE_LOOP_IVOPTS,                  /* tv_id */
644   PROP_cfg | PROP_ssa,                  /* properties_required */
645   0,                                    /* properties_provided */
646   0,                                    /* properties_destroyed */
647   0,                                    /* todo_flags_start */
648   TODO_dump_func | TODO_verify_loops
649   | TODO_update_ssa | TODO_ggc_collect  /* todo_flags_finish */
650  }
651 };
652
653 /* Loop optimizer finalization.  */
654
655 static unsigned int
656 tree_ssa_loop_done (void)
657 {
658   free_numbers_of_iterations_estimates ();
659   scev_finalize ();
660   loop_optimizer_finalize ();
661   return 0;
662 }
663   
664 struct gimple_opt_pass pass_tree_loop_done = 
665 {
666  {
667   GIMPLE_PASS,
668   "loopdone",                           /* name */
669   NULL,                                 /* gate */
670   tree_ssa_loop_done,                   /* execute */
671   NULL,                                 /* sub */
672   NULL,                                 /* next */
673   0,                                    /* static_pass_number */
674   TV_TREE_LOOP_FINI,                    /* tv_id */
675   PROP_cfg,                             /* properties_required */
676   0,                                    /* properties_provided */
677   0,                                    /* properties_destroyed */
678   0,                                    /* todo_flags_start */
679   TODO_cleanup_cfg | TODO_dump_func     /* todo_flags_finish */
680  }
681 };