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 autovectorization. */
140 tree_loop_vectorize (void)
142 if (number_of_loops (cfun
) <= 1)
145 return vectorize_loops ();
149 gate_tree_loop_vectorize (void)
151 return flag_tree_loop_vectorize
|| cfun
->has_force_vect_loops
;
156 const pass_data pass_data_vectorize
=
158 GIMPLE_PASS
, /* type */
160 OPTGROUP_LOOP
| OPTGROUP_VEC
, /* optinfo_flags */
162 true, /* has_execute */
163 TV_TREE_VECTORIZATION
, /* tv_id */
164 ( PROP_cfg
| PROP_ssa
), /* properties_required */
165 0, /* properties_provided */
166 0, /* properties_destroyed */
167 0, /* todo_flags_start */
168 0, /* todo_flags_finish */
171 class pass_vectorize
: public gimple_opt_pass
174 pass_vectorize (gcc::context
*ctxt
)
175 : gimple_opt_pass (pass_data_vectorize
, ctxt
)
178 /* opt_pass methods: */
179 bool gate () { return gate_tree_loop_vectorize (); }
180 unsigned int execute () { return tree_loop_vectorize (); }
182 }; // class pass_vectorize
187 make_pass_vectorize (gcc::context
*ctxt
)
189 return new pass_vectorize (ctxt
);
192 /* Check the correctness of the data dependence analyzers. */
195 check_data_deps (void)
197 if (number_of_loops (cfun
) <= 1)
200 tree_check_data_deps ();
205 gate_check_data_deps (void)
207 return flag_check_data_deps
!= 0;
212 const pass_data pass_data_check_data_deps
=
214 GIMPLE_PASS
, /* type */
216 OPTGROUP_LOOP
, /* optinfo_flags */
218 true, /* has_execute */
219 TV_CHECK_DATA_DEPS
, /* tv_id */
220 ( PROP_cfg
| PROP_ssa
), /* properties_required */
221 0, /* properties_provided */
222 0, /* properties_destroyed */
223 0, /* todo_flags_start */
224 0, /* todo_flags_finish */
227 class pass_check_data_deps
: public gimple_opt_pass
230 pass_check_data_deps (gcc::context
*ctxt
)
231 : gimple_opt_pass (pass_data_check_data_deps
, ctxt
)
234 /* opt_pass methods: */
235 bool gate () { return gate_check_data_deps (); }
236 unsigned int execute () { return check_data_deps (); }
238 }; // class pass_check_data_deps
243 make_pass_check_data_deps (gcc::context
*ctxt
)
245 return new pass_check_data_deps (ctxt
);
248 /* Propagation of constants using scev. */
251 gate_scev_const_prop (void)
253 return flag_tree_scev_cprop
;
258 const pass_data pass_data_scev_cprop
=
260 GIMPLE_PASS
, /* type */
262 OPTGROUP_LOOP
, /* optinfo_flags */
264 true, /* has_execute */
265 TV_SCEV_CONST
, /* tv_id */
266 ( PROP_cfg
| PROP_ssa
), /* properties_required */
267 0, /* properties_provided */
268 0, /* properties_destroyed */
269 0, /* todo_flags_start */
271 | TODO_update_ssa_only_virtuals
), /* todo_flags_finish */
274 class pass_scev_cprop
: public gimple_opt_pass
277 pass_scev_cprop (gcc::context
*ctxt
)
278 : gimple_opt_pass (pass_data_scev_cprop
, ctxt
)
281 /* opt_pass methods: */
282 bool gate () { return gate_scev_const_prop (); }
283 unsigned int execute () { return scev_const_prop (); }
285 }; // class pass_scev_cprop
290 make_pass_scev_cprop (gcc::context
*ctxt
)
292 return new pass_scev_cprop (ctxt
);
295 /* Record bounds on numbers of iterations of loops. */
298 tree_ssa_loop_bounds (void)
300 if (number_of_loops (cfun
) <= 1)
303 estimate_numbers_of_iterations ();
310 const pass_data pass_data_record_bounds
=
312 GIMPLE_PASS
, /* type */
313 "*record_bounds", /* name */
314 OPTGROUP_NONE
, /* optinfo_flags */
315 false, /* has_gate */
316 true, /* has_execute */
317 TV_TREE_LOOP_BOUNDS
, /* tv_id */
318 ( PROP_cfg
| PROP_ssa
), /* properties_required */
319 0, /* properties_provided */
320 0, /* properties_destroyed */
321 0, /* todo_flags_start */
322 0, /* todo_flags_finish */
325 class pass_record_bounds
: public gimple_opt_pass
328 pass_record_bounds (gcc::context
*ctxt
)
329 : gimple_opt_pass (pass_data_record_bounds
, ctxt
)
332 /* opt_pass methods: */
333 unsigned int execute () { return tree_ssa_loop_bounds (); }
335 }; // class pass_record_bounds
340 make_pass_record_bounds (gcc::context
*ctxt
)
342 return new pass_record_bounds (ctxt
);
345 /* Induction variable optimizations. */
348 tree_ssa_loop_ivopts (void)
350 if (number_of_loops (cfun
) <= 1)
353 tree_ssa_iv_optimize ();
358 gate_tree_ssa_loop_ivopts (void)
360 return flag_ivopts
!= 0;
365 const pass_data pass_data_iv_optimize
=
367 GIMPLE_PASS
, /* type */
369 OPTGROUP_LOOP
, /* optinfo_flags */
371 true, /* has_execute */
372 TV_TREE_LOOP_IVOPTS
, /* tv_id */
373 ( PROP_cfg
| PROP_ssa
), /* properties_required */
374 0, /* properties_provided */
375 0, /* properties_destroyed */
376 0, /* todo_flags_start */
377 TODO_update_ssa
, /* todo_flags_finish */
380 class pass_iv_optimize
: public gimple_opt_pass
383 pass_iv_optimize (gcc::context
*ctxt
)
384 : gimple_opt_pass (pass_data_iv_optimize
, ctxt
)
387 /* opt_pass methods: */
388 bool gate () { return gate_tree_ssa_loop_ivopts (); }
389 unsigned int execute () { return tree_ssa_loop_ivopts (); }
391 }; // class pass_iv_optimize
396 make_pass_iv_optimize (gcc::context
*ctxt
)
398 return new pass_iv_optimize (ctxt
);
401 /* Loop optimizer finalization. */
404 tree_ssa_loop_done (void)
406 free_numbers_of_iterations_estimates ();
408 loop_optimizer_finalize ();
414 const pass_data pass_data_tree_loop_done
=
416 GIMPLE_PASS
, /* type */
417 "loopdone", /* name */
418 OPTGROUP_LOOP
, /* optinfo_flags */
419 false, /* has_gate */
420 true, /* has_execute */
422 PROP_cfg
, /* properties_required */
423 0, /* properties_provided */
424 0, /* properties_destroyed */
425 0, /* todo_flags_start */
426 ( TODO_cleanup_cfg
| TODO_verify_flow
), /* todo_flags_finish */
429 class pass_tree_loop_done
: public gimple_opt_pass
432 pass_tree_loop_done (gcc::context
*ctxt
)
433 : gimple_opt_pass (pass_data_tree_loop_done
, ctxt
)
436 /* opt_pass methods: */
437 unsigned int execute () { return tree_ssa_loop_done (); }
439 }; // class pass_tree_loop_done
444 make_pass_tree_loop_done (gcc::context
*ctxt
)
446 return new pass_tree_loop_done (ctxt
);
449 /* Calls CBCK for each index in memory reference ADDR_P. There are two
450 kinds situations handled; in each of these cases, the memory reference
451 and DATA are passed to the callback:
453 Access to an array: ARRAY_{RANGE_}REF (base, index). In this case we also
454 pass the pointer to the index to the callback.
456 Pointer dereference: INDIRECT_REF (addr). In this case we also pass the
457 pointer to addr to the callback.
459 If the callback returns false, the whole search stops and false is returned.
460 Otherwise the function returns true after traversing through the whole
461 reference *ADDR_P. */
464 for_each_index (tree
*addr_p
, bool (*cbck
) (tree
, tree
*, void *), void *data
)
468 for (; ; addr_p
= nxt
)
470 switch (TREE_CODE (*addr_p
))
473 return cbck (*addr_p
, addr_p
, data
);
476 nxt
= &TREE_OPERAND (*addr_p
, 0);
477 return cbck (*addr_p
, nxt
, data
);
480 case VIEW_CONVERT_EXPR
:
483 nxt
= &TREE_OPERAND (*addr_p
, 0);
487 /* If the component has varying offset, it behaves like index
489 idx
= &TREE_OPERAND (*addr_p
, 2);
491 && !cbck (*addr_p
, idx
, data
))
494 nxt
= &TREE_OPERAND (*addr_p
, 0);
498 case ARRAY_RANGE_REF
:
499 nxt
= &TREE_OPERAND (*addr_p
, 0);
500 if (!cbck (*addr_p
, &TREE_OPERAND (*addr_p
, 1), data
))
518 gcc_assert (is_gimple_min_invariant (*addr_p
));
522 idx
= &TMR_BASE (*addr_p
);
524 && !cbck (*addr_p
, idx
, data
))
526 idx
= &TMR_INDEX (*addr_p
);
528 && !cbck (*addr_p
, idx
, data
))
530 idx
= &TMR_INDEX2 (*addr_p
);
532 && !cbck (*addr_p
, idx
, data
))
543 /* The name and the length of the currently generated variable
545 #define MAX_LSM_NAME_LENGTH 40
546 static char lsm_tmp_name
[MAX_LSM_NAME_LENGTH
+ 1];
547 static int lsm_tmp_name_length
;
549 /* Adds S to lsm_tmp_name. */
552 lsm_tmp_name_add (const char *s
)
554 int l
= strlen (s
) + lsm_tmp_name_length
;
555 if (l
> MAX_LSM_NAME_LENGTH
)
558 strcpy (lsm_tmp_name
+ lsm_tmp_name_length
, s
);
559 lsm_tmp_name_length
= l
;
562 /* Stores the name for temporary variable that replaces REF to
566 gen_lsm_tmp_name (tree ref
)
570 switch (TREE_CODE (ref
))
574 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
575 lsm_tmp_name_add ("_");
579 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
583 case VIEW_CONVERT_EXPR
:
584 case ARRAY_RANGE_REF
:
585 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
589 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
590 lsm_tmp_name_add ("_RE");
594 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
595 lsm_tmp_name_add ("_IM");
599 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
600 lsm_tmp_name_add ("_");
601 name
= get_name (TREE_OPERAND (ref
, 1));
604 lsm_tmp_name_add (name
);
608 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
609 lsm_tmp_name_add ("_I");
615 name
= get_name (ref
);
618 lsm_tmp_name_add (name
);
622 lsm_tmp_name_add ("S");
626 lsm_tmp_name_add ("R");
638 /* Determines name for temporary variable that replaces REF.
639 The name is accumulated into the lsm_tmp_name variable.
640 N is added to the name of the temporary. */
643 get_lsm_tmp_name (tree ref
, unsigned n
, const char *suffix
)
647 lsm_tmp_name_length
= 0;
648 gen_lsm_tmp_name (ref
);
649 lsm_tmp_name_add ("_lsm");
654 lsm_tmp_name_add (ns
);
658 lsm_tmp_name_add (suffix
);
661 /* Computes an estimated number of insns in LOOP, weighted by WEIGHTS. */
664 tree_num_loop_insns (struct loop
*loop
, eni_weights
*weights
)
666 basic_block
*body
= get_loop_body (loop
);
667 gimple_stmt_iterator gsi
;
668 unsigned size
= 0, i
;
670 for (i
= 0; i
< loop
->num_nodes
; i
++)
671 for (gsi
= gsi_start_bb (body
[i
]); !gsi_end_p (gsi
); gsi_next (&gsi
))
672 size
+= estimate_num_insns (gsi_stmt (gsi
), weights
);