[AArch64] fix big.LITTLE spec rewriting
[official-gcc.git] / gcc / tree-ssa-loop.c
blobe71519acf7b9ac42bad7a9bb0d7434af63dbc3a7
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
9 later version.
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
14 for more details.
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/>. */
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "tm.h"
24 #include "tree.h"
25 #include "tm_p.h"
26 #include "basic-block.h"
27 #include "tree-ssa-alias.h"
28 #include "internal-fn.h"
29 #include "gimple-expr.h"
30 #include "is-a.h"
31 #include "gimple.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"
38 #include "cfgloop.h"
39 #include "flags.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. */
47 static bool
48 gate_tree_loop (void)
50 return flag_tree_loop_optimize != 0;
53 namespace {
55 const pass_data pass_data_tree_loop =
57 GIMPLE_PASS, /* type */
58 "loop", /* name */
59 OPTGROUP_LOOP, /* optinfo_flags */
60 true, /* has_gate */
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
72 public:
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
82 } // anon namespace
84 gimple_opt_pass *
85 make_pass_tree_loop (gcc::context *ctxt)
87 return new pass_tree_loop (ctxt);
90 /* Loop optimizer initialization. */
92 static unsigned int
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. */
101 scev_initialize ();
103 if (number_of_loops (cfun) <= 1)
104 return 0;
106 return 0;
109 namespace {
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 */
118 TV_NONE, /* tv_id */
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
128 public:
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
138 } // anon namespace
140 gimple_opt_pass *
141 make_pass_tree_loop_init (gcc::context *ctxt)
143 return new pass_tree_loop_init (ctxt);
146 /* Loop autovectorization. */
148 static unsigned int
149 tree_loop_vectorize (void)
151 if (number_of_loops (cfun) <= 1)
152 return 0;
154 return vectorize_loops ();
157 static bool
158 gate_tree_loop_vectorize (void)
160 return flag_tree_loop_vectorize || cfun->has_force_vect_loops;
163 namespace {
165 const pass_data pass_data_vectorize =
167 GIMPLE_PASS, /* type */
168 "vect", /* name */
169 OPTGROUP_LOOP | OPTGROUP_VEC, /* optinfo_flags */
170 true, /* has_gate */
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
182 public:
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
193 } // anon namespace
195 gimple_opt_pass *
196 make_pass_vectorize (gcc::context *ctxt)
198 return new pass_vectorize (ctxt);
201 /* Check the correctness of the data dependence analyzers. */
203 static unsigned int
204 check_data_deps (void)
206 if (number_of_loops (cfun) <= 1)
207 return 0;
209 tree_check_data_deps ();
210 return 0;
213 static bool
214 gate_check_data_deps (void)
216 return flag_check_data_deps != 0;
219 namespace {
221 const pass_data pass_data_check_data_deps =
223 GIMPLE_PASS, /* type */
224 "ckdd", /* name */
225 OPTGROUP_LOOP, /* optinfo_flags */
226 true, /* has_gate */
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
238 public:
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
249 } // anon namespace
251 gimple_opt_pass *
252 make_pass_check_data_deps (gcc::context *ctxt)
254 return new pass_check_data_deps (ctxt);
257 /* Propagation of constants using scev. */
259 static bool
260 gate_scev_const_prop (void)
262 return flag_tree_scev_cprop;
265 namespace {
267 const pass_data pass_data_scev_cprop =
269 GIMPLE_PASS, /* type */
270 "sccp", /* name */
271 OPTGROUP_LOOP, /* optinfo_flags */
272 true, /* has_gate */
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 */
279 ( TODO_cleanup_cfg
280 | TODO_update_ssa_only_virtuals ), /* todo_flags_finish */
283 class pass_scev_cprop : public gimple_opt_pass
285 public:
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
296 } // anon namespace
298 gimple_opt_pass *
299 make_pass_scev_cprop (gcc::context *ctxt)
301 return new pass_scev_cprop (ctxt);
304 /* Record bounds on numbers of iterations of loops. */
306 static unsigned int
307 tree_ssa_loop_bounds (void)
309 if (number_of_loops (cfun) <= 1)
310 return 0;
312 estimate_numbers_of_iterations ();
313 scev_reset ();
314 return 0;
317 namespace {
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
336 public:
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
346 } // anon namespace
348 gimple_opt_pass *
349 make_pass_record_bounds (gcc::context *ctxt)
351 return new pass_record_bounds (ctxt);
354 /* Induction variable optimizations. */
356 static unsigned int
357 tree_ssa_loop_ivopts (void)
359 if (number_of_loops (cfun) <= 1)
360 return 0;
362 tree_ssa_iv_optimize ();
363 return 0;
366 static bool
367 gate_tree_ssa_loop_ivopts (void)
369 return flag_ivopts != 0;
372 namespace {
374 const pass_data pass_data_iv_optimize =
376 GIMPLE_PASS, /* type */
377 "ivopts", /* name */
378 OPTGROUP_LOOP, /* optinfo_flags */
379 true, /* has_gate */
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
391 public:
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
402 } // anon namespace
404 gimple_opt_pass *
405 make_pass_iv_optimize (gcc::context *ctxt)
407 return new pass_iv_optimize (ctxt);
410 /* Loop optimizer finalization. */
412 static unsigned int
413 tree_ssa_loop_done (void)
415 free_numbers_of_iterations_estimates ();
416 scev_finalize ();
417 loop_optimizer_finalize ();
418 return 0;
421 namespace {
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 */
430 TV_NONE, /* tv_id */
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
440 public:
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
450 } // anon namespace
452 gimple_opt_pass *
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. */
472 bool
473 for_each_index (tree *addr_p, bool (*cbck) (tree, tree *, void *), void *data)
475 tree *nxt, *idx;
477 for (; ; addr_p = nxt)
479 switch (TREE_CODE (*addr_p))
481 case SSA_NAME:
482 return cbck (*addr_p, addr_p, data);
484 case MEM_REF:
485 nxt = &TREE_OPERAND (*addr_p, 0);
486 return cbck (*addr_p, nxt, data);
488 case BIT_FIELD_REF:
489 case VIEW_CONVERT_EXPR:
490 case REALPART_EXPR:
491 case IMAGPART_EXPR:
492 nxt = &TREE_OPERAND (*addr_p, 0);
493 break;
495 case COMPONENT_REF:
496 /* If the component has varying offset, it behaves like index
497 as well. */
498 idx = &TREE_OPERAND (*addr_p, 2);
499 if (*idx
500 && !cbck (*addr_p, idx, data))
501 return false;
503 nxt = &TREE_OPERAND (*addr_p, 0);
504 break;
506 case ARRAY_REF:
507 case ARRAY_RANGE_REF:
508 nxt = &TREE_OPERAND (*addr_p, 0);
509 if (!cbck (*addr_p, &TREE_OPERAND (*addr_p, 1), data))
510 return false;
511 break;
513 case VAR_DECL:
514 case PARM_DECL:
515 case CONST_DECL:
516 case STRING_CST:
517 case RESULT_DECL:
518 case VECTOR_CST:
519 case COMPLEX_CST:
520 case INTEGER_CST:
521 case REAL_CST:
522 case FIXED_CST:
523 case CONSTRUCTOR:
524 return true;
526 case ADDR_EXPR:
527 gcc_assert (is_gimple_min_invariant (*addr_p));
528 return true;
530 case TARGET_MEM_REF:
531 idx = &TMR_BASE (*addr_p);
532 if (*idx
533 && !cbck (*addr_p, idx, data))
534 return false;
535 idx = &TMR_INDEX (*addr_p);
536 if (*idx
537 && !cbck (*addr_p, idx, data))
538 return false;
539 idx = &TMR_INDEX2 (*addr_p);
540 if (*idx
541 && !cbck (*addr_p, idx, data))
542 return false;
543 return true;
545 default:
546 gcc_unreachable ();
552 /* The name and the length of the currently generated variable
553 for lsm. */
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. */
560 static void
561 lsm_tmp_name_add (const char *s)
563 int l = strlen (s) + lsm_tmp_name_length;
564 if (l > MAX_LSM_NAME_LENGTH)
565 return;
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
572 lsm_tmp_name. */
574 static void
575 gen_lsm_tmp_name (tree ref)
577 const char *name;
579 switch (TREE_CODE (ref))
581 case MEM_REF:
582 case TARGET_MEM_REF:
583 gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
584 lsm_tmp_name_add ("_");
585 break;
587 case ADDR_EXPR:
588 gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
589 break;
591 case BIT_FIELD_REF:
592 case VIEW_CONVERT_EXPR:
593 case ARRAY_RANGE_REF:
594 gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
595 break;
597 case REALPART_EXPR:
598 gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
599 lsm_tmp_name_add ("_RE");
600 break;
602 case IMAGPART_EXPR:
603 gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
604 lsm_tmp_name_add ("_IM");
605 break;
607 case COMPONENT_REF:
608 gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
609 lsm_tmp_name_add ("_");
610 name = get_name (TREE_OPERAND (ref, 1));
611 if (!name)
612 name = "F";
613 lsm_tmp_name_add (name);
614 break;
616 case ARRAY_REF:
617 gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
618 lsm_tmp_name_add ("_I");
619 break;
621 case SSA_NAME:
622 case VAR_DECL:
623 case PARM_DECL:
624 name = get_name (ref);
625 if (!name)
626 name = "D";
627 lsm_tmp_name_add (name);
628 break;
630 case STRING_CST:
631 lsm_tmp_name_add ("S");
632 break;
634 case RESULT_DECL:
635 lsm_tmp_name_add ("R");
636 break;
638 case INTEGER_CST:
639 /* Nothing. */
640 break;
642 default:
643 gcc_unreachable ();
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. */
651 char *
652 get_lsm_tmp_name (tree ref, unsigned n, const char *suffix)
654 char ns[2];
656 lsm_tmp_name_length = 0;
657 gen_lsm_tmp_name (ref);
658 lsm_tmp_name_add ("_lsm");
659 if (n < 10)
661 ns[0] = '0' + n;
662 ns[1] = 0;
663 lsm_tmp_name_add (ns);
665 return lsm_tmp_name;
666 if (suffix != NULL)
667 lsm_tmp_name_add (suffix);
670 /* Computes an estimated number of insns in LOOP, weighted by WEIGHTS. */
672 unsigned
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);
682 free (body);
684 return size;