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 */
60 false, /* has_execute */
61 TV_TREE_LOOP
, /* tv_id */
62 PROP_cfg
, /* properties_required */
63 0, /* properties_provided */
64 0, /* properties_destroyed */
65 0, /* todo_flags_start */
66 TODO_verify_ssa
, /* todo_flags_finish */
69 class pass_tree_loop
: public gimple_opt_pass
72 pass_tree_loop (gcc::context
*ctxt
)
73 : gimple_opt_pass (pass_data_tree_loop
, ctxt
)
76 /* opt_pass methods: */
77 bool gate () { return gate_tree_loop (); }
79 }; // class pass_tree_loop
84 make_pass_tree_loop (gcc::context
*ctxt
)
86 return new pass_tree_loop (ctxt
);
89 /* Loop optimizer initialization. */
92 tree_ssa_loop_init (void)
94 loop_optimizer_init (LOOPS_NORMAL
95 | LOOPS_HAVE_RECORDED_EXITS
);
96 rewrite_into_loop_closed_ssa (NULL
, TODO_update_ssa
);
98 /* We might discover new loops, e.g. when turning irreducible
99 regions into reducible. */
102 if (number_of_loops (cfun
) <= 1)
110 const pass_data pass_data_tree_loop_init
=
112 GIMPLE_PASS
, /* type */
113 "loopinit", /* name */
114 OPTGROUP_LOOP
, /* optinfo_flags */
115 true, /* has_execute */
117 PROP_cfg
, /* properties_required */
118 0, /* properties_provided */
119 0, /* properties_destroyed */
120 0, /* todo_flags_start */
121 0, /* todo_flags_finish */
124 class pass_tree_loop_init
: public gimple_opt_pass
127 pass_tree_loop_init (gcc::context
*ctxt
)
128 : gimple_opt_pass (pass_data_tree_loop_init
, ctxt
)
131 /* opt_pass methods: */
132 unsigned int execute () { return tree_ssa_loop_init (); }
134 }; // class pass_tree_loop_init
139 make_pass_tree_loop_init (gcc::context
*ctxt
)
141 return new pass_tree_loop_init (ctxt
);
144 /* Loop autovectorization. */
147 tree_loop_vectorize (void)
149 if (number_of_loops (cfun
) <= 1)
152 return vectorize_loops ();
156 gate_tree_loop_vectorize (void)
158 return flag_tree_loop_vectorize
|| cfun
->has_force_vectorize_loops
;
163 const pass_data pass_data_vectorize
=
165 GIMPLE_PASS
, /* type */
167 OPTGROUP_LOOP
| OPTGROUP_VEC
, /* optinfo_flags */
168 true, /* has_execute */
169 TV_TREE_VECTORIZATION
, /* tv_id */
170 ( PROP_cfg
| PROP_ssa
), /* properties_required */
171 0, /* properties_provided */
172 0, /* properties_destroyed */
173 0, /* todo_flags_start */
174 0, /* todo_flags_finish */
177 class pass_vectorize
: public gimple_opt_pass
180 pass_vectorize (gcc::context
*ctxt
)
181 : gimple_opt_pass (pass_data_vectorize
, ctxt
)
184 /* opt_pass methods: */
185 bool gate () { return gate_tree_loop_vectorize (); }
186 unsigned int execute () { return tree_loop_vectorize (); }
188 }; // class pass_vectorize
193 make_pass_vectorize (gcc::context
*ctxt
)
195 return new pass_vectorize (ctxt
);
198 /* Check the correctness of the data dependence analyzers. */
201 check_data_deps (void)
203 if (number_of_loops (cfun
) <= 1)
206 tree_check_data_deps ();
211 gate_check_data_deps (void)
213 return flag_check_data_deps
!= 0;
218 const pass_data pass_data_check_data_deps
=
220 GIMPLE_PASS
, /* type */
222 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 */
268 true, /* has_execute */
269 TV_SCEV_CONST
, /* tv_id */
270 ( PROP_cfg
| PROP_ssa
), /* properties_required */
271 0, /* properties_provided */
272 0, /* properties_destroyed */
273 0, /* todo_flags_start */
275 | TODO_update_ssa_only_virtuals
), /* todo_flags_finish */
278 class pass_scev_cprop
: public gimple_opt_pass
281 pass_scev_cprop (gcc::context
*ctxt
)
282 : gimple_opt_pass (pass_data_scev_cprop
, ctxt
)
285 /* opt_pass methods: */
286 bool gate () { return gate_scev_const_prop (); }
287 unsigned int execute () { return scev_const_prop (); }
289 }; // class pass_scev_cprop
294 make_pass_scev_cprop (gcc::context
*ctxt
)
296 return new pass_scev_cprop (ctxt
);
299 /* Record bounds on numbers of iterations of loops. */
302 tree_ssa_loop_bounds (void)
304 if (number_of_loops (cfun
) <= 1)
307 estimate_numbers_of_iterations ();
314 const pass_data pass_data_record_bounds
=
316 GIMPLE_PASS
, /* type */
317 "*record_bounds", /* name */
318 OPTGROUP_NONE
, /* optinfo_flags */
319 true, /* has_execute */
320 TV_TREE_LOOP_BOUNDS
, /* tv_id */
321 ( PROP_cfg
| PROP_ssa
), /* properties_required */
322 0, /* properties_provided */
323 0, /* properties_destroyed */
324 0, /* todo_flags_start */
325 0, /* todo_flags_finish */
328 class pass_record_bounds
: public gimple_opt_pass
331 pass_record_bounds (gcc::context
*ctxt
)
332 : gimple_opt_pass (pass_data_record_bounds
, ctxt
)
335 /* opt_pass methods: */
336 unsigned int execute () { return tree_ssa_loop_bounds (); }
338 }; // class pass_record_bounds
343 make_pass_record_bounds (gcc::context
*ctxt
)
345 return new pass_record_bounds (ctxt
);
348 /* Induction variable optimizations. */
351 tree_ssa_loop_ivopts (void)
353 if (number_of_loops (cfun
) <= 1)
356 tree_ssa_iv_optimize ();
361 gate_tree_ssa_loop_ivopts (void)
363 return flag_ivopts
!= 0;
368 const pass_data pass_data_iv_optimize
=
370 GIMPLE_PASS
, /* type */
372 OPTGROUP_LOOP
, /* optinfo_flags */
373 true, /* has_execute */
374 TV_TREE_LOOP_IVOPTS
, /* tv_id */
375 ( PROP_cfg
| PROP_ssa
), /* properties_required */
376 0, /* properties_provided */
377 0, /* properties_destroyed */
378 0, /* todo_flags_start */
379 TODO_update_ssa
, /* todo_flags_finish */
382 class pass_iv_optimize
: public gimple_opt_pass
385 pass_iv_optimize (gcc::context
*ctxt
)
386 : gimple_opt_pass (pass_data_iv_optimize
, ctxt
)
389 /* opt_pass methods: */
390 bool gate () { return gate_tree_ssa_loop_ivopts (); }
391 unsigned int execute () { return tree_ssa_loop_ivopts (); }
393 }; // class pass_iv_optimize
398 make_pass_iv_optimize (gcc::context
*ctxt
)
400 return new pass_iv_optimize (ctxt
);
403 /* Loop optimizer finalization. */
406 tree_ssa_loop_done (void)
408 free_numbers_of_iterations_estimates ();
410 loop_optimizer_finalize ();
416 const pass_data pass_data_tree_loop_done
=
418 GIMPLE_PASS
, /* type */
419 "loopdone", /* name */
420 OPTGROUP_LOOP
, /* optinfo_flags */
421 true, /* has_execute */
423 PROP_cfg
, /* properties_required */
424 0, /* properties_provided */
425 0, /* properties_destroyed */
426 0, /* todo_flags_start */
427 ( TODO_cleanup_cfg
| TODO_verify_flow
), /* todo_flags_finish */
430 class pass_tree_loop_done
: public gimple_opt_pass
433 pass_tree_loop_done (gcc::context
*ctxt
)
434 : gimple_opt_pass (pass_data_tree_loop_done
, ctxt
)
437 /* opt_pass methods: */
438 unsigned int execute () { return tree_ssa_loop_done (); }
440 }; // class pass_tree_loop_done
445 make_pass_tree_loop_done (gcc::context
*ctxt
)
447 return new pass_tree_loop_done (ctxt
);
450 /* Calls CBCK for each index in memory reference ADDR_P. There are two
451 kinds situations handled; in each of these cases, the memory reference
452 and DATA are passed to the callback:
454 Access to an array: ARRAY_{RANGE_}REF (base, index). In this case we also
455 pass the pointer to the index to the callback.
457 Pointer dereference: INDIRECT_REF (addr). In this case we also pass the
458 pointer to addr to the callback.
460 If the callback returns false, the whole search stops and false is returned.
461 Otherwise the function returns true after traversing through the whole
462 reference *ADDR_P. */
465 for_each_index (tree
*addr_p
, bool (*cbck
) (tree
, tree
*, void *), void *data
)
469 for (; ; addr_p
= nxt
)
471 switch (TREE_CODE (*addr_p
))
474 return cbck (*addr_p
, addr_p
, data
);
477 nxt
= &TREE_OPERAND (*addr_p
, 0);
478 return cbck (*addr_p
, nxt
, data
);
481 case VIEW_CONVERT_EXPR
:
484 nxt
= &TREE_OPERAND (*addr_p
, 0);
488 /* If the component has varying offset, it behaves like index
490 idx
= &TREE_OPERAND (*addr_p
, 2);
492 && !cbck (*addr_p
, idx
, data
))
495 nxt
= &TREE_OPERAND (*addr_p
, 0);
499 case ARRAY_RANGE_REF
:
500 nxt
= &TREE_OPERAND (*addr_p
, 0);
501 if (!cbck (*addr_p
, &TREE_OPERAND (*addr_p
, 1), data
))
519 gcc_assert (is_gimple_min_invariant (*addr_p
));
523 idx
= &TMR_BASE (*addr_p
);
525 && !cbck (*addr_p
, idx
, data
))
527 idx
= &TMR_INDEX (*addr_p
);
529 && !cbck (*addr_p
, idx
, data
))
531 idx
= &TMR_INDEX2 (*addr_p
);
533 && !cbck (*addr_p
, idx
, data
))
544 /* The name and the length of the currently generated variable
546 #define MAX_LSM_NAME_LENGTH 40
547 static char lsm_tmp_name
[MAX_LSM_NAME_LENGTH
+ 1];
548 static int lsm_tmp_name_length
;
550 /* Adds S to lsm_tmp_name. */
553 lsm_tmp_name_add (const char *s
)
555 int l
= strlen (s
) + lsm_tmp_name_length
;
556 if (l
> MAX_LSM_NAME_LENGTH
)
559 strcpy (lsm_tmp_name
+ lsm_tmp_name_length
, s
);
560 lsm_tmp_name_length
= l
;
563 /* Stores the name for temporary variable that replaces REF to
567 gen_lsm_tmp_name (tree ref
)
571 switch (TREE_CODE (ref
))
575 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
576 lsm_tmp_name_add ("_");
580 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
584 case VIEW_CONVERT_EXPR
:
585 case ARRAY_RANGE_REF
:
586 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
590 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
591 lsm_tmp_name_add ("_RE");
595 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
596 lsm_tmp_name_add ("_IM");
600 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
601 lsm_tmp_name_add ("_");
602 name
= get_name (TREE_OPERAND (ref
, 1));
605 lsm_tmp_name_add (name
);
609 gen_lsm_tmp_name (TREE_OPERAND (ref
, 0));
610 lsm_tmp_name_add ("_I");
616 name
= get_name (ref
);
619 lsm_tmp_name_add (name
);
623 lsm_tmp_name_add ("S");
627 lsm_tmp_name_add ("R");
639 /* Determines name for temporary variable that replaces REF.
640 The name is accumulated into the lsm_tmp_name variable.
641 N is added to the name of the temporary. */
644 get_lsm_tmp_name (tree ref
, unsigned n
, const char *suffix
)
648 lsm_tmp_name_length
= 0;
649 gen_lsm_tmp_name (ref
);
650 lsm_tmp_name_add ("_lsm");
655 lsm_tmp_name_add (ns
);
659 lsm_tmp_name_add (suffix
);
662 /* Computes an estimated number of insns in LOOP, weighted by WEIGHTS. */
665 tree_num_loop_insns (struct loop
*loop
, eni_weights
*weights
)
667 basic_block
*body
= get_loop_body (loop
);
668 gimple_stmt_iterator gsi
;
669 unsigned size
= 0, i
;
671 for (i
= 0; i
< loop
->num_nodes
; i
++)
672 for (gsi
= gsi_start_bb (body
[i
]); !gsi_end_p (gsi
); gsi_next (&gsi
))
673 size
+= estimate_num_insns (gsi_stmt (gsi
), weights
);