1 /* Loop optimizations over tree-ssa.
2 Copyright (C) 2003-2013 Free Software Foundation, Inc.
4 This file is part of GCC.
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
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
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/>. */
22 #include "coretypes.h"
26 #include "basic-block.h"
28 #include "tree-pass.h"
31 #include "tree-inline.h"
32 #include "tree-scalar-evolution.h"
33 #include "diagnostic-core.h"
34 #include "tree-vectorizer.h"
36 /* The loop superpass. */
41 return flag_tree_loop_optimize
!= 0;
46 const pass_data pass_data_tree_loop
=
48 GIMPLE_PASS
, /* type */
50 OPTGROUP_LOOP
, /* optinfo_flags */
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 */
61 class pass_tree_loop
: public gimple_opt_pass
64 pass_tree_loop(gcc::context
*ctxt
)
65 : gimple_opt_pass(pass_data_tree_loop
, ctxt
)
68 /* opt_pass methods: */
69 bool gate () { return gate_tree_loop (); }
71 }; // class pass_tree_loop
76 make_pass_tree_loop (gcc::context
*ctxt
)
78 return new pass_tree_loop (ctxt
);
81 /* Loop optimizer initialization. */
84 tree_ssa_loop_init (void)
86 loop_optimizer_init (LOOPS_NORMAL
87 | LOOPS_HAVE_RECORDED_EXITS
);
88 rewrite_into_loop_closed_ssa (NULL
, TODO_update_ssa
);
90 /* We might discover new loops, e.g. when turning irreducible
91 regions into reducible. */
94 if (number_of_loops (cfun
) <= 1)
102 const pass_data pass_data_tree_loop_init
=
104 GIMPLE_PASS
, /* type */
105 "loopinit", /* name */
106 OPTGROUP_LOOP
, /* optinfo_flags */
107 false, /* has_gate */
108 true, /* has_execute */
110 PROP_cfg
, /* properties_required */
111 0, /* properties_provided */
112 0, /* properties_destroyed */
113 0, /* todo_flags_start */
114 0, /* todo_flags_finish */
117 class pass_tree_loop_init
: public gimple_opt_pass
120 pass_tree_loop_init(gcc::context
*ctxt
)
121 : gimple_opt_pass(pass_data_tree_loop_init
, ctxt
)
124 /* opt_pass methods: */
125 unsigned int execute () { return tree_ssa_loop_init (); }
127 }; // class pass_tree_loop_init
132 make_pass_tree_loop_init (gcc::context
*ctxt
)
134 return new pass_tree_loop_init (ctxt
);
137 /* Loop invariant motion pass. */
140 tree_ssa_loop_im (void)
142 if (number_of_loops (cfun
) <= 1)
145 return tree_ssa_lim ();
149 gate_tree_ssa_loop_im (void)
151 return flag_tree_loop_im
!= 0;
156 const pass_data pass_data_lim
=
158 GIMPLE_PASS
, /* type */
160 OPTGROUP_LOOP
, /* optinfo_flags */
162 true, /* has_execute */
164 PROP_cfg
, /* properties_required */
165 0, /* properties_provided */
166 0, /* properties_destroyed */
167 0, /* todo_flags_start */
168 0, /* todo_flags_finish */
171 class pass_lim
: public gimple_opt_pass
174 pass_lim(gcc::context
*ctxt
)
175 : gimple_opt_pass(pass_data_lim
, ctxt
)
178 /* opt_pass methods: */
179 opt_pass
* clone () { return new pass_lim (ctxt_
); }
180 bool gate () { return gate_tree_ssa_loop_im (); }
181 unsigned int execute () { return tree_ssa_loop_im (); }
188 make_pass_lim (gcc::context
*ctxt
)
190 return new pass_lim (ctxt
);
193 /* Loop unswitching pass. */
196 tree_ssa_loop_unswitch (void)
198 if (number_of_loops (cfun
) <= 1)
201 return tree_ssa_unswitch_loops ();
205 gate_tree_ssa_loop_unswitch (void)
207 return flag_unswitch_loops
!= 0;
212 const pass_data pass_data_tree_unswitch
=
214 GIMPLE_PASS
, /* type */
215 "unswitch", /* name */
216 OPTGROUP_LOOP
, /* optinfo_flags */
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 */
227 class pass_tree_unswitch
: public gimple_opt_pass
230 pass_tree_unswitch(gcc::context
*ctxt
)
231 : gimple_opt_pass(pass_data_tree_unswitch
, ctxt
)
234 /* opt_pass methods: */
235 bool gate () { return gate_tree_ssa_loop_unswitch (); }
236 unsigned int execute () { return tree_ssa_loop_unswitch (); }
238 }; // class pass_tree_unswitch
243 make_pass_tree_unswitch (gcc::context
*ctxt
)
245 return new pass_tree_unswitch (ctxt
);
248 /* Predictive commoning. */
251 run_tree_predictive_commoning (void)
256 return tree_predictive_commoning ();
260 gate_tree_predictive_commoning (void)
262 return flag_predictive_commoning
!= 0;
267 const pass_data pass_data_predcom
=
269 GIMPLE_PASS
, /* type */
271 OPTGROUP_LOOP
, /* optinfo_flags */
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 */
282 class pass_predcom
: public gimple_opt_pass
285 pass_predcom(gcc::context
*ctxt
)
286 : gimple_opt_pass(pass_data_predcom
, ctxt
)
289 /* opt_pass methods: */
290 bool gate () { return gate_tree_predictive_commoning (); }
291 unsigned int execute () { return run_tree_predictive_commoning (); }
293 }; // class pass_predcom
298 make_pass_predcom (gcc::context
*ctxt
)
300 return new pass_predcom (ctxt
);
303 /* Loop autovectorization. */
306 tree_vectorize (void)
308 if (number_of_loops (cfun
) <= 1)
311 return vectorize_loops ();
315 gate_tree_vectorize (void)
317 return flag_tree_vectorize
|| cfun
->has_force_vect_loops
;
322 const pass_data pass_data_vectorize
=
324 GIMPLE_PASS
, /* type */
326 OPTGROUP_LOOP
| OPTGROUP_VEC
, /* optinfo_flags */
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 */
337 class pass_vectorize
: public gimple_opt_pass
340 pass_vectorize(gcc::context
*ctxt
)
341 : gimple_opt_pass(pass_data_vectorize
, ctxt
)
344 /* opt_pass methods: */
345 bool gate () { return gate_tree_vectorize (); }
346 unsigned int execute () { return tree_vectorize (); }
348 }; // class pass_vectorize
353 make_pass_vectorize (gcc::context
*ctxt
)
355 return new pass_vectorize (ctxt
);
358 /* GRAPHITE optimizations. */
361 graphite_transforms (void)
366 graphite_transform_loops ();
372 gate_graphite_transforms (void)
374 /* Enable -fgraphite pass if any one of the graphite optimization flags
377 || flag_loop_interchange
378 || flag_loop_strip_mine
379 || flag_graphite_identity
380 || flag_loop_parallelize_all
381 || flag_loop_optimize_isl
)
384 return flag_graphite
!= 0;
389 const pass_data pass_data_graphite
=
391 GIMPLE_PASS
, /* type */
392 "graphite0", /* name */
393 OPTGROUP_LOOP
, /* optinfo_flags */
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 */
404 class pass_graphite
: public gimple_opt_pass
407 pass_graphite(gcc::context
*ctxt
)
408 : gimple_opt_pass(pass_data_graphite
, ctxt
)
411 /* opt_pass methods: */
412 bool gate () { return gate_graphite_transforms (); }
414 }; // class pass_graphite
419 make_pass_graphite (gcc::context
*ctxt
)
421 return new pass_graphite (ctxt
);
426 const pass_data pass_data_graphite_transforms
=
428 GIMPLE_PASS
, /* type */
429 "graphite", /* name */
430 OPTGROUP_LOOP
, /* optinfo_flags */
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 */
441 class pass_graphite_transforms
: public gimple_opt_pass
444 pass_graphite_transforms(gcc::context
*ctxt
)
445 : gimple_opt_pass(pass_data_graphite_transforms
, ctxt
)
448 /* opt_pass methods: */
449 bool gate () { return gate_graphite_transforms (); }
450 unsigned int execute () { return graphite_transforms (); }
452 }; // class pass_graphite_transforms
457 make_pass_graphite_transforms (gcc::context
*ctxt
)
459 return new pass_graphite_transforms (ctxt
);
462 /* Check the correctness of the data dependence analyzers. */
465 check_data_deps (void)
467 if (number_of_loops (cfun
) <= 1)
470 tree_check_data_deps ();
475 gate_check_data_deps (void)
477 return flag_check_data_deps
!= 0;
482 const pass_data pass_data_check_data_deps
=
484 GIMPLE_PASS
, /* type */
486 OPTGROUP_LOOP
, /* optinfo_flags */
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 */
497 class pass_check_data_deps
: public gimple_opt_pass
500 pass_check_data_deps(gcc::context
*ctxt
)
501 : gimple_opt_pass(pass_data_check_data_deps
, ctxt
)
504 /* opt_pass methods: */
505 bool gate () { return gate_check_data_deps (); }
506 unsigned int execute () { return check_data_deps (); }
508 }; // class pass_check_data_deps
513 make_pass_check_data_deps (gcc::context
*ctxt
)
515 return new pass_check_data_deps (ctxt
);
518 /* Canonical induction variable creation pass. */
521 tree_ssa_loop_ivcanon (void)
523 if (number_of_loops (cfun
) <= 1)
526 return canonicalize_induction_variables ();
530 gate_tree_ssa_loop_ivcanon (void)
532 return flag_tree_loop_ivcanon
!= 0;
537 const pass_data pass_data_iv_canon
=
539 GIMPLE_PASS
, /* type */
540 "ivcanon", /* name */
541 OPTGROUP_LOOP
, /* optinfo_flags */
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 */
552 class pass_iv_canon
: public gimple_opt_pass
555 pass_iv_canon(gcc::context
*ctxt
)
556 : gimple_opt_pass(pass_data_iv_canon
, ctxt
)
559 /* opt_pass methods: */
560 bool gate () { return gate_tree_ssa_loop_ivcanon (); }
561 unsigned int execute () { return tree_ssa_loop_ivcanon (); }
563 }; // class pass_iv_canon
568 make_pass_iv_canon (gcc::context
*ctxt
)
570 return new pass_iv_canon (ctxt
);
573 /* Propagation of constants using scev. */
576 gate_scev_const_prop (void)
578 return flag_tree_scev_cprop
;
583 const pass_data pass_data_scev_cprop
=
585 GIMPLE_PASS
, /* type */
587 OPTGROUP_LOOP
, /* optinfo_flags */
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 */
596 | TODO_update_ssa_only_virtuals
), /* todo_flags_finish */
599 class pass_scev_cprop
: public gimple_opt_pass
602 pass_scev_cprop(gcc::context
*ctxt
)
603 : gimple_opt_pass(pass_data_scev_cprop
, ctxt
)
606 /* opt_pass methods: */
607 bool gate () { return gate_scev_const_prop (); }
608 unsigned int execute () { return scev_const_prop (); }
610 }; // class pass_scev_cprop
615 make_pass_scev_cprop (gcc::context
*ctxt
)
617 return new pass_scev_cprop (ctxt
);
620 /* Record bounds on numbers of iterations of loops. */
623 tree_ssa_loop_bounds (void)
625 if (number_of_loops (cfun
) <= 1)
628 estimate_numbers_of_iterations ();
635 const pass_data pass_data_record_bounds
=
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 */
650 class pass_record_bounds
: public gimple_opt_pass
653 pass_record_bounds(gcc::context
*ctxt
)
654 : gimple_opt_pass(pass_data_record_bounds
, ctxt
)
657 /* opt_pass methods: */
658 unsigned int execute () { return tree_ssa_loop_bounds (); }
660 }; // class pass_record_bounds
665 make_pass_record_bounds (gcc::context
*ctxt
)
667 return new pass_record_bounds (ctxt
);
670 /* Complete unrolling of loops. */
673 tree_complete_unroll (void)
675 if (number_of_loops (cfun
) <= 1)
678 return tree_unroll_loops_completely (flag_unroll_loops
680 || optimize
>= 3, true);
684 gate_tree_complete_unroll (void)
691 const pass_data pass_data_complete_unroll
=
693 GIMPLE_PASS
, /* type */
694 "cunroll", /* name */
695 OPTGROUP_LOOP
, /* optinfo_flags */
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 */
706 class pass_complete_unroll
: public gimple_opt_pass
709 pass_complete_unroll(gcc::context
*ctxt
)
710 : gimple_opt_pass(pass_data_complete_unroll
, ctxt
)
713 /* opt_pass methods: */
714 bool gate () { return gate_tree_complete_unroll (); }
715 unsigned int execute () { return tree_complete_unroll (); }
717 }; // class pass_complete_unroll
722 make_pass_complete_unroll (gcc::context
*ctxt
)
724 return new pass_complete_unroll (ctxt
);
727 /* Complete unrolling of inner loops. */
730 tree_complete_unroll_inner (void)
734 loop_optimizer_init (LOOPS_NORMAL
735 | LOOPS_HAVE_RECORDED_EXITS
);
736 if (number_of_loops (cfun
) > 1)
739 ret
= tree_unroll_loops_completely (optimize
>= 3, false);
740 free_numbers_of_iterations_estimates ();
743 loop_optimizer_finalize ();
749 gate_tree_complete_unroll_inner (void)
751 return optimize
>= 2;
756 const pass_data pass_data_complete_unrolli
=
758 GIMPLE_PASS
, /* type */
759 "cunrolli", /* name */
760 OPTGROUP_LOOP
, /* optinfo_flags */
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 */
771 class pass_complete_unrolli
: public gimple_opt_pass
774 pass_complete_unrolli(gcc::context
*ctxt
)
775 : gimple_opt_pass(pass_data_complete_unrolli
, ctxt
)
778 /* opt_pass methods: */
779 bool gate () { return gate_tree_complete_unroll_inner (); }
780 unsigned int execute () { return tree_complete_unroll_inner (); }
782 }; // class pass_complete_unrolli
787 make_pass_complete_unrolli (gcc::context
*ctxt
)
789 return new pass_complete_unrolli (ctxt
);
792 /* Parallelization. */
795 gate_tree_parallelize_loops (void)
797 return flag_tree_parallelize_loops
> 1;
801 tree_parallelize_loops (void)
803 if (number_of_loops (cfun
) <= 1)
806 if (parallelize_loops ())
807 return TODO_cleanup_cfg
| TODO_rebuild_alias
;
813 const pass_data pass_data_parallelize_loops
=
815 GIMPLE_PASS
, /* type */
816 "parloops", /* name */
817 OPTGROUP_LOOP
, /* optinfo_flags */
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 */
828 class pass_parallelize_loops
: public gimple_opt_pass
831 pass_parallelize_loops(gcc::context
*ctxt
)
832 : gimple_opt_pass(pass_data_parallelize_loops
, ctxt
)
835 /* opt_pass methods: */
836 bool gate () { return gate_tree_parallelize_loops (); }
837 unsigned int execute () { return tree_parallelize_loops (); }
839 }; // class pass_parallelize_loops
844 make_pass_parallelize_loops (gcc::context
*ctxt
)
846 return new pass_parallelize_loops (ctxt
);
852 tree_ssa_loop_prefetch (void)
854 if (number_of_loops (cfun
) <= 1)
857 return tree_ssa_prefetch_arrays ();
861 gate_tree_ssa_loop_prefetch (void)
863 return flag_prefetch_loop_arrays
> 0;
868 const pass_data pass_data_loop_prefetch
=
870 GIMPLE_PASS
, /* type */
871 "aprefetch", /* name */
872 OPTGROUP_LOOP
, /* optinfo_flags */
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 */
883 class pass_loop_prefetch
: public gimple_opt_pass
886 pass_loop_prefetch(gcc::context
*ctxt
)
887 : gimple_opt_pass(pass_data_loop_prefetch
, ctxt
)
890 /* opt_pass methods: */
891 bool gate () { return gate_tree_ssa_loop_prefetch (); }
892 unsigned int execute () { return tree_ssa_loop_prefetch (); }
894 }; // class pass_loop_prefetch
899 make_pass_loop_prefetch (gcc::context
*ctxt
)
901 return new pass_loop_prefetch (ctxt
);
904 /* Induction variable optimizations. */
907 tree_ssa_loop_ivopts (void)
909 if (number_of_loops (cfun
) <= 1)
912 tree_ssa_iv_optimize ();
917 gate_tree_ssa_loop_ivopts (void)
919 return flag_ivopts
!= 0;
924 const pass_data pass_data_iv_optimize
=
926 GIMPLE_PASS
, /* type */
928 OPTGROUP_LOOP
, /* optinfo_flags */
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 */
939 class pass_iv_optimize
: public gimple_opt_pass
942 pass_iv_optimize(gcc::context
*ctxt
)
943 : gimple_opt_pass(pass_data_iv_optimize
, ctxt
)
946 /* opt_pass methods: */
947 bool gate () { return gate_tree_ssa_loop_ivopts (); }
948 unsigned int execute () { return tree_ssa_loop_ivopts (); }
950 }; // class pass_iv_optimize
955 make_pass_iv_optimize (gcc::context
*ctxt
)
957 return new pass_iv_optimize (ctxt
);
960 /* Loop optimizer finalization. */
963 tree_ssa_loop_done (void)
965 free_numbers_of_iterations_estimates ();
967 loop_optimizer_finalize ();
973 const pass_data pass_data_tree_loop_done
=
975 GIMPLE_PASS
, /* type */
976 "loopdone", /* name */
977 OPTGROUP_LOOP
, /* optinfo_flags */
978 false, /* has_gate */
979 true, /* has_execute */
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 */
988 class pass_tree_loop_done
: public gimple_opt_pass
991 pass_tree_loop_done(gcc::context
*ctxt
)
992 : gimple_opt_pass(pass_data_tree_loop_done
, ctxt
)
995 /* opt_pass methods: */
996 unsigned int execute () { return tree_ssa_loop_done (); }
998 }; // class pass_tree_loop_done
1003 make_pass_tree_loop_done (gcc::context
*ctxt
)
1005 return new pass_tree_loop_done (ctxt
);