]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/tree-ssa-loop.c
gcc/
[thirdparty/gcc.git] / gcc / tree-ssa-loop.c
1 /* Loop optimizations over tree-ssa.
2 Copyright (C) 2003-2013 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 "tm_p.h"
26 #include "basic-block.h"
27 #include "tree-ssa.h"
28 #include "tree-pass.h"
29 #include "cfgloop.h"
30 #include "flags.h"
31 #include "tree-inline.h"
32 #include "tree-scalar-evolution.h"
33 #include "diagnostic-core.h"
34 #include "tree-vectorizer.h"
35
36 /* The loop superpass. */
37
38 static bool
39 gate_tree_loop (void)
40 {
41 return flag_tree_loop_optimize != 0;
42 }
43
44 namespace {
45
46 const pass_data pass_data_tree_loop =
47 {
48 GIMPLE_PASS, /* type */
49 "loop", /* name */
50 OPTGROUP_LOOP, /* optinfo_flags */
51 true, /* has_gate */
52 false, /* has_execute */
53 TV_TREE_LOOP, /* tv_id */
54 PROP_cfg, /* properties_required */
55 0, /* properties_provided */
56 0, /* properties_destroyed */
57 0, /* todo_flags_start */
58 TODO_verify_ssa, /* todo_flags_finish */
59 };
60
61 class pass_tree_loop : public gimple_opt_pass
62 {
63 public:
64 pass_tree_loop (gcc::context *ctxt)
65 : gimple_opt_pass (pass_data_tree_loop, ctxt)
66 {}
67
68 /* opt_pass methods: */
69 bool gate () { return gate_tree_loop (); }
70
71 }; // class pass_tree_loop
72
73 } // anon namespace
74
75 gimple_opt_pass *
76 make_pass_tree_loop (gcc::context *ctxt)
77 {
78 return new pass_tree_loop (ctxt);
79 }
80
81 /* Loop optimizer initialization. */
82
83 static unsigned int
84 tree_ssa_loop_init (void)
85 {
86 loop_optimizer_init (LOOPS_NORMAL
87 | LOOPS_HAVE_RECORDED_EXITS);
88 rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
89
90 /* We might discover new loops, e.g. when turning irreducible
91 regions into reducible. */
92 scev_initialize ();
93
94 if (number_of_loops (cfun) <= 1)
95 return 0;
96
97 return 0;
98 }
99
100 namespace {
101
102 const pass_data pass_data_tree_loop_init =
103 {
104 GIMPLE_PASS, /* type */
105 "loopinit", /* name */
106 OPTGROUP_LOOP, /* optinfo_flags */
107 false, /* has_gate */
108 true, /* has_execute */
109 TV_NONE, /* tv_id */
110 PROP_cfg, /* properties_required */
111 0, /* properties_provided */
112 0, /* properties_destroyed */
113 0, /* todo_flags_start */
114 0, /* todo_flags_finish */
115 };
116
117 class pass_tree_loop_init : public gimple_opt_pass
118 {
119 public:
120 pass_tree_loop_init (gcc::context *ctxt)
121 : gimple_opt_pass (pass_data_tree_loop_init, ctxt)
122 {}
123
124 /* opt_pass methods: */
125 unsigned int execute () { return tree_ssa_loop_init (); }
126
127 }; // class pass_tree_loop_init
128
129 } // anon namespace
130
131 gimple_opt_pass *
132 make_pass_tree_loop_init (gcc::context *ctxt)
133 {
134 return new pass_tree_loop_init (ctxt);
135 }
136
137 /* Loop invariant motion pass. */
138
139 static unsigned int
140 tree_ssa_loop_im (void)
141 {
142 if (number_of_loops (cfun) <= 1)
143 return 0;
144
145 return tree_ssa_lim ();
146 }
147
148 static bool
149 gate_tree_ssa_loop_im (void)
150 {
151 return flag_tree_loop_im != 0;
152 }
153
154 namespace {
155
156 const pass_data pass_data_lim =
157 {
158 GIMPLE_PASS, /* type */
159 "lim", /* name */
160 OPTGROUP_LOOP, /* optinfo_flags */
161 true, /* has_gate */
162 true, /* has_execute */
163 TV_LIM, /* tv_id */
164 PROP_cfg, /* properties_required */
165 0, /* properties_provided */
166 0, /* properties_destroyed */
167 0, /* todo_flags_start */
168 0, /* todo_flags_finish */
169 };
170
171 class pass_lim : public gimple_opt_pass
172 {
173 public:
174 pass_lim (gcc::context *ctxt)
175 : gimple_opt_pass (pass_data_lim, ctxt)
176 {}
177
178 /* opt_pass methods: */
179 opt_pass * clone () { return new pass_lim (m_ctxt); }
180 bool gate () { return gate_tree_ssa_loop_im (); }
181 unsigned int execute () { return tree_ssa_loop_im (); }
182
183 }; // class pass_lim
184
185 } // anon namespace
186
187 gimple_opt_pass *
188 make_pass_lim (gcc::context *ctxt)
189 {
190 return new pass_lim (ctxt);
191 }
192
193 /* Loop unswitching pass. */
194
195 static unsigned int
196 tree_ssa_loop_unswitch (void)
197 {
198 if (number_of_loops (cfun) <= 1)
199 return 0;
200
201 return tree_ssa_unswitch_loops ();
202 }
203
204 static bool
205 gate_tree_ssa_loop_unswitch (void)
206 {
207 return flag_unswitch_loops != 0;
208 }
209
210 namespace {
211
212 const pass_data pass_data_tree_unswitch =
213 {
214 GIMPLE_PASS, /* type */
215 "unswitch", /* name */
216 OPTGROUP_LOOP, /* optinfo_flags */
217 true, /* has_gate */
218 true, /* has_execute */
219 TV_TREE_LOOP_UNSWITCH, /* tv_id */
220 PROP_cfg, /* properties_required */
221 0, /* properties_provided */
222 0, /* properties_destroyed */
223 0, /* todo_flags_start */
224 0, /* todo_flags_finish */
225 };
226
227 class pass_tree_unswitch : public gimple_opt_pass
228 {
229 public:
230 pass_tree_unswitch (gcc::context *ctxt)
231 : gimple_opt_pass (pass_data_tree_unswitch, ctxt)
232 {}
233
234 /* opt_pass methods: */
235 bool gate () { return gate_tree_ssa_loop_unswitch (); }
236 unsigned int execute () { return tree_ssa_loop_unswitch (); }
237
238 }; // class pass_tree_unswitch
239
240 } // anon namespace
241
242 gimple_opt_pass *
243 make_pass_tree_unswitch (gcc::context *ctxt)
244 {
245 return new pass_tree_unswitch (ctxt);
246 }
247
248 /* Predictive commoning. */
249
250 static unsigned
251 run_tree_predictive_commoning (void)
252 {
253 if (!current_loops)
254 return 0;
255
256 return tree_predictive_commoning ();
257 }
258
259 static bool
260 gate_tree_predictive_commoning (void)
261 {
262 return flag_predictive_commoning != 0;
263 }
264
265 namespace {
266
267 const pass_data pass_data_predcom =
268 {
269 GIMPLE_PASS, /* type */
270 "pcom", /* name */
271 OPTGROUP_LOOP, /* optinfo_flags */
272 true, /* has_gate */
273 true, /* has_execute */
274 TV_PREDCOM, /* tv_id */
275 PROP_cfg, /* properties_required */
276 0, /* properties_provided */
277 0, /* properties_destroyed */
278 0, /* todo_flags_start */
279 TODO_update_ssa_only_virtuals, /* todo_flags_finish */
280 };
281
282 class pass_predcom : public gimple_opt_pass
283 {
284 public:
285 pass_predcom (gcc::context *ctxt)
286 : gimple_opt_pass (pass_data_predcom, ctxt)
287 {}
288
289 /* opt_pass methods: */
290 bool gate () { return gate_tree_predictive_commoning (); }
291 unsigned int execute () { return run_tree_predictive_commoning (); }
292
293 }; // class pass_predcom
294
295 } // anon namespace
296
297 gimple_opt_pass *
298 make_pass_predcom (gcc::context *ctxt)
299 {
300 return new pass_predcom (ctxt);
301 }
302
303 /* Loop autovectorization. */
304
305 static unsigned int
306 tree_loop_vectorize (void)
307 {
308 if (number_of_loops (cfun) <= 1)
309 return 0;
310
311 return vectorize_loops ();
312 }
313
314 static bool
315 gate_tree_loop_vectorize (void)
316 {
317 return flag_tree_loop_vectorize || cfun->has_force_vect_loops;
318 }
319
320 namespace {
321
322 const pass_data pass_data_vectorize =
323 {
324 GIMPLE_PASS, /* type */
325 "vect", /* name */
326 OPTGROUP_LOOP | OPTGROUP_VEC, /* optinfo_flags */
327 true, /* has_gate */
328 true, /* has_execute */
329 TV_TREE_VECTORIZATION, /* tv_id */
330 ( PROP_cfg | PROP_ssa ), /* properties_required */
331 0, /* properties_provided */
332 0, /* properties_destroyed */
333 0, /* todo_flags_start */
334 0, /* todo_flags_finish */
335 };
336
337 class pass_vectorize : public gimple_opt_pass
338 {
339 public:
340 pass_vectorize (gcc::context *ctxt)
341 : gimple_opt_pass (pass_data_vectorize, ctxt)
342 {}
343
344 /* opt_pass methods: */
345 bool gate () { return gate_tree_loop_vectorize (); }
346 unsigned int execute () { return tree_loop_vectorize (); }
347
348 }; // class pass_vectorize
349
350 } // anon namespace
351
352 gimple_opt_pass *
353 make_pass_vectorize (gcc::context *ctxt)
354 {
355 return new pass_vectorize (ctxt);
356 }
357
358 /* GRAPHITE optimizations. */
359
360 static unsigned int
361 graphite_transforms (void)
362 {
363 if (!current_loops)
364 return 0;
365
366 graphite_transform_loops ();
367
368 return 0;
369 }
370
371 static bool
372 gate_graphite_transforms (void)
373 {
374 /* Enable -fgraphite pass if any one of the graphite optimization flags
375 is turned on. */
376 if (flag_loop_block
377 || flag_loop_interchange
378 || flag_loop_strip_mine
379 || flag_graphite_identity
380 || flag_loop_parallelize_all
381 || flag_loop_optimize_isl)
382 flag_graphite = 1;
383
384 return flag_graphite != 0;
385 }
386
387 namespace {
388
389 const pass_data pass_data_graphite =
390 {
391 GIMPLE_PASS, /* type */
392 "graphite0", /* name */
393 OPTGROUP_LOOP, /* optinfo_flags */
394 true, /* has_gate */
395 false, /* has_execute */
396 TV_GRAPHITE, /* tv_id */
397 ( PROP_cfg | PROP_ssa ), /* properties_required */
398 0, /* properties_provided */
399 0, /* properties_destroyed */
400 0, /* todo_flags_start */
401 0, /* todo_flags_finish */
402 };
403
404 class pass_graphite : public gimple_opt_pass
405 {
406 public:
407 pass_graphite (gcc::context *ctxt)
408 : gimple_opt_pass (pass_data_graphite, ctxt)
409 {}
410
411 /* opt_pass methods: */
412 bool gate () { return gate_graphite_transforms (); }
413
414 }; // class pass_graphite
415
416 } // anon namespace
417
418 gimple_opt_pass *
419 make_pass_graphite (gcc::context *ctxt)
420 {
421 return new pass_graphite (ctxt);
422 }
423
424 namespace {
425
426 const pass_data pass_data_graphite_transforms =
427 {
428 GIMPLE_PASS, /* type */
429 "graphite", /* name */
430 OPTGROUP_LOOP, /* optinfo_flags */
431 true, /* has_gate */
432 true, /* has_execute */
433 TV_GRAPHITE_TRANSFORMS, /* tv_id */
434 ( PROP_cfg | PROP_ssa ), /* properties_required */
435 0, /* properties_provided */
436 0, /* properties_destroyed */
437 0, /* todo_flags_start */
438 0, /* todo_flags_finish */
439 };
440
441 class pass_graphite_transforms : public gimple_opt_pass
442 {
443 public:
444 pass_graphite_transforms (gcc::context *ctxt)
445 : gimple_opt_pass (pass_data_graphite_transforms, ctxt)
446 {}
447
448 /* opt_pass methods: */
449 bool gate () { return gate_graphite_transforms (); }
450 unsigned int execute () { return graphite_transforms (); }
451
452 }; // class pass_graphite_transforms
453
454 } // anon namespace
455
456 gimple_opt_pass *
457 make_pass_graphite_transforms (gcc::context *ctxt)
458 {
459 return new pass_graphite_transforms (ctxt);
460 }
461
462 /* Check the correctness of the data dependence analyzers. */
463
464 static unsigned int
465 check_data_deps (void)
466 {
467 if (number_of_loops (cfun) <= 1)
468 return 0;
469
470 tree_check_data_deps ();
471 return 0;
472 }
473
474 static bool
475 gate_check_data_deps (void)
476 {
477 return flag_check_data_deps != 0;
478 }
479
480 namespace {
481
482 const pass_data pass_data_check_data_deps =
483 {
484 GIMPLE_PASS, /* type */
485 "ckdd", /* name */
486 OPTGROUP_LOOP, /* optinfo_flags */
487 true, /* has_gate */
488 true, /* has_execute */
489 TV_CHECK_DATA_DEPS, /* tv_id */
490 ( PROP_cfg | PROP_ssa ), /* properties_required */
491 0, /* properties_provided */
492 0, /* properties_destroyed */
493 0, /* todo_flags_start */
494 0, /* todo_flags_finish */
495 };
496
497 class pass_check_data_deps : public gimple_opt_pass
498 {
499 public:
500 pass_check_data_deps (gcc::context *ctxt)
501 : gimple_opt_pass (pass_data_check_data_deps, ctxt)
502 {}
503
504 /* opt_pass methods: */
505 bool gate () { return gate_check_data_deps (); }
506 unsigned int execute () { return check_data_deps (); }
507
508 }; // class pass_check_data_deps
509
510 } // anon namespace
511
512 gimple_opt_pass *
513 make_pass_check_data_deps (gcc::context *ctxt)
514 {
515 return new pass_check_data_deps (ctxt);
516 }
517
518 /* Canonical induction variable creation pass. */
519
520 static unsigned int
521 tree_ssa_loop_ivcanon (void)
522 {
523 if (number_of_loops (cfun) <= 1)
524 return 0;
525
526 return canonicalize_induction_variables ();
527 }
528
529 static bool
530 gate_tree_ssa_loop_ivcanon (void)
531 {
532 return flag_tree_loop_ivcanon != 0;
533 }
534
535 namespace {
536
537 const pass_data pass_data_iv_canon =
538 {
539 GIMPLE_PASS, /* type */
540 "ivcanon", /* name */
541 OPTGROUP_LOOP, /* optinfo_flags */
542 true, /* has_gate */
543 true, /* has_execute */
544 TV_TREE_LOOP_IVCANON, /* tv_id */
545 ( PROP_cfg | PROP_ssa ), /* properties_required */
546 0, /* properties_provided */
547 0, /* properties_destroyed */
548 0, /* todo_flags_start */
549 0, /* todo_flags_finish */
550 };
551
552 class pass_iv_canon : public gimple_opt_pass
553 {
554 public:
555 pass_iv_canon (gcc::context *ctxt)
556 : gimple_opt_pass (pass_data_iv_canon, ctxt)
557 {}
558
559 /* opt_pass methods: */
560 bool gate () { return gate_tree_ssa_loop_ivcanon (); }
561 unsigned int execute () { return tree_ssa_loop_ivcanon (); }
562
563 }; // class pass_iv_canon
564
565 } // anon namespace
566
567 gimple_opt_pass *
568 make_pass_iv_canon (gcc::context *ctxt)
569 {
570 return new pass_iv_canon (ctxt);
571 }
572
573 /* Propagation of constants using scev. */
574
575 static bool
576 gate_scev_const_prop (void)
577 {
578 return flag_tree_scev_cprop;
579 }
580
581 namespace {
582
583 const pass_data pass_data_scev_cprop =
584 {
585 GIMPLE_PASS, /* type */
586 "sccp", /* name */
587 OPTGROUP_LOOP, /* optinfo_flags */
588 true, /* has_gate */
589 true, /* has_execute */
590 TV_SCEV_CONST, /* tv_id */
591 ( PROP_cfg | PROP_ssa ), /* properties_required */
592 0, /* properties_provided */
593 0, /* properties_destroyed */
594 0, /* todo_flags_start */
595 ( TODO_cleanup_cfg
596 | TODO_update_ssa_only_virtuals ), /* todo_flags_finish */
597 };
598
599 class pass_scev_cprop : public gimple_opt_pass
600 {
601 public:
602 pass_scev_cprop (gcc::context *ctxt)
603 : gimple_opt_pass (pass_data_scev_cprop, ctxt)
604 {}
605
606 /* opt_pass methods: */
607 bool gate () { return gate_scev_const_prop (); }
608 unsigned int execute () { return scev_const_prop (); }
609
610 }; // class pass_scev_cprop
611
612 } // anon namespace
613
614 gimple_opt_pass *
615 make_pass_scev_cprop (gcc::context *ctxt)
616 {
617 return new pass_scev_cprop (ctxt);
618 }
619
620 /* Record bounds on numbers of iterations of loops. */
621
622 static unsigned int
623 tree_ssa_loop_bounds (void)
624 {
625 if (number_of_loops (cfun) <= 1)
626 return 0;
627
628 estimate_numbers_of_iterations ();
629 scev_reset ();
630 return 0;
631 }
632
633 namespace {
634
635 const pass_data pass_data_record_bounds =
636 {
637 GIMPLE_PASS, /* type */
638 "*record_bounds", /* name */
639 OPTGROUP_NONE, /* optinfo_flags */
640 false, /* has_gate */
641 true, /* has_execute */
642 TV_TREE_LOOP_BOUNDS, /* tv_id */
643 ( PROP_cfg | PROP_ssa ), /* properties_required */
644 0, /* properties_provided */
645 0, /* properties_destroyed */
646 0, /* todo_flags_start */
647 0, /* todo_flags_finish */
648 };
649
650 class pass_record_bounds : public gimple_opt_pass
651 {
652 public:
653 pass_record_bounds (gcc::context *ctxt)
654 : gimple_opt_pass (pass_data_record_bounds, ctxt)
655 {}
656
657 /* opt_pass methods: */
658 unsigned int execute () { return tree_ssa_loop_bounds (); }
659
660 }; // class pass_record_bounds
661
662 } // anon namespace
663
664 gimple_opt_pass *
665 make_pass_record_bounds (gcc::context *ctxt)
666 {
667 return new pass_record_bounds (ctxt);
668 }
669
670 /* Complete unrolling of loops. */
671
672 static unsigned int
673 tree_complete_unroll (void)
674 {
675 if (number_of_loops (cfun) <= 1)
676 return 0;
677
678 return tree_unroll_loops_completely (flag_unroll_loops
679 || flag_peel_loops
680 || optimize >= 3, true);
681 }
682
683 static bool
684 gate_tree_complete_unroll (void)
685 {
686 return true;
687 }
688
689 namespace {
690
691 const pass_data pass_data_complete_unroll =
692 {
693 GIMPLE_PASS, /* type */
694 "cunroll", /* name */
695 OPTGROUP_LOOP, /* optinfo_flags */
696 true, /* has_gate */
697 true, /* has_execute */
698 TV_COMPLETE_UNROLL, /* tv_id */
699 ( PROP_cfg | PROP_ssa ), /* properties_required */
700 0, /* properties_provided */
701 0, /* properties_destroyed */
702 0, /* todo_flags_start */
703 0, /* todo_flags_finish */
704 };
705
706 class pass_complete_unroll : public gimple_opt_pass
707 {
708 public:
709 pass_complete_unroll (gcc::context *ctxt)
710 : gimple_opt_pass (pass_data_complete_unroll, ctxt)
711 {}
712
713 /* opt_pass methods: */
714 bool gate () { return gate_tree_complete_unroll (); }
715 unsigned int execute () { return tree_complete_unroll (); }
716
717 }; // class pass_complete_unroll
718
719 } // anon namespace
720
721 gimple_opt_pass *
722 make_pass_complete_unroll (gcc::context *ctxt)
723 {
724 return new pass_complete_unroll (ctxt);
725 }
726
727 /* Complete unrolling of inner loops. */
728
729 static unsigned int
730 tree_complete_unroll_inner (void)
731 {
732 unsigned ret = 0;
733
734 loop_optimizer_init (LOOPS_NORMAL
735 | LOOPS_HAVE_RECORDED_EXITS);
736 if (number_of_loops (cfun) > 1)
737 {
738 scev_initialize ();
739 ret = tree_unroll_loops_completely (optimize >= 3, false);
740 free_numbers_of_iterations_estimates ();
741 scev_finalize ();
742 }
743 loop_optimizer_finalize ();
744
745 return ret;
746 }
747
748 static bool
749 gate_tree_complete_unroll_inner (void)
750 {
751 return optimize >= 2;
752 }
753
754 namespace {
755
756 const pass_data pass_data_complete_unrolli =
757 {
758 GIMPLE_PASS, /* type */
759 "cunrolli", /* name */
760 OPTGROUP_LOOP, /* optinfo_flags */
761 true, /* has_gate */
762 true, /* has_execute */
763 TV_COMPLETE_UNROLL, /* tv_id */
764 ( PROP_cfg | PROP_ssa ), /* properties_required */
765 0, /* properties_provided */
766 0, /* properties_destroyed */
767 0, /* todo_flags_start */
768 TODO_verify_flow, /* todo_flags_finish */
769 };
770
771 class pass_complete_unrolli : public gimple_opt_pass
772 {
773 public:
774 pass_complete_unrolli (gcc::context *ctxt)
775 : gimple_opt_pass (pass_data_complete_unrolli, ctxt)
776 {}
777
778 /* opt_pass methods: */
779 bool gate () { return gate_tree_complete_unroll_inner (); }
780 unsigned int execute () { return tree_complete_unroll_inner (); }
781
782 }; // class pass_complete_unrolli
783
784 } // anon namespace
785
786 gimple_opt_pass *
787 make_pass_complete_unrolli (gcc::context *ctxt)
788 {
789 return new pass_complete_unrolli (ctxt);
790 }
791
792 /* Parallelization. */
793
794 static bool
795 gate_tree_parallelize_loops (void)
796 {
797 return flag_tree_parallelize_loops > 1;
798 }
799
800 static unsigned
801 tree_parallelize_loops (void)
802 {
803 if (number_of_loops (cfun) <= 1)
804 return 0;
805
806 if (parallelize_loops ())
807 return TODO_cleanup_cfg | TODO_rebuild_alias;
808 return 0;
809 }
810
811 namespace {
812
813 const pass_data pass_data_parallelize_loops =
814 {
815 GIMPLE_PASS, /* type */
816 "parloops", /* name */
817 OPTGROUP_LOOP, /* optinfo_flags */
818 true, /* has_gate */
819 true, /* has_execute */
820 TV_TREE_PARALLELIZE_LOOPS, /* tv_id */
821 ( PROP_cfg | PROP_ssa ), /* properties_required */
822 0, /* properties_provided */
823 0, /* properties_destroyed */
824 0, /* todo_flags_start */
825 TODO_verify_flow, /* todo_flags_finish */
826 };
827
828 class pass_parallelize_loops : public gimple_opt_pass
829 {
830 public:
831 pass_parallelize_loops (gcc::context *ctxt)
832 : gimple_opt_pass (pass_data_parallelize_loops, ctxt)
833 {}
834
835 /* opt_pass methods: */
836 bool gate () { return gate_tree_parallelize_loops (); }
837 unsigned int execute () { return tree_parallelize_loops (); }
838
839 }; // class pass_parallelize_loops
840
841 } // anon namespace
842
843 gimple_opt_pass *
844 make_pass_parallelize_loops (gcc::context *ctxt)
845 {
846 return new pass_parallelize_loops (ctxt);
847 }
848
849 /* Prefetching. */
850
851 static unsigned int
852 tree_ssa_loop_prefetch (void)
853 {
854 if (number_of_loops (cfun) <= 1)
855 return 0;
856
857 return tree_ssa_prefetch_arrays ();
858 }
859
860 static bool
861 gate_tree_ssa_loop_prefetch (void)
862 {
863 return flag_prefetch_loop_arrays > 0;
864 }
865
866 namespace {
867
868 const pass_data pass_data_loop_prefetch =
869 {
870 GIMPLE_PASS, /* type */
871 "aprefetch", /* name */
872 OPTGROUP_LOOP, /* optinfo_flags */
873 true, /* has_gate */
874 true, /* has_execute */
875 TV_TREE_PREFETCH, /* tv_id */
876 ( PROP_cfg | PROP_ssa ), /* properties_required */
877 0, /* properties_provided */
878 0, /* properties_destroyed */
879 0, /* todo_flags_start */
880 0, /* todo_flags_finish */
881 };
882
883 class pass_loop_prefetch : public gimple_opt_pass
884 {
885 public:
886 pass_loop_prefetch (gcc::context *ctxt)
887 : gimple_opt_pass (pass_data_loop_prefetch, ctxt)
888 {}
889
890 /* opt_pass methods: */
891 bool gate () { return gate_tree_ssa_loop_prefetch (); }
892 unsigned int execute () { return tree_ssa_loop_prefetch (); }
893
894 }; // class pass_loop_prefetch
895
896 } // anon namespace
897
898 gimple_opt_pass *
899 make_pass_loop_prefetch (gcc::context *ctxt)
900 {
901 return new pass_loop_prefetch (ctxt);
902 }
903
904 /* Induction variable optimizations. */
905
906 static unsigned int
907 tree_ssa_loop_ivopts (void)
908 {
909 if (number_of_loops (cfun) <= 1)
910 return 0;
911
912 tree_ssa_iv_optimize ();
913 return 0;
914 }
915
916 static bool
917 gate_tree_ssa_loop_ivopts (void)
918 {
919 return flag_ivopts != 0;
920 }
921
922 namespace {
923
924 const pass_data pass_data_iv_optimize =
925 {
926 GIMPLE_PASS, /* type */
927 "ivopts", /* name */
928 OPTGROUP_LOOP, /* optinfo_flags */
929 true, /* has_gate */
930 true, /* has_execute */
931 TV_TREE_LOOP_IVOPTS, /* tv_id */
932 ( PROP_cfg | PROP_ssa ), /* properties_required */
933 0, /* properties_provided */
934 0, /* properties_destroyed */
935 0, /* todo_flags_start */
936 TODO_update_ssa, /* todo_flags_finish */
937 };
938
939 class pass_iv_optimize : public gimple_opt_pass
940 {
941 public:
942 pass_iv_optimize (gcc::context *ctxt)
943 : gimple_opt_pass (pass_data_iv_optimize, ctxt)
944 {}
945
946 /* opt_pass methods: */
947 bool gate () { return gate_tree_ssa_loop_ivopts (); }
948 unsigned int execute () { return tree_ssa_loop_ivopts (); }
949
950 }; // class pass_iv_optimize
951
952 } // anon namespace
953
954 gimple_opt_pass *
955 make_pass_iv_optimize (gcc::context *ctxt)
956 {
957 return new pass_iv_optimize (ctxt);
958 }
959
960 /* Loop optimizer finalization. */
961
962 static unsigned int
963 tree_ssa_loop_done (void)
964 {
965 free_numbers_of_iterations_estimates ();
966 scev_finalize ();
967 loop_optimizer_finalize ();
968 return 0;
969 }
970
971 namespace {
972
973 const pass_data pass_data_tree_loop_done =
974 {
975 GIMPLE_PASS, /* type */
976 "loopdone", /* name */
977 OPTGROUP_LOOP, /* optinfo_flags */
978 false, /* has_gate */
979 true, /* has_execute */
980 TV_NONE, /* tv_id */
981 PROP_cfg, /* properties_required */
982 0, /* properties_provided */
983 0, /* properties_destroyed */
984 0, /* todo_flags_start */
985 ( TODO_cleanup_cfg | TODO_verify_flow ), /* todo_flags_finish */
986 };
987
988 class pass_tree_loop_done : public gimple_opt_pass
989 {
990 public:
991 pass_tree_loop_done (gcc::context *ctxt)
992 : gimple_opt_pass (pass_data_tree_loop_done, ctxt)
993 {}
994
995 /* opt_pass methods: */
996 unsigned int execute () { return tree_ssa_loop_done (); }
997
998 }; // class pass_tree_loop_done
999
1000 } // anon namespace
1001
1002 gimple_opt_pass *
1003 make_pass_tree_loop_done (gcc::context *ctxt)
1004 {
1005 return new pass_tree_loop_done (ctxt);
1006 }