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 "gimple-iterator.h"
29 #include "tree-ssa-loop-ivopts.h"
30 #include "tree-ssa-loop-manip.h"
31 #include "tree-ssa-loop-niter.h"
32 #include "tree-ssa-loop.h"
33 #include "tree-pass.h"
36 #include "tree-inline.h"
37 #include "tree-scalar-evolution.h"
38 #include "diagnostic-core.h"
39 #include "tree-vectorizer.h"
41 /* The loop superpass. */
46 return flag_tree_loop_optimize
!= 0;
51 const pass_data pass_data_tree_loop
=
53 GIMPLE_PASS
, /* type */
55 OPTGROUP_LOOP
, /* optinfo_flags */
57 false, /* has_execute */
58 TV_TREE_LOOP
, /* tv_id */
59 PROP_cfg
, /* properties_required */
60 0, /* properties_provided */
61 0, /* properties_destroyed */
62 0, /* todo_flags_start */
63 TODO_verify_ssa
, /* todo_flags_finish */
66 class pass_tree_loop
: public gimple_opt_pass
69 pass_tree_loop (gcc::context
*ctxt
)
70 : gimple_opt_pass (pass_data_tree_loop
, ctxt
)
73 /* opt_pass methods: */
74 bool gate () { return gate_tree_loop (); }
76 }; // class pass_tree_loop
81 make_pass_tree_loop (gcc::context
*ctxt
)
83 return new pass_tree_loop (ctxt
);
86 /* Loop optimizer initialization. */
89 tree_ssa_loop_init (void)
91 loop_optimizer_init (LOOPS_NORMAL
92 | LOOPS_HAVE_RECORDED_EXITS
);
93 rewrite_into_loop_closed_ssa (NULL
, TODO_update_ssa
);
95 /* We might discover new loops, e.g. when turning irreducible
96 regions into reducible. */
99 if (number_of_loops (cfun
) <= 1)
107 const pass_data pass_data_tree_loop_init
=
109 GIMPLE_PASS
, /* type */
110 "loopinit", /* name */
111 OPTGROUP_LOOP
, /* optinfo_flags */
112 false, /* has_gate */
113 true, /* has_execute */
115 PROP_cfg
, /* properties_required */
116 0, /* properties_provided */
117 0, /* properties_destroyed */
118 0, /* todo_flags_start */
119 0, /* todo_flags_finish */
122 class pass_tree_loop_init
: public gimple_opt_pass
125 pass_tree_loop_init (gcc::context
*ctxt
)
126 : gimple_opt_pass (pass_data_tree_loop_init
, ctxt
)
129 /* opt_pass methods: */
130 unsigned int execute () { return tree_ssa_loop_init (); }
132 }; // class pass_tree_loop_init
137 make_pass_tree_loop_init (gcc::context
*ctxt
)
139 return new pass_tree_loop_init (ctxt
);
142 /* Loop autovectorization. */
145 tree_loop_vectorize (void)
147 if (number_of_loops (cfun
) <= 1)
150 return vectorize_loops ();
154 gate_tree_loop_vectorize (void)
156 return flag_tree_loop_vectorize
|| cfun
->has_force_vect_loops
;
161 const pass_data pass_data_vectorize
=
163 GIMPLE_PASS
, /* type */
165 OPTGROUP_LOOP
| OPTGROUP_VEC
, /* optinfo_flags */
167 true, /* has_execute */
168 TV_TREE_VECTORIZATION
, /* tv_id */
169 ( PROP_cfg
| PROP_ssa
), /* properties_required */
170 0, /* properties_provided */
171 0, /* properties_destroyed */
172 0, /* todo_flags_start */
173 0, /* todo_flags_finish */
176 class pass_vectorize
: public gimple_opt_pass
179 pass_vectorize (gcc::context
*ctxt
)
180 : gimple_opt_pass (pass_data_vectorize
, ctxt
)
183 /* opt_pass methods: */
184 bool gate () { return gate_tree_loop_vectorize (); }
185 unsigned int execute () { return tree_loop_vectorize (); }
187 }; // class pass_vectorize
192 make_pass_vectorize (gcc::context
*ctxt
)
194 return new pass_vectorize (ctxt
);
197 /* Check the correctness of the data dependence analyzers. */
200 check_data_deps (void)
202 if (number_of_loops (cfun
) <= 1)
205 tree_check_data_deps ();
210 gate_check_data_deps (void)
212 return flag_check_data_deps
!= 0;
217 const pass_data pass_data_check_data_deps
=
219 GIMPLE_PASS
, /* type */
221 OPTGROUP_LOOP
, /* optinfo_flags */
223 true, /* has_execute */
224 TV_CHECK_DATA_DEPS
, /* tv_id */
225 ( PROP_cfg
| PROP_ssa
), /* properties_required */
226 0, /* properties_provided */
227 0, /* properties_destroyed */
228 0, /* todo_flags_start */
229 0, /* todo_flags_finish */
232 class pass_check_data_deps
: public gimple_opt_pass
235 pass_check_data_deps (gcc::context
*ctxt
)
236 : gimple_opt_pass (pass_data_check_data_deps
, ctxt
)
239 /* opt_pass methods: */
240 bool gate () { return gate_check_data_deps (); }
241 unsigned int execute () { return check_data_deps (); }
243 }; // class pass_check_data_deps
248 make_pass_check_data_deps (gcc::context
*ctxt
)
250 return new pass_check_data_deps (ctxt
);
253 /* Propagation of constants using scev. */
256 gate_scev_const_prop (void)
258 return flag_tree_scev_cprop
;
263 const pass_data pass_data_scev_cprop
=
265 GIMPLE_PASS
, /* type */
267 OPTGROUP_LOOP
, /* optinfo_flags */
269 true, /* has_execute */
270 TV_SCEV_CONST
, /* tv_id */
271 ( PROP_cfg
| PROP_ssa
), /* properties_required */
272 0, /* properties_provided */
273 0, /* properties_destroyed */
274 0, /* todo_flags_start */
276 | TODO_update_ssa_only_virtuals
), /* todo_flags_finish */
279 class pass_scev_cprop
: public gimple_opt_pass
282 pass_scev_cprop (gcc::context
*ctxt
)
283 : gimple_opt_pass (pass_data_scev_cprop
, ctxt
)
286 /* opt_pass methods: */
287 bool gate () { return gate_scev_const_prop (); }
288 unsigned int execute () { return scev_const_prop (); }
290 }; // class pass_scev_cprop
295 make_pass_scev_cprop (gcc::context
*ctxt
)
297 return new pass_scev_cprop (ctxt
);
300 /* Record bounds on numbers of iterations of loops. */
303 tree_ssa_loop_bounds (void)
305 if (number_of_loops (cfun
) <= 1)
308 estimate_numbers_of_iterations ();
315 const pass_data pass_data_record_bounds
=
317 GIMPLE_PASS
, /* type */
318 "*record_bounds", /* name */
319 OPTGROUP_NONE
, /* optinfo_flags */
320 false, /* has_gate */
321 true, /* has_execute */
322 TV_TREE_LOOP_BOUNDS
, /* tv_id */
323 ( PROP_cfg
| PROP_ssa
), /* properties_required */
324 0, /* properties_provided */
325 0, /* properties_destroyed */
326 0, /* todo_flags_start */
327 0, /* todo_flags_finish */
330 class pass_record_bounds
: public gimple_opt_pass
333 pass_record_bounds (gcc::context
*ctxt
)
334 : gimple_opt_pass (pass_data_record_bounds
, ctxt
)
337 /* opt_pass methods: */
338 unsigned int execute () { return tree_ssa_loop_bounds (); }
340 }; // class pass_record_bounds
345 make_pass_record_bounds (gcc::context
*ctxt
)
347 return new pass_record_bounds (ctxt
);
350 /* Induction variable optimizations. */
353 tree_ssa_loop_ivopts (void)
355 if (number_of_loops (cfun
) <= 1)
358 tree_ssa_iv_optimize ();
363 gate_tree_ssa_loop_ivopts (void)
365 return flag_ivopts
!= 0;
370 const pass_data pass_data_iv_optimize
=
372 GIMPLE_PASS
, /* type */
374 OPTGROUP_LOOP
, /* optinfo_flags */
376 true, /* has_execute */
377 TV_TREE_LOOP_IVOPTS
, /* tv_id */
378 ( PROP_cfg
| PROP_ssa
), /* properties_required */
379 0, /* properties_provided */
380 0, /* properties_destroyed */
381 0, /* todo_flags_start */
382 TODO_update_ssa
, /* todo_flags_finish */
385 class pass_iv_optimize
: public gimple_opt_pass
388 pass_iv_optimize (gcc::context
*ctxt
)
389 : gimple_opt_pass (pass_data_iv_optimize
, ctxt
)
392 /* opt_pass methods: */
393 bool gate () { return gate_tree_ssa_loop_ivopts (); }
394 unsigned int execute () { return tree_ssa_loop_ivopts (); }
396 }; // class pass_iv_optimize
401 make_pass_iv_optimize (gcc::context
*ctxt
)
403 return new pass_iv_optimize (ctxt
);
406 /* Loop optimizer finalization. */
409 tree_ssa_loop_done (void)
411 free_numbers_of_iterations_estimates ();
413 loop_optimizer_finalize ();
419 const pass_data pass_data_tree_loop_done
=
421 GIMPLE_PASS
, /* type */
422 "loopdone", /* name */
423 OPTGROUP_LOOP
, /* optinfo_flags */
424 false, /* has_gate */
425 true, /* has_execute */
427 PROP_cfg
, /* properties_required */
428 0, /* properties_provided */
429 0, /* properties_destroyed */
430 0, /* todo_flags_start */
431 ( TODO_cleanup_cfg
| TODO_verify_flow
), /* todo_flags_finish */
434 class pass_tree_loop_done
: public gimple_opt_pass
437 pass_tree_loop_done (gcc::context
*ctxt
)
438 : gimple_opt_pass (pass_data_tree_loop_done
, ctxt
)
441 /* opt_pass methods: */
442 unsigned int execute () { return tree_ssa_loop_done (); }
444 }; // class pass_tree_loop_done
449 make_pass_tree_loop_done (gcc::context
*ctxt
)
451 return new pass_tree_loop_done (ctxt
);
454 /* Calls CBCK for each index in memory reference ADDR_P. There are two
455 kinds situations handled; in each of these cases, the memory reference
456 and DATA are passed to the callback:
458 Access to an array: ARRAY_{RANGE_}REF (base, index). In this case we also
459 pass the pointer to the index to the callback.
461 Pointer dereference: INDIRECT_REF (addr). In this case we also pass the
462 pointer to addr to the callback.
464 If the callback returns false, the whole search stops and false is returned.
465 Otherwise the function returns true after traversing through the whole
466 reference *ADDR_P. */
469 for_each_index (tree
*addr_p
, bool (*cbck
) (tree
, tree
*, void *), void *data
)
473 for (; ; addr_p
= nxt
)
475 switch (TREE_CODE (*addr_p
))
478 return cbck (*addr_p
, addr_p
, data
);
481 nxt
= &TREE_OPERAND (*addr_p
, 0);
482 return cbck (*addr_p
, nxt
, data
);
485 case VIEW_CONVERT_EXPR
:
488 nxt
= &TREE_OPERAND (*addr_p
, 0);
492 /* If the component has varying offset, it behaves like index
494 idx
= &TREE_OPERAND (*addr_p
, 2);
496 && !cbck (*addr_p
, idx
, data
))
499 nxt
= &TREE_OPERAND (*addr_p
, 0);
503 case ARRAY_RANGE_REF
:
504 nxt
= &TREE_OPERAND (*addr_p
, 0);
505 if (!cbck (*addr_p
, &TREE_OPERAND (*addr_p
, 1), data
))
523 gcc_assert (is_gimple_min_invariant (*addr_p
));
527 idx
= &TMR_BASE (*addr_p
);
529 && !cbck (*addr_p
, idx
, data
))
531 idx
= &TMR_INDEX (*addr_p
);
533 && !cbck (*addr_p
, idx
, data
))
535 idx
= &TMR_INDEX2 (*addr_p
);
537 && !cbck (*addr_p
, idx
, data
))
548 /* The name and the length of the currently generated variable
550 #define MAX_LSM_NAME_LENGTH 40
551 static char lsm_tmp_name
[MAX_LSM_NAME_LENGTH
+ 1];
552 static int lsm_tmp_name_length
;
554 /* Adds S to lsm_tmp_name. */
557 lsm_tmp_name_add (const char *s
)
559 int l
= strlen (s
) + lsm_tmp_name_length
;
560 if (l
> MAX_LSM_NAME_LENGTH
)
563 strcpy (lsm_tmp_name
+ lsm_tmp_name_length
, s
);
564 lsm_tmp_name_length
= l
;
567 /* Stores the name for temporary variable that replaces REF to
571 gen_lsm_tmp_name (tree ref
)
575 switch (TREE_CODE (ref
))
579 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
580 lsm_tmp_name_add ("_");
584 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
588 case VIEW_CONVERT_EXPR
:
589 case ARRAY_RANGE_REF
:
590 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
594 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
595 lsm_tmp_name_add ("_RE");
599 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
600 lsm_tmp_name_add ("_IM");
604 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
605 lsm_tmp_name_add ("_");
606 name
= get_name (TREE_OPERAND (ref
, 1));
609 lsm_tmp_name_add (name
);
613 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
614 lsm_tmp_name_add ("_I");
620 name
= get_name (ref
);
623 lsm_tmp_name_add (name
);
627 lsm_tmp_name_add ("S");
631 lsm_tmp_name_add ("R");
643 /* Determines name for temporary variable that replaces REF.
644 The name is accumulated into the lsm_tmp_name variable.
645 N is added to the name of the temporary. */
648 get_lsm_tmp_name (tree ref
, unsigned n
, const char *suffix
)
652 lsm_tmp_name_length
= 0;
653 gen_lsm_tmp_name (ref
);
654 lsm_tmp_name_add ("_lsm");
659 lsm_tmp_name_add (ns
);
663 lsm_tmp_name_add (suffix
);
666 /* Computes an estimated number of insns in LOOP, weighted by WEIGHTS. */
669 tree_num_loop_insns (struct loop
*loop
, eni_weights
*weights
)
671 basic_block
*body
= get_loop_body (loop
);
672 gimple_stmt_iterator gsi
;
673 unsigned size
= 0, i
;
675 for (i
= 0; i
< loop
->num_nodes
; i
++)
676 for (gsi
= gsi_start_bb (body
[i
]); !gsi_end_p (gsi
); gsi_next (&gsi
))
677 size
+= estimate_num_insns (gsi_stmt (gsi
), weights
);