1 /* Loop optimizations over tree-ssa.
2 Copyright (C) 2003-2015 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 "tree-pass.h"
28 #include "fold-const.h"
29 #include "gimple-iterator.h"
30 #include "tree-ssa-loop-ivopts.h"
31 #include "tree-ssa-loop-manip.h"
32 #include "tree-ssa-loop-niter.h"
33 #include "tree-ssa-loop.h"
35 #include "tree-inline.h"
36 #include "tree-scalar-evolution.h"
37 #include "tree-vectorizer.h"
41 /* A pass making sure loops are fixed up. */
45 const pass_data pass_data_fix_loops
=
47 GIMPLE_PASS
, /* type */
48 "fix_loops", /* name */
49 OPTGROUP_LOOP
, /* optinfo_flags */
50 TV_TREE_LOOP
, /* tv_id */
51 PROP_cfg
, /* properties_required */
52 0, /* properties_provided */
53 0, /* properties_destroyed */
54 0, /* todo_flags_start */
55 0, /* todo_flags_finish */
58 class pass_fix_loops
: public gimple_opt_pass
61 pass_fix_loops (gcc::context
*ctxt
)
62 : gimple_opt_pass (pass_data_fix_loops
, ctxt
)
65 /* opt_pass methods: */
66 virtual bool gate (function
*) { return flag_tree_loop_optimize
; }
68 virtual unsigned int execute (function
*fn
);
69 }; // class pass_fix_loops
72 pass_fix_loops::execute (function
*)
74 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
76 calculate_dominance_info (CDI_DOMINATORS
);
77 fix_loop_structure (NULL
);
85 make_pass_fix_loops (gcc::context
*ctxt
)
87 return new pass_fix_loops (ctxt
);
91 /* Gate for loop pass group. The group is controlled by -ftree-loop-optimize
92 but we also avoid running it when the IL doesn't contain any loop. */
95 gate_loop (function
*fn
)
97 if (!flag_tree_loop_optimize
)
100 /* For -fdump-passes which runs before loop discovery print the
101 state of -ftree-loop-optimize. */
102 if (!loops_for_fn (fn
))
105 return number_of_loops (fn
) > 1;
108 /* The loop superpass. */
112 const pass_data pass_data_tree_loop
=
114 GIMPLE_PASS
, /* type */
116 OPTGROUP_LOOP
, /* optinfo_flags */
117 TV_TREE_LOOP
, /* tv_id */
118 PROP_cfg
, /* properties_required */
119 0, /* properties_provided */
120 0, /* properties_destroyed */
121 0, /* todo_flags_start */
122 0, /* todo_flags_finish */
125 class pass_tree_loop
: public gimple_opt_pass
128 pass_tree_loop (gcc::context
*ctxt
)
129 : gimple_opt_pass (pass_data_tree_loop
, ctxt
)
132 /* opt_pass methods: */
133 virtual bool gate (function
*fn
) { return gate_loop (fn
); }
135 }; // class pass_tree_loop
140 make_pass_tree_loop (gcc::context
*ctxt
)
142 return new pass_tree_loop (ctxt
);
145 /* Gate for oacc kernels pass group. */
148 gate_oacc_kernels (function
*fn
)
150 if (flag_tree_parallelize_loops
<= 1)
153 tree oacc_function_attr
= get_oacc_fn_attrib (fn
->decl
);
154 if (oacc_function_attr
== NULL_TREE
)
157 tree val
= TREE_VALUE (oacc_function_attr
);
158 while (val
!= NULL_TREE
&& TREE_VALUE (val
) == NULL_TREE
)
159 val
= TREE_CHAIN (val
);
161 if (val
!= NULL_TREE
)
165 FOR_EACH_LOOP (loop
, 0)
166 if (loop
->in_oacc_kernels_region
)
172 /* The oacc kernels superpass. */
176 const pass_data pass_data_oacc_kernels
=
178 GIMPLE_PASS
, /* type */
179 "oacc_kernels", /* name */
180 OPTGROUP_LOOP
, /* optinfo_flags */
181 TV_TREE_LOOP
, /* tv_id */
182 PROP_cfg
, /* properties_required */
183 0, /* properties_provided */
184 0, /* properties_destroyed */
185 0, /* todo_flags_start */
186 0, /* todo_flags_finish */
189 class pass_oacc_kernels
: public gimple_opt_pass
192 pass_oacc_kernels (gcc::context
*ctxt
)
193 : gimple_opt_pass (pass_data_oacc_kernels
, ctxt
)
196 /* opt_pass methods: */
197 virtual bool gate (function
*fn
) { return gate_oacc_kernels (fn
); }
199 }; // class pass_oacc_kernels
204 make_pass_oacc_kernels (gcc::context
*ctxt
)
206 return new pass_oacc_kernels (ctxt
);
211 const pass_data pass_data_oacc_kernels2
=
213 GIMPLE_PASS
, /* type */
214 "oacc_kernels2", /* name */
215 OPTGROUP_LOOP
, /* optinfo_flags */
216 TV_TREE_LOOP
, /* tv_id */
217 PROP_cfg
, /* properties_required */
218 0, /* properties_provided */
219 0, /* properties_destroyed */
220 0, /* todo_flags_start */
221 0, /* todo_flags_finish */
224 class pass_oacc_kernels2
: public gimple_opt_pass
227 pass_oacc_kernels2 (gcc::context
*ctxt
)
228 : gimple_opt_pass (pass_data_oacc_kernels2
, ctxt
)
231 /* opt_pass methods: */
232 virtual bool gate (function
*fn
) { return gate_oacc_kernels (fn
); }
233 virtual unsigned int execute (function
*fn
)
235 /* Rather than having a copy of the previous dump, get some use out of
236 this dump, and try to minimize differences with the following pass
237 (pass_lim), which will initizalize the loop optimizer with
239 loop_optimizer_init (LOOPS_NORMAL
);
240 loop_optimizer_finalize (fn
);
244 }; // class pass_oacc_kernels2
249 make_pass_oacc_kernels2 (gcc::context
*ctxt
)
251 return new pass_oacc_kernels2 (ctxt
);
254 /* The no-loop superpass. */
258 const pass_data pass_data_tree_no_loop
=
260 GIMPLE_PASS
, /* type */
261 "no_loop", /* name */
262 OPTGROUP_NONE
, /* optinfo_flags */
263 TV_TREE_NOLOOP
, /* tv_id */
264 PROP_cfg
, /* properties_required */
265 0, /* properties_provided */
266 0, /* properties_destroyed */
267 0, /* todo_flags_start */
268 0, /* todo_flags_finish */
271 class pass_tree_no_loop
: public gimple_opt_pass
274 pass_tree_no_loop (gcc::context
*ctxt
)
275 : gimple_opt_pass (pass_data_tree_no_loop
, ctxt
)
278 /* opt_pass methods: */
279 virtual bool gate (function
*fn
) { return !gate_loop (fn
); }
281 }; // class pass_tree_no_loop
286 make_pass_tree_no_loop (gcc::context
*ctxt
)
288 return new pass_tree_no_loop (ctxt
);
292 /* Loop optimizer initialization. */
296 const pass_data pass_data_tree_loop_init
=
298 GIMPLE_PASS
, /* type */
299 "loopinit", /* name */
300 OPTGROUP_LOOP
, /* optinfo_flags */
302 PROP_cfg
, /* properties_required */
303 0, /* properties_provided */
304 0, /* properties_destroyed */
305 0, /* todo_flags_start */
306 0, /* todo_flags_finish */
309 class pass_tree_loop_init
: public gimple_opt_pass
312 pass_tree_loop_init (gcc::context
*ctxt
)
313 : gimple_opt_pass (pass_data_tree_loop_init
, ctxt
)
316 /* opt_pass methods: */
317 virtual unsigned int execute (function
*);
319 }; // class pass_tree_loop_init
322 pass_tree_loop_init::execute (function
*fun ATTRIBUTE_UNUSED
)
324 /* When processing a loop in the loop pipeline, we should be able to assert
326 (loops_state_satisfies_p (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS
328 && scev_initialized_p ())
330 loop_optimizer_init (LOOPS_NORMAL
331 | LOOPS_HAVE_RECORDED_EXITS
);
332 rewrite_into_loop_closed_ssa (NULL
, TODO_update_ssa
);
341 make_pass_tree_loop_init (gcc::context
*ctxt
)
343 return new pass_tree_loop_init (ctxt
);
346 /* Loop autovectorization. */
350 const pass_data pass_data_vectorize
=
352 GIMPLE_PASS
, /* type */
354 OPTGROUP_LOOP
| OPTGROUP_VEC
, /* optinfo_flags */
355 TV_TREE_VECTORIZATION
, /* tv_id */
356 ( PROP_cfg
| PROP_ssa
), /* properties_required */
357 0, /* properties_provided */
358 0, /* properties_destroyed */
359 0, /* todo_flags_start */
360 0, /* todo_flags_finish */
363 class pass_vectorize
: public gimple_opt_pass
366 pass_vectorize (gcc::context
*ctxt
)
367 : gimple_opt_pass (pass_data_vectorize
, ctxt
)
370 /* opt_pass methods: */
371 virtual bool gate (function
*fun
)
373 return flag_tree_loop_vectorize
|| fun
->has_force_vectorize_loops
;
376 virtual unsigned int execute (function
*);
378 }; // class pass_vectorize
381 pass_vectorize::execute (function
*fun
)
383 if (number_of_loops (fun
) <= 1)
386 return vectorize_loops ();
392 make_pass_vectorize (gcc::context
*ctxt
)
394 return new pass_vectorize (ctxt
);
397 /* Propagation of constants using scev. */
401 const pass_data pass_data_scev_cprop
=
403 GIMPLE_PASS
, /* type */
405 OPTGROUP_LOOP
, /* optinfo_flags */
406 TV_SCEV_CONST
, /* tv_id */
407 ( PROP_cfg
| PROP_ssa
), /* properties_required */
408 0, /* properties_provided */
409 0, /* properties_destroyed */
410 0, /* todo_flags_start */
412 | TODO_update_ssa_only_virtuals
), /* todo_flags_finish */
415 class pass_scev_cprop
: public gimple_opt_pass
418 pass_scev_cprop (gcc::context
*ctxt
)
419 : gimple_opt_pass (pass_data_scev_cprop
, ctxt
)
422 /* opt_pass methods: */
423 virtual bool gate (function
*) { return flag_tree_scev_cprop
; }
424 virtual unsigned int execute (function
*) { return scev_const_prop (); }
426 }; // class pass_scev_cprop
431 make_pass_scev_cprop (gcc::context
*ctxt
)
433 return new pass_scev_cprop (ctxt
);
436 /* Record bounds on numbers of iterations of loops. */
440 const pass_data pass_data_record_bounds
=
442 GIMPLE_PASS
, /* type */
443 "*record_bounds", /* name */
444 OPTGROUP_NONE
, /* optinfo_flags */
445 TV_TREE_LOOP_BOUNDS
, /* tv_id */
446 ( PROP_cfg
| PROP_ssa
), /* properties_required */
447 0, /* properties_provided */
448 0, /* properties_destroyed */
449 0, /* todo_flags_start */
450 0, /* todo_flags_finish */
453 class pass_record_bounds
: public gimple_opt_pass
456 pass_record_bounds (gcc::context
*ctxt
)
457 : gimple_opt_pass (pass_data_record_bounds
, ctxt
)
460 /* opt_pass methods: */
461 virtual unsigned int execute (function
*);
463 }; // class pass_record_bounds
466 pass_record_bounds::execute (function
*fun
)
468 if (number_of_loops (fun
) <= 1)
471 estimate_numbers_of_iterations ();
479 make_pass_record_bounds (gcc::context
*ctxt
)
481 return new pass_record_bounds (ctxt
);
484 /* Induction variable optimizations. */
488 const pass_data pass_data_iv_optimize
=
490 GIMPLE_PASS
, /* type */
492 OPTGROUP_LOOP
, /* optinfo_flags */
493 TV_TREE_LOOP_IVOPTS
, /* tv_id */
494 ( PROP_cfg
| PROP_ssa
), /* properties_required */
495 0, /* properties_provided */
496 0, /* properties_destroyed */
497 0, /* todo_flags_start */
498 TODO_update_ssa
, /* todo_flags_finish */
501 class pass_iv_optimize
: public gimple_opt_pass
504 pass_iv_optimize (gcc::context
*ctxt
)
505 : gimple_opt_pass (pass_data_iv_optimize
, ctxt
)
508 /* opt_pass methods: */
509 virtual bool gate (function
*) { return flag_ivopts
!= 0; }
510 virtual unsigned int execute (function
*);
512 }; // class pass_iv_optimize
515 pass_iv_optimize::execute (function
*fun
)
517 if (number_of_loops (fun
) <= 1)
520 tree_ssa_iv_optimize ();
527 make_pass_iv_optimize (gcc::context
*ctxt
)
529 return new pass_iv_optimize (ctxt
);
532 /* Loop optimizer finalization. */
535 tree_ssa_loop_done (void)
537 free_numbers_of_iterations_estimates (cfun
);
539 loop_optimizer_finalize ();
545 const pass_data pass_data_tree_loop_done
=
547 GIMPLE_PASS
, /* type */
548 "loopdone", /* name */
549 OPTGROUP_LOOP
, /* optinfo_flags */
551 PROP_cfg
, /* properties_required */
552 0, /* properties_provided */
553 0, /* properties_destroyed */
554 0, /* todo_flags_start */
555 TODO_cleanup_cfg
, /* todo_flags_finish */
558 class pass_tree_loop_done
: public gimple_opt_pass
561 pass_tree_loop_done (gcc::context
*ctxt
)
562 : gimple_opt_pass (pass_data_tree_loop_done
, ctxt
)
565 /* opt_pass methods: */
566 virtual unsigned int execute (function
*) { return tree_ssa_loop_done (); }
568 }; // class pass_tree_loop_done
573 make_pass_tree_loop_done (gcc::context
*ctxt
)
575 return new pass_tree_loop_done (ctxt
);
578 /* Calls CBCK for each index in memory reference ADDR_P. There are two
579 kinds situations handled; in each of these cases, the memory reference
580 and DATA are passed to the callback:
582 Access to an array: ARRAY_{RANGE_}REF (base, index). In this case we also
583 pass the pointer to the index to the callback.
585 Pointer dereference: INDIRECT_REF (addr). In this case we also pass the
586 pointer to addr to the callback.
588 If the callback returns false, the whole search stops and false is returned.
589 Otherwise the function returns true after traversing through the whole
590 reference *ADDR_P. */
593 for_each_index (tree
*addr_p
, bool (*cbck
) (tree
, tree
*, void *), void *data
)
597 for (; ; addr_p
= nxt
)
599 switch (TREE_CODE (*addr_p
))
602 return cbck (*addr_p
, addr_p
, data
);
605 nxt
= &TREE_OPERAND (*addr_p
, 0);
606 return cbck (*addr_p
, nxt
, data
);
609 case VIEW_CONVERT_EXPR
:
612 nxt
= &TREE_OPERAND (*addr_p
, 0);
616 /* If the component has varying offset, it behaves like index
618 idx
= &TREE_OPERAND (*addr_p
, 2);
620 && !cbck (*addr_p
, idx
, data
))
623 nxt
= &TREE_OPERAND (*addr_p
, 0);
627 case ARRAY_RANGE_REF
:
628 nxt
= &TREE_OPERAND (*addr_p
, 0);
629 if (!cbck (*addr_p
, &TREE_OPERAND (*addr_p
, 1), data
))
647 gcc_assert (is_gimple_min_invariant (*addr_p
));
651 idx
= &TMR_BASE (*addr_p
);
653 && !cbck (*addr_p
, idx
, data
))
655 idx
= &TMR_INDEX (*addr_p
);
657 && !cbck (*addr_p
, idx
, data
))
659 idx
= &TMR_INDEX2 (*addr_p
);
661 && !cbck (*addr_p
, idx
, data
))
672 /* The name and the length of the currently generated variable
674 #define MAX_LSM_NAME_LENGTH 40
675 static char lsm_tmp_name
[MAX_LSM_NAME_LENGTH
+ 1];
676 static int lsm_tmp_name_length
;
678 /* Adds S to lsm_tmp_name. */
681 lsm_tmp_name_add (const char *s
)
683 int l
= strlen (s
) + lsm_tmp_name_length
;
684 if (l
> MAX_LSM_NAME_LENGTH
)
687 strcpy (lsm_tmp_name
+ lsm_tmp_name_length
, s
);
688 lsm_tmp_name_length
= l
;
691 /* Stores the name for temporary variable that replaces REF to
695 gen_lsm_tmp_name (tree ref
)
699 switch (TREE_CODE (ref
))
703 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
704 lsm_tmp_name_add ("_");
708 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
712 case VIEW_CONVERT_EXPR
:
713 case ARRAY_RANGE_REF
:
714 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
718 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
719 lsm_tmp_name_add ("_RE");
723 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
724 lsm_tmp_name_add ("_IM");
728 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
729 lsm_tmp_name_add ("_");
730 name
= get_name (TREE_OPERAND (ref
, 1));
733 lsm_tmp_name_add (name
);
737 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
738 lsm_tmp_name_add ("_I");
744 name
= get_name (ref
);
747 lsm_tmp_name_add (name
);
751 lsm_tmp_name_add ("S");
755 lsm_tmp_name_add ("R");
767 /* Determines name for temporary variable that replaces REF.
768 The name is accumulated into the lsm_tmp_name variable.
769 N is added to the name of the temporary. */
772 get_lsm_tmp_name (tree ref
, unsigned n
, const char *suffix
)
776 lsm_tmp_name_length
= 0;
777 gen_lsm_tmp_name (ref
);
778 lsm_tmp_name_add ("_lsm");
783 lsm_tmp_name_add (ns
);
787 lsm_tmp_name_add (suffix
);
790 /* Computes an estimated number of insns in LOOP, weighted by WEIGHTS. */
793 tree_num_loop_insns (struct loop
*loop
, eni_weights
*weights
)
795 basic_block
*body
= get_loop_body (loop
);
796 gimple_stmt_iterator gsi
;
797 unsigned size
= 0, i
;
799 for (i
= 0; i
< loop
->num_nodes
; i
++)
800 for (gsi
= gsi_start_bb (body
[i
]); !gsi_end_p (gsi
); gsi_next (&gsi
))
801 size
+= estimate_num_insns (gsi_stmt (gsi
), weights
);