]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/loop-init.c
In PR70010, a function is marked with target(no-vsx) to disable VSX code
[thirdparty/gcc.git] / gcc / loop-init.c
CommitLineData
0526a3ff 1/* Loop optimizer initialization routines and RTL loop optimization passes.
fbd26352 2 Copyright (C) 2002-2019 Free Software Foundation, Inc.
6a606e3c 3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8c4c00c1 8Software Foundation; either version 3, or (at your option) any later
6a606e3c 9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
8c4c00c1 17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
6a606e3c 19
20#include "config.h"
21#include "system.h"
22#include "coretypes.h"
9ef16211 23#include "backend.h"
7c29e30e 24#include "target.h"
6a606e3c 25#include "rtl.h"
7c29e30e 26#include "tree.h"
27#include "cfghooks.h"
9ef16211 28#include "df.h"
4a020a8c 29#include "regs.h"
94ea8568 30#include "cfgcleanup.h"
6a606e3c 31#include "cfgloop.h"
77fce4cd 32#include "tree-pass.h"
05d9c18a 33#include "tree-ssa-loop-niter.h"
f7b51129 34#include "loop-unroll.h"
1ebce849 35#include "tree-scalar-evolution.h"
6a606e3c 36
0526a3ff 37\f
ff829efa 38/* Apply FLAGS to the loop state. */
6a606e3c 39
ff829efa 40static void
41apply_loop_flags (unsigned flags)
6a606e3c 42{
4a6f9e19 43 if (flags & LOOPS_MAY_HAVE_MULTIPLE_LATCHES)
44 {
45 /* If the loops may have multiple latches, we cannot canonicalize
46 them further (and most of the loop manipulation functions will
47 not work). However, we avoid modifying cfg, which some
48 passes may want. */
49 gcc_assert ((flags & ~(LOOPS_MAY_HAVE_MULTIPLE_LATCHES
50 | LOOPS_HAVE_RECORDED_EXITS)) == 0);
f24ec26f 51 loops_state_set (LOOPS_MAY_HAVE_MULTIPLE_LATCHES);
4a6f9e19 52 }
53 else
54 disambiguate_loops_with_multiple_latches ();
55
6a606e3c 56 /* Create pre-headers. */
c8d055f6 57 if (flags & LOOPS_HAVE_PREHEADERS)
e1ab7874 58 {
59 int cp_flags = CP_SIMPLE_PREHEADERS;
60
61 if (flags & LOOPS_HAVE_FALLTHRU_PREHEADERS)
62 cp_flags |= CP_FALLTHRU_PREHEADERS;
48e1416a 63
e1ab7874 64 create_preheaders (cp_flags);
65 }
6a606e3c 66
67 /* Force all latches to have only single successor. */
c8d055f6 68 if (flags & LOOPS_HAVE_SIMPLE_LATCHES)
7194de72 69 force_single_succ_latches ();
6a606e3c 70
71 /* Mark irreducible loops. */
c8d055f6 72 if (flags & LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)
7194de72 73 mark_irreducible_loops ();
c8d055f6 74
dce58e66 75 if (flags & LOOPS_HAVE_RECORDED_EXITS)
76 record_loop_exits ();
ff829efa 77}
78
79/* Initialize loop structures. This is used by the tree and RTL loop
80 optimizers. FLAGS specify what properties to compute and/or ensure for
81 loops. */
82
83void
84loop_optimizer_init (unsigned flags)
85{
86 timevar_push (TV_LOOP_INIT);
87
88 if (!current_loops)
89 {
90 gcc_assert (!(cfun->curr_properties & PROP_loops));
91
92 /* Find the loops. */
93 current_loops = flow_loops_find (NULL);
94 }
95 else
96 {
f6568ea4 97 bool recorded_exits = loops_state_satisfies_p (LOOPS_HAVE_RECORDED_EXITS);
37dc09f8 98 bool needs_fixup = loops_state_satisfies_p (LOOPS_NEED_FIXUP);
f6568ea4 99
ff829efa 100 gcc_assert (cfun->curr_properties & PROP_loops);
101
102 /* Ensure that the dominators are computed, like flow_loops_find does. */
103 calculate_dominance_info (CDI_DOMINATORS);
104
37dc09f8 105 if (!needs_fixup)
382ecba7 106 checking_verify_loop_structure ();
51f707ce 107
108 /* Clear all flags. */
f6568ea4 109 if (recorded_exits)
d4f078b5 110 release_recorded_exits (cfun);
51f707ce 111 loops_state_clear (~0U);
37dc09f8 112
113 if (needs_fixup)
114 {
115 /* Apply LOOPS_MAY_HAVE_MULTIPLE_LATCHES early as fix_loop_structure
116 re-applies flags. */
117 loops_state_set (flags & LOOPS_MAY_HAVE_MULTIPLE_LATCHES);
118 fix_loop_structure (NULL);
119 }
ff829efa 120 }
121
122 /* Apply flags to loops. */
123 apply_loop_flags (flags);
6a606e3c 124
125 /* Dump loops. */
7194de72 126 flow_loops_dump (dump_file, NULL, 1);
6a606e3c 127
382ecba7 128 checking_verify_loop_structure ();
a66c9777 129
130 timevar_pop (TV_LOOP_INIT);
6a606e3c 131}
132
88e6f696 133/* Finalize loop structures. */
134
6a606e3c 135void
d4f078b5 136loop_optimizer_finalize (struct function *fn)
6a606e3c 137{
2e966e2a 138 class loop *loop;
88e6f696 139 basic_block bb;
6a606e3c 140
a66c9777 141 timevar_push (TV_LOOP_FINI);
142
d4f078b5 143 if (loops_state_satisfies_p (fn, LOOPS_HAVE_RECORDED_EXITS))
144 release_recorded_exits (fn);
79f958cb 145
d4f078b5 146 free_numbers_of_iterations_estimates (fn);
9584aa9d 147
79f958cb 148 /* If we should preserve loop structure, do not free it but clear
149 flags that advanced properties are there as we are not preserving
150 that in full. */
d4f078b5 151 if (fn->curr_properties & PROP_loops)
79f958cb 152 {
d4f078b5 153 loops_state_clear (fn, LOOP_CLOSED_SSA
79f958cb 154 | LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS
155 | LOOPS_HAVE_PREHEADERS
156 | LOOPS_HAVE_SIMPLE_LATCHES
157 | LOOPS_HAVE_FALLTHRU_PREHEADERS);
d4f078b5 158 loops_state_set (fn, LOOPS_MAY_HAVE_MULTIPLE_LATCHES);
a66c9777 159 goto loop_fini_done;
79f958cb 160 }
161
d4f078b5 162 FOR_EACH_LOOP_FN (fn, loop, 0)
f21d4d00 163 free_simple_loop_desc (loop);
6a606e3c 164
6a606e3c 165 /* Clean up. */
d4f078b5 166 flow_loops_free (loops_for_fn (fn));
167 ggc_free (loops_for_fn (fn));
168 set_loops_for_fn (fn, NULL);
88e6f696 169
d4f078b5 170 FOR_ALL_BB_FN (bb, fn)
88e6f696 171 {
172 bb->loop_father = NULL;
173 }
a66c9777 174
175loop_fini_done:
176 timevar_pop (TV_LOOP_FINI);
6a606e3c 177}
0526a3ff 178
ff829efa 179/* The structure of loops might have changed. Some loops might get removed
180 (and their headers and latches were set to NULL), loop exists might get
181 removed (thus the loop nesting may be wrong), and some blocks and edges
182 were changed (so the information about bb --> loop mapping does not have
183 to be correct). But still for the remaining loops the header dominates
184 the latch, and loops did not get new subloops (new loops might possibly
185 get created, but we are not interested in them). Fix up the mess.
186
b6f3c6f1 187 If CHANGED_BBS is not NULL, basic blocks whose loop depth has changed are
188 marked in it.
ff829efa 189
b6f3c6f1 190 Returns the number of new discovered loops. */
191
192unsigned
ff829efa 193fix_loop_structure (bitmap changed_bbs)
194{
195 basic_block bb;
196 int record_exits = 0;
2e966e2a 197 class loop *loop;
84087109 198 unsigned old_nloops, i;
ff829efa 199
200 timevar_push (TV_LOOP_INIT);
201
1ebce849 202 if (dump_file && (dump_flags & TDF_DETAILS))
203 fprintf (dump_file, "fix_loop_structure: fixing up loops for function\n");
204
ff829efa 205 /* We need exact and fast dominance info to be available. */
206 gcc_assert (dom_info_state (CDI_DOMINATORS) == DOM_OK);
207
208 if (loops_state_satisfies_p (LOOPS_HAVE_RECORDED_EXITS))
209 {
d4f078b5 210 release_recorded_exits (cfun);
ff829efa 211 record_exits = LOOPS_HAVE_RECORDED_EXITS;
212 }
213
214 /* Remember the depth of the blocks in the loop hierarchy, so that we can
215 recognize blocks whose loop nesting relationship has changed. */
216 if (changed_bbs)
fc00614f 217 FOR_EACH_BB_FN (bb, cfun)
ff829efa 218 bb->aux = (void *) (size_t) loop_depth (bb->loop_father);
219
220 /* Remove the dead loops from structures. We start from the innermost
221 loops, so that when we remove the loops, we know that the loops inside
222 are preserved, and do not waste time relinking loops that will be
223 removed later. */
f21d4d00 224 FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
ff829efa 225 {
226 /* Detect the case that the loop is no longer present even though
227 it wasn't marked for removal.
228 ??? If we do that we can get away with not marking loops for
229 removal at all. And possibly avoid some spurious removals. */
230 if (loop->header
231 && bb_loop_header_p (loop->header))
232 continue;
233
234 if (dump_file && (dump_flags & TDF_DETAILS))
235 fprintf (dump_file, "fix_loop_structure: removing loop %d\n",
236 loop->num);
237
238 while (loop->inner)
239 {
2e966e2a 240 class loop *ploop = loop->inner;
ff829efa 241 flow_loop_tree_node_remove (ploop);
242 flow_loop_tree_node_add (loop_outer (loop), ploop);
243 }
244
84087109 245 /* Remove the loop. */
6437689e 246 if (loop->header)
247 loop->former_header = loop->header;
248 else
249 gcc_assert (loop->former_header != NULL);
84087109 250 loop->header = NULL;
251 flow_loop_tree_node_remove (loop);
ff829efa 252 }
253
b6f3c6f1 254 /* Remember the number of loops so we can return how many new loops
255 flow_loops_find discovered. */
41f75a99 256 old_nloops = number_of_loops (cfun);
b6f3c6f1 257
ff829efa 258 /* Re-compute loop structure in-place. */
259 flow_loops_find (current_loops);
260
261 /* Mark the blocks whose loop has changed. */
262 if (changed_bbs)
263 {
fc00614f 264 FOR_EACH_BB_FN (bb, cfun)
ff829efa 265 {
266 if ((void *) (size_t) loop_depth (bb->loop_father) != bb->aux)
267 bitmap_set_bit (changed_bbs, bb->index);
268
269 bb->aux = NULL;
270 }
271 }
272
84087109 273 /* Finally free deleted loops. */
1ebce849 274 bool any_deleted = false;
41f75a99 275 FOR_EACH_VEC_ELT (*get_loops (cfun), i, loop)
84087109 276 if (loop && loop->header == NULL)
277 {
6437689e 278 if (dump_file
279 && ((unsigned) loop->former_header->index
280 < basic_block_info_for_fn (cfun)->length ()))
281 {
282 basic_block former_header
283 = BASIC_BLOCK_FOR_FN (cfun, loop->former_header->index);
284 /* If the old header still exists we want to check if the
285 original loop is re-discovered or the old header is now
286 part of a newly discovered loop.
287 In both cases we should have avoided removing the loop. */
288 if (former_header == loop->former_header)
289 {
290 if (former_header->loop_father->header == former_header)
291 fprintf (dump_file, "fix_loop_structure: rediscovered "
292 "removed loop %d as loop %d with old header %d\n",
293 loop->num, former_header->loop_father->num,
294 former_header->index);
295 else if ((unsigned) former_header->loop_father->num
296 >= old_nloops)
297 fprintf (dump_file, "fix_loop_structure: header %d of "
298 "removed loop %d is part of the newly "
299 "discovered loop %d with header %d\n",
300 former_header->index, loop->num,
301 former_header->loop_father->num,
302 former_header->loop_father->header->index);
303 }
304 }
41f75a99 305 (*get_loops (cfun))[i] = NULL;
84087109 306 flow_loop_free (loop);
1ebce849 307 any_deleted = true;
84087109 308 }
309
1ebce849 310 /* If we deleted loops then the cached scalar evolutions refering to
311 those loops become invalid. */
312 if (any_deleted && scev_initialized_p ())
313 scev_reset_htab ();
314
ff829efa 315 loops_state_clear (LOOPS_NEED_FIXUP);
316
317 /* Apply flags to loops. */
318 apply_loop_flags (current_loops->state | record_exits);
319
382ecba7 320 checking_verify_loop_structure ();
ff829efa 321
322 timevar_pop (TV_LOOP_INIT);
b6f3c6f1 323
41f75a99 324 return number_of_loops (cfun) - old_nloops;
ff829efa 325}
77fce4cd 326\f
31315c24 327/* The RTL loop superpass. The actual passes are subpasses. See passes.c for
328 more on that. */
77fce4cd 329
cbe8bda8 330namespace {
331
332const pass_data pass_data_loop2 =
333{
334 RTL_PASS, /* type */
335 "loop2", /* name */
336 OPTGROUP_LOOP, /* optinfo_flags */
cbe8bda8 337 TV_LOOP, /* tv_id */
338 0, /* properties_required */
339 0, /* properties_provided */
340 0, /* properties_destroyed */
341 0, /* todo_flags_start */
342 0, /* todo_flags_finish */
0526a3ff 343};
77fce4cd 344
cbe8bda8 345class pass_loop2 : public rtl_opt_pass
346{
347public:
9af5ce0c 348 pass_loop2 (gcc::context *ctxt)
349 : rtl_opt_pass (pass_data_loop2, ctxt)
cbe8bda8 350 {}
351
352 /* opt_pass methods: */
31315c24 353 virtual bool gate (function *);
cbe8bda8 354
355}; // class pass_loop2
356
31315c24 357bool
358pass_loop2::gate (function *fun)
359{
360 if (optimize > 0
361 && (flag_move_loop_invariants
362 || flag_unswitch_loops
31315c24 363 || flag_unroll_loops
2a09b28c 364 || (flag_branch_on_count_reg && targetm.have_doloop_end ())
365 || cfun->has_unroll))
31315c24 366 return true;
367 else
368 {
369 /* No longer preserve loops, remove them now. */
370 fun->curr_properties &= ~PROP_loops;
371 if (current_loops)
372 loop_optimizer_finalize ();
373 return false;
374 }
375}
376
cbe8bda8 377} // anon namespace
378
379rtl_opt_pass *
380make_pass_loop2 (gcc::context *ctxt)
381{
382 return new pass_loop2 (ctxt);
383}
384
0526a3ff 385\f
386/* Initialization of the RTL loop passes. */
2a1990e9 387static unsigned int
0526a3ff 388rtl_loop_init (void)
389{
207c7ab2 390 gcc_assert (current_ir_type () == IR_RTL_CFGLAYOUT);
48e1416a 391
77fce4cd 392 if (dump_file)
4a020a8c 393 {
394 dump_reg_info (dump_file);
395 dump_flow_info (dump_file, dump_flags);
396 }
77fce4cd 397
005f5910 398 loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS);
2a1990e9 399 return 0;
0526a3ff 400}
77fce4cd 401
cbe8bda8 402namespace {
403
404const pass_data pass_data_rtl_loop_init =
405{
406 RTL_PASS, /* type */
407 "loop2_init", /* name */
408 OPTGROUP_LOOP, /* optinfo_flags */
cbe8bda8 409 TV_LOOP, /* tv_id */
410 0, /* properties_required */
411 0, /* properties_provided */
412 0, /* properties_destroyed */
413 0, /* todo_flags_start */
8b88439e 414 0, /* todo_flags_finish */
0526a3ff 415};
77fce4cd 416
cbe8bda8 417class pass_rtl_loop_init : public rtl_opt_pass
418{
419public:
9af5ce0c 420 pass_rtl_loop_init (gcc::context *ctxt)
421 : rtl_opt_pass (pass_data_rtl_loop_init, ctxt)
cbe8bda8 422 {}
423
424 /* opt_pass methods: */
65b0537f 425 virtual unsigned int execute (function *) { return rtl_loop_init (); }
cbe8bda8 426
427}; // class pass_rtl_loop_init
428
429} // anon namespace
430
431rtl_opt_pass *
432make_pass_rtl_loop_init (gcc::context *ctxt)
433{
434 return new pass_rtl_loop_init (ctxt);
435}
436
0526a3ff 437\f
438/* Finalization of the RTL loop passes. */
88e6f696 439
cbe8bda8 440namespace {
441
442const pass_data pass_data_rtl_loop_done =
443{
444 RTL_PASS, /* type */
445 "loop2_done", /* name */
446 OPTGROUP_LOOP, /* optinfo_flags */
cbe8bda8 447 TV_LOOP, /* tv_id */
448 0, /* properties_required */
449 0, /* properties_provided */
450 PROP_loops, /* properties_destroyed */
451 0, /* todo_flags_start */
8b88439e 452 0, /* todo_flags_finish */
0526a3ff 453};
454
cbe8bda8 455class pass_rtl_loop_done : public rtl_opt_pass
456{
457public:
9af5ce0c 458 pass_rtl_loop_done (gcc::context *ctxt)
459 : rtl_opt_pass (pass_data_rtl_loop_done, ctxt)
cbe8bda8 460 {}
461
462 /* opt_pass methods: */
65b0537f 463 virtual unsigned int execute (function *);
cbe8bda8 464
465}; // class pass_rtl_loop_done
466
65b0537f 467unsigned int
468pass_rtl_loop_done::execute (function *fun)
469{
470 /* No longer preserve loops, remove them now. */
471 fun->curr_properties &= ~PROP_loops;
472 loop_optimizer_finalize ();
473 free_dominance_info (CDI_DOMINATORS);
474
475 cleanup_cfg (0);
476 if (dump_file)
477 {
478 dump_reg_info (dump_file);
479 dump_flow_info (dump_file, dump_flags);
480 }
481
482 return 0;
483}
484
cbe8bda8 485} // anon namespace
486
487rtl_opt_pass *
488make_pass_rtl_loop_done (gcc::context *ctxt)
489{
490 return new pass_rtl_loop_done (ctxt);
491}
492
0526a3ff 493\f
494/* Loop invariant code motion. */
0526a3ff 495
cbe8bda8 496namespace {
497
498const pass_data pass_data_rtl_move_loop_invariants =
499{
500 RTL_PASS, /* type */
501 "loop2_invariant", /* name */
502 OPTGROUP_LOOP, /* optinfo_flags */
cbe8bda8 503 TV_LOOP_MOVE_INVARIANTS, /* tv_id */
504 0, /* properties_required */
505 0, /* properties_provided */
506 0, /* properties_destroyed */
507 0, /* todo_flags_start */
8b88439e 508 ( TODO_df_verify | TODO_df_finish ), /* todo_flags_finish */
0526a3ff 509};
510
cbe8bda8 511class pass_rtl_move_loop_invariants : public rtl_opt_pass
512{
513public:
9af5ce0c 514 pass_rtl_move_loop_invariants (gcc::context *ctxt)
515 : rtl_opt_pass (pass_data_rtl_move_loop_invariants, ctxt)
cbe8bda8 516 {}
517
518 /* opt_pass methods: */
31315c24 519 virtual bool gate (function *) { return flag_move_loop_invariants; }
65b0537f 520 virtual unsigned int execute (function *fun)
521 {
522 if (number_of_loops (fun) > 1)
523 move_loop_invariants ();
524 return 0;
525 }
cbe8bda8 526
527}; // class pass_rtl_move_loop_invariants
528
529} // anon namespace
530
531rtl_opt_pass *
532make_pass_rtl_move_loop_invariants (gcc::context *ctxt)
533{
534 return new pass_rtl_move_loop_invariants (ctxt);
535}
536
0526a3ff 537\f
cbe8bda8 538namespace {
539
c836de3f 540const pass_data pass_data_rtl_unroll_loops =
cbe8bda8 541{
542 RTL_PASS, /* type */
543 "loop2_unroll", /* name */
544 OPTGROUP_LOOP, /* optinfo_flags */
cbe8bda8 545 TV_LOOP_UNROLL, /* tv_id */
546 0, /* properties_required */
547 0, /* properties_provided */
548 0, /* properties_destroyed */
549 0, /* todo_flags_start */
8b88439e 550 0, /* todo_flags_finish */
0526a3ff 551};
552
c836de3f 553class pass_rtl_unroll_loops : public rtl_opt_pass
cbe8bda8 554{
555public:
c836de3f 556 pass_rtl_unroll_loops (gcc::context *ctxt)
557 : rtl_opt_pass (pass_data_rtl_unroll_loops, ctxt)
cbe8bda8 558 {}
559
560 /* opt_pass methods: */
31315c24 561 virtual bool gate (function *)
562 {
2a09b28c 563 return (flag_unroll_loops || flag_unroll_all_loops || cfun->has_unroll);
31315c24 564 }
565
65b0537f 566 virtual unsigned int execute (function *);
cbe8bda8 567
c836de3f 568}; // class pass_rtl_unroll_loops
cbe8bda8 569
65b0537f 570unsigned int
c836de3f 571pass_rtl_unroll_loops::execute (function *fun)
65b0537f 572{
573 if (number_of_loops (fun) > 1)
574 {
575 int flags = 0;
576 if (dump_file)
577 df_dump (dump_file);
578
65b0537f 579 if (flag_unroll_loops)
580 flags |= UAP_UNROLL;
581 if (flag_unroll_all_loops)
582 flags |= UAP_UNROLL_ALL;
583
c836de3f 584 unroll_loops (flags);
65b0537f 585 }
586 return 0;
587}
588
cbe8bda8 589} // anon namespace
590
591rtl_opt_pass *
c836de3f 592make_pass_rtl_unroll_loops (gcc::context *ctxt)
cbe8bda8 593{
c836de3f 594 return new pass_rtl_unroll_loops (ctxt);
cbe8bda8 595}
596
0526a3ff 597\f
cbe8bda8 598namespace {
599
600const pass_data pass_data_rtl_doloop =
601{
602 RTL_PASS, /* type */
603 "loop2_doloop", /* name */
604 OPTGROUP_LOOP, /* optinfo_flags */
cbe8bda8 605 TV_LOOP_DOLOOP, /* tv_id */
606 0, /* properties_required */
607 0, /* properties_provided */
608 0, /* properties_destroyed */
609 0, /* todo_flags_start */
8b88439e 610 0, /* todo_flags_finish */
77fce4cd 611};
cbe8bda8 612
613class pass_rtl_doloop : public rtl_opt_pass
614{
615public:
9af5ce0c 616 pass_rtl_doloop (gcc::context *ctxt)
617 : rtl_opt_pass (pass_data_rtl_doloop, ctxt)
cbe8bda8 618 {}
619
620 /* opt_pass methods: */
31315c24 621 virtual bool gate (function *);
65b0537f 622 virtual unsigned int execute (function *);
cbe8bda8 623
624}; // class pass_rtl_doloop
625
31315c24 626bool
627pass_rtl_doloop::gate (function *)
628{
4177c695 629 return (flag_branch_on_count_reg && targetm.have_doloop_end ());
31315c24 630}
631
65b0537f 632unsigned int
4177c695 633pass_rtl_doloop::execute (function *fun)
65b0537f 634{
65b0537f 635 if (number_of_loops (fun) > 1)
636 doloop_optimize_loops ();
65b0537f 637 return 0;
638}
639
cbe8bda8 640} // anon namespace
641
642rtl_opt_pass *
643make_pass_rtl_doloop (gcc::context *ctxt)
644{
645 return new pass_rtl_doloop (ctxt);
646}