1 /* Loop optimizations over tree-ssa.
2 Copyright (C) 2003-2014 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"
27 #include "tree-ssa-alias.h"
28 #include "internal-fn.h"
29 #include "gimple-expr.h"
32 #include "gimple-iterator.h"
33 #include "tree-ssa-loop-ivopts.h"
34 #include "tree-ssa-loop-manip.h"
35 #include "tree-ssa-loop-niter.h"
36 #include "tree-ssa-loop.h"
37 #include "tree-pass.h"
40 #include "tree-inline.h"
41 #include "tree-scalar-evolution.h"
42 #include "diagnostic-core.h"
43 #include "tree-vectorizer.h"
45 /* The loop superpass. */
50 return flag_tree_loop_optimize
!= 0;
55 const pass_data pass_data_tree_loop
=
57 GIMPLE_PASS
, /* type */
59 OPTGROUP_LOOP
, /* optinfo_flags */
61 false, /* has_execute */
62 TV_TREE_LOOP
, /* tv_id */
63 PROP_cfg
, /* properties_required */
64 0, /* properties_provided */
65 0, /* properties_destroyed */
66 0, /* todo_flags_start */
67 TODO_verify_ssa
, /* todo_flags_finish */
70 class pass_tree_loop
: public gimple_opt_pass
73 pass_tree_loop (gcc::context
*ctxt
)
74 : gimple_opt_pass (pass_data_tree_loop
, ctxt
)
77 /* opt_pass methods: */
78 bool gate () { return gate_tree_loop (); }
80 }; // class pass_tree_loop
85 make_pass_tree_loop (gcc::context
*ctxt
)
87 return new pass_tree_loop (ctxt
);
90 /* Loop optimizer initialization. */
93 tree_ssa_loop_init (void)
95 loop_optimizer_init (LOOPS_NORMAL
96 | LOOPS_HAVE_RECORDED_EXITS
);
97 rewrite_into_loop_closed_ssa (NULL
, TODO_update_ssa
);
99 /* We might discover new loops, e.g. when turning irreducible
100 regions into reducible. */
103 if (number_of_loops (cfun
) <= 1)
111 const pass_data pass_data_tree_loop_init
=
113 GIMPLE_PASS
, /* type */
114 "loopinit", /* name */
115 OPTGROUP_LOOP
, /* optinfo_flags */
116 false, /* has_gate */
117 true, /* has_execute */
119 PROP_cfg
, /* properties_required */
120 0, /* properties_provided */
121 0, /* properties_destroyed */
122 0, /* todo_flags_start */
123 0, /* todo_flags_finish */
126 class pass_tree_loop_init
: public gimple_opt_pass
129 pass_tree_loop_init (gcc::context
*ctxt
)
130 : gimple_opt_pass (pass_data_tree_loop_init
, ctxt
)
133 /* opt_pass methods: */
134 unsigned int execute () { return tree_ssa_loop_init (); }
136 }; // class pass_tree_loop_init
141 make_pass_tree_loop_init (gcc::context
*ctxt
)
143 return new pass_tree_loop_init (ctxt
);
146 /* Loop autovectorization. */
149 tree_loop_vectorize (void)
151 if (number_of_loops (cfun
) <= 1)
154 return vectorize_loops ();
158 gate_tree_loop_vectorize (void)
160 return flag_tree_loop_vectorize
|| cfun
->has_force_vect_loops
;
165 const pass_data pass_data_vectorize
=
167 GIMPLE_PASS
, /* type */
169 OPTGROUP_LOOP
| OPTGROUP_VEC
, /* optinfo_flags */
171 true, /* has_execute */
172 TV_TREE_VECTORIZATION
, /* tv_id */
173 ( PROP_cfg
| PROP_ssa
), /* properties_required */
174 0, /* properties_provided */
175 0, /* properties_destroyed */
176 0, /* todo_flags_start */
177 0, /* todo_flags_finish */
180 class pass_vectorize
: public gimple_opt_pass
183 pass_vectorize (gcc::context
*ctxt
)
184 : gimple_opt_pass (pass_data_vectorize
, ctxt
)
187 /* opt_pass methods: */
188 bool gate () { return gate_tree_loop_vectorize (); }
189 unsigned int execute () { return tree_loop_vectorize (); }
191 }; // class pass_vectorize
196 make_pass_vectorize (gcc::context
*ctxt
)
198 return new pass_vectorize (ctxt
);
201 /* Check the correctness of the data dependence analyzers. */
204 check_data_deps (void)
206 if (number_of_loops (cfun
) <= 1)
209 tree_check_data_deps ();
214 gate_check_data_deps (void)
216 return flag_check_data_deps
!= 0;
221 const pass_data pass_data_check_data_deps
=
223 GIMPLE_PASS
, /* type */
225 OPTGROUP_LOOP
, /* optinfo_flags */
227 true, /* has_execute */
228 TV_CHECK_DATA_DEPS
, /* tv_id */
229 ( PROP_cfg
| PROP_ssa
), /* properties_required */
230 0, /* properties_provided */
231 0, /* properties_destroyed */
232 0, /* todo_flags_start */
233 0, /* todo_flags_finish */
236 class pass_check_data_deps
: public gimple_opt_pass
239 pass_check_data_deps (gcc::context
*ctxt
)
240 : gimple_opt_pass (pass_data_check_data_deps
, ctxt
)
243 /* opt_pass methods: */
244 bool gate () { return gate_check_data_deps (); }
245 unsigned int execute () { return check_data_deps (); }
247 }; // class pass_check_data_deps
252 make_pass_check_data_deps (gcc::context
*ctxt
)
254 return new pass_check_data_deps (ctxt
);
257 /* Propagation of constants using scev. */
260 gate_scev_const_prop (void)
262 return flag_tree_scev_cprop
;
267 const pass_data pass_data_scev_cprop
=
269 GIMPLE_PASS
, /* type */
271 OPTGROUP_LOOP
, /* optinfo_flags */
273 true, /* has_execute */
274 TV_SCEV_CONST
, /* tv_id */
275 ( PROP_cfg
| PROP_ssa
), /* properties_required */
276 0, /* properties_provided */
277 0, /* properties_destroyed */
278 0, /* todo_flags_start */
280 | TODO_update_ssa_only_virtuals
), /* todo_flags_finish */
283 class pass_scev_cprop
: public gimple_opt_pass
286 pass_scev_cprop (gcc::context
*ctxt
)
287 : gimple_opt_pass (pass_data_scev_cprop
, ctxt
)
290 /* opt_pass methods: */
291 bool gate () { return gate_scev_const_prop (); }
292 unsigned int execute () { return scev_const_prop (); }
294 }; // class pass_scev_cprop
299 make_pass_scev_cprop (gcc::context
*ctxt
)
301 return new pass_scev_cprop (ctxt
);
304 /* Record bounds on numbers of iterations of loops. */
307 tree_ssa_loop_bounds (void)
309 if (number_of_loops (cfun
) <= 1)
312 estimate_numbers_of_iterations ();
319 const pass_data pass_data_record_bounds
=
321 GIMPLE_PASS
, /* type */
322 "*record_bounds", /* name */
323 OPTGROUP_NONE
, /* optinfo_flags */
324 false, /* has_gate */
325 true, /* has_execute */
326 TV_TREE_LOOP_BOUNDS
, /* tv_id */
327 ( PROP_cfg
| PROP_ssa
), /* properties_required */
328 0, /* properties_provided */
329 0, /* properties_destroyed */
330 0, /* todo_flags_start */
331 0, /* todo_flags_finish */
334 class pass_record_bounds
: public gimple_opt_pass
337 pass_record_bounds (gcc::context
*ctxt
)
338 : gimple_opt_pass (pass_data_record_bounds
, ctxt
)
341 /* opt_pass methods: */
342 unsigned int execute () { return tree_ssa_loop_bounds (); }
344 }; // class pass_record_bounds
349 make_pass_record_bounds (gcc::context
*ctxt
)
351 return new pass_record_bounds (ctxt
);
354 /* Induction variable optimizations. */
357 tree_ssa_loop_ivopts (void)
359 if (number_of_loops (cfun
) <= 1)
362 tree_ssa_iv_optimize ();
367 gate_tree_ssa_loop_ivopts (void)
369 return flag_ivopts
!= 0;
374 const pass_data pass_data_iv_optimize
=
376 GIMPLE_PASS
, /* type */
378 OPTGROUP_LOOP
, /* optinfo_flags */
380 true, /* has_execute */
381 TV_TREE_LOOP_IVOPTS
, /* tv_id */
382 ( PROP_cfg
| PROP_ssa
), /* properties_required */
383 0, /* properties_provided */
384 0, /* properties_destroyed */
385 0, /* todo_flags_start */
386 TODO_update_ssa
, /* todo_flags_finish */
389 class pass_iv_optimize
: public gimple_opt_pass
392 pass_iv_optimize (gcc::context
*ctxt
)
393 : gimple_opt_pass (pass_data_iv_optimize
, ctxt
)
396 /* opt_pass methods: */
397 bool gate () { return gate_tree_ssa_loop_ivopts (); }
398 unsigned int execute () { return tree_ssa_loop_ivopts (); }
400 }; // class pass_iv_optimize
405 make_pass_iv_optimize (gcc::context
*ctxt
)
407 return new pass_iv_optimize (ctxt
);
410 /* Loop optimizer finalization. */
413 tree_ssa_loop_done (void)
415 free_numbers_of_iterations_estimates ();
417 loop_optimizer_finalize ();
423 const pass_data pass_data_tree_loop_done
=
425 GIMPLE_PASS
, /* type */
426 "loopdone", /* name */
427 OPTGROUP_LOOP
, /* optinfo_flags */
428 false, /* has_gate */
429 true, /* has_execute */
431 PROP_cfg
, /* properties_required */
432 0, /* properties_provided */
433 0, /* properties_destroyed */
434 0, /* todo_flags_start */
435 ( TODO_cleanup_cfg
| TODO_verify_flow
), /* todo_flags_finish */
438 class pass_tree_loop_done
: public gimple_opt_pass
441 pass_tree_loop_done (gcc::context
*ctxt
)
442 : gimple_opt_pass (pass_data_tree_loop_done
, ctxt
)
445 /* opt_pass methods: */
446 unsigned int execute () { return tree_ssa_loop_done (); }
448 }; // class pass_tree_loop_done
453 make_pass_tree_loop_done (gcc::context
*ctxt
)
455 return new pass_tree_loop_done (ctxt
);
458 /* Calls CBCK for each index in memory reference ADDR_P. There are two
459 kinds situations handled; in each of these cases, the memory reference
460 and DATA are passed to the callback:
462 Access to an array: ARRAY_{RANGE_}REF (base, index). In this case we also
463 pass the pointer to the index to the callback.
465 Pointer dereference: INDIRECT_REF (addr). In this case we also pass the
466 pointer to addr to the callback.
468 If the callback returns false, the whole search stops and false is returned.
469 Otherwise the function returns true after traversing through the whole
470 reference *ADDR_P. */
473 for_each_index (tree
*addr_p
, bool (*cbck
) (tree
, tree
*, void *), void *data
)
477 for (; ; addr_p
= nxt
)
479 switch (TREE_CODE (*addr_p
))
482 return cbck (*addr_p
, addr_p
, data
);
485 nxt
= &TREE_OPERAND (*addr_p
, 0);
486 return cbck (*addr_p
, nxt
, data
);
489 case VIEW_CONVERT_EXPR
:
492 nxt
= &TREE_OPERAND (*addr_p
, 0);
496 /* If the component has varying offset, it behaves like index
498 idx
= &TREE_OPERAND (*addr_p
, 2);
500 && !cbck (*addr_p
, idx
, data
))
503 nxt
= &TREE_OPERAND (*addr_p
, 0);
507 case ARRAY_RANGE_REF
:
508 nxt
= &TREE_OPERAND (*addr_p
, 0);
509 if (!cbck (*addr_p
, &TREE_OPERAND (*addr_p
, 1), data
))
527 gcc_assert (is_gimple_min_invariant (*addr_p
));
531 idx
= &TMR_BASE (*addr_p
);
533 && !cbck (*addr_p
, idx
, data
))
535 idx
= &TMR_INDEX (*addr_p
);
537 && !cbck (*addr_p
, idx
, data
))
539 idx
= &TMR_INDEX2 (*addr_p
);
541 && !cbck (*addr_p
, idx
, data
))
552 /* The name and the length of the currently generated variable
554 #define MAX_LSM_NAME_LENGTH 40
555 static char lsm_tmp_name
[MAX_LSM_NAME_LENGTH
+ 1];
556 static int lsm_tmp_name_length
;
558 /* Adds S to lsm_tmp_name. */
561 lsm_tmp_name_add (const char *s
)
563 int l
= strlen (s
) + lsm_tmp_name_length
;
564 if (l
> MAX_LSM_NAME_LENGTH
)
567 strcpy (lsm_tmp_name
+ lsm_tmp_name_length
, s
);
568 lsm_tmp_name_length
= l
;
571 /* Stores the name for temporary variable that replaces REF to
575 gen_lsm_tmp_name (tree ref
)
579 switch (TREE_CODE (ref
))
583 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
584 lsm_tmp_name_add ("_");
588 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
592 case VIEW_CONVERT_EXPR
:
593 case ARRAY_RANGE_REF
:
594 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
598 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
599 lsm_tmp_name_add ("_RE");
603 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
604 lsm_tmp_name_add ("_IM");
608 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
609 lsm_tmp_name_add ("_");
610 name
= get_name (TREE_OPERAND (ref
, 1));
613 lsm_tmp_name_add (name
);
617 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
618 lsm_tmp_name_add ("_I");
624 name
= get_name (ref
);
627 lsm_tmp_name_add (name
);
631 lsm_tmp_name_add ("S");
635 lsm_tmp_name_add ("R");
647 /* Determines name for temporary variable that replaces REF.
648 The name is accumulated into the lsm_tmp_name variable.
649 N is added to the name of the temporary. */
652 get_lsm_tmp_name (tree ref
, unsigned n
, const char *suffix
)
656 lsm_tmp_name_length
= 0;
657 gen_lsm_tmp_name (ref
);
658 lsm_tmp_name_add ("_lsm");
663 lsm_tmp_name_add (ns
);
667 lsm_tmp_name_add (suffix
);
670 /* Computes an estimated number of insns in LOOP, weighted by WEIGHTS. */
673 tree_num_loop_insns (struct loop
*loop
, eni_weights
*weights
)
675 basic_block
*body
= get_loop_body (loop
);
676 gimple_stmt_iterator gsi
;
677 unsigned size
= 0, i
;
679 for (i
= 0; i
< loop
->num_nodes
; i
++)
680 for (gsi
= gsi_start_bb (body
[i
]); !gsi_end_p (gsi
); gsi_next (&gsi
))
681 size
+= estimate_num_insns (gsi_stmt (gsi
), weights
);