1 /* Loop optimizer initialization routines and RTL loop optimization passes.
2 Copyright (C) 2002-2023 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 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"
30 #include "cfgcleanup.h"
32 #include "tree-pass.h"
33 #include "tree-ssa-loop-niter.h"
34 #include "loop-unroll.h"
35 #include "tree-scalar-evolution.h"
36 #include "tree-cfgcleanup.h"
39 /* Apply FLAGS to the loop state. */
42 apply_loop_flags (unsigned flags
)
44 if (flags
& LOOPS_MAY_HAVE_MULTIPLE_LATCHES
)
46 /* If the loops may have multiple latches, we cannot canonicalize
47 them further (and most of the loop manipulation functions will
48 not work). However, we avoid modifying cfg, which some
50 gcc_assert ((flags
& ~(LOOPS_MAY_HAVE_MULTIPLE_LATCHES
51 | LOOPS_HAVE_RECORDED_EXITS
52 | LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS
)) == 0);
53 loops_state_set (LOOPS_MAY_HAVE_MULTIPLE_LATCHES
);
56 disambiguate_loops_with_multiple_latches ();
58 /* Create pre-headers. */
59 if (flags
& LOOPS_HAVE_PREHEADERS
)
61 int cp_flags
= CP_SIMPLE_PREHEADERS
;
63 if (flags
& LOOPS_HAVE_FALLTHRU_PREHEADERS
)
64 cp_flags
|= CP_FALLTHRU_PREHEADERS
;
66 create_preheaders (cp_flags
);
69 /* Force all latches to have only single successor. */
70 if (flags
& LOOPS_HAVE_SIMPLE_LATCHES
)
71 force_single_succ_latches ();
73 /* Mark irreducible loops. */
74 if (flags
& LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS
)
75 mark_irreducible_loops ();
77 if (flags
& LOOPS_HAVE_RECORDED_EXITS
)
81 /* Initialize loop structures. This is used by the tree and RTL loop
82 optimizers. FLAGS specify what properties to compute and/or ensure for
86 loop_optimizer_init (unsigned flags
)
88 timevar_push (TV_LOOP_INIT
);
92 gcc_assert (!(cfun
->curr_properties
& PROP_loops
));
95 current_loops
= flow_loops_find (NULL
);
99 bool recorded_exits
= loops_state_satisfies_p (LOOPS_HAVE_RECORDED_EXITS
);
100 bool needs_fixup
= loops_state_satisfies_p (LOOPS_NEED_FIXUP
);
102 gcc_assert (cfun
->curr_properties
& PROP_loops
);
104 /* Ensure that the dominators are computed, like flow_loops_find does. */
105 calculate_dominance_info (CDI_DOMINATORS
);
108 checking_verify_loop_structure ();
110 /* Clear all flags. */
112 release_recorded_exits (cfun
);
113 loops_state_clear (~0U);
117 /* Apply LOOPS_MAY_HAVE_MULTIPLE_LATCHES early as fix_loop_structure
119 loops_state_set (flags
& LOOPS_MAY_HAVE_MULTIPLE_LATCHES
);
120 fix_loop_structure (NULL
);
124 /* Apply flags to loops. */
125 apply_loop_flags (flags
);
128 flow_loops_dump (dump_file
, NULL
, 1);
130 checking_verify_loop_structure ();
132 timevar_pop (TV_LOOP_INIT
);
135 /* Finalize loop structures. */
138 loop_optimizer_finalize (struct function
*fn
, bool clean_loop_closed_phi
)
142 timevar_push (TV_LOOP_FINI
);
144 if (clean_loop_closed_phi
&& loops_state_satisfies_p (fn
, LOOP_CLOSED_SSA
))
146 clean_up_loop_closed_phi (fn
);
147 loops_state_clear (fn
, LOOP_CLOSED_SSA
);
150 if (loops_state_satisfies_p (fn
, LOOPS_HAVE_RECORDED_EXITS
))
151 release_recorded_exits (fn
);
153 free_numbers_of_iterations_estimates (fn
);
155 /* If we should preserve loop structure, do not free it but clear
156 flags that advanced properties are there as we are not preserving
158 if (fn
->curr_properties
& PROP_loops
)
160 loops_state_clear (fn
, LOOP_CLOSED_SSA
161 | LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS
162 | LOOPS_HAVE_PREHEADERS
163 | LOOPS_HAVE_SIMPLE_LATCHES
164 | LOOPS_HAVE_FALLTHRU_PREHEADERS
);
165 loops_state_set (fn
, LOOPS_MAY_HAVE_MULTIPLE_LATCHES
);
169 for (auto loop
: loops_list (fn
, 0))
170 free_simple_loop_desc (loop
);
173 flow_loops_free (loops_for_fn (fn
));
174 ggc_free (loops_for_fn (fn
));
175 set_loops_for_fn (fn
, NULL
);
177 FOR_ALL_BB_FN (bb
, fn
)
179 bb
->loop_father
= NULL
;
183 timevar_pop (TV_LOOP_FINI
);
186 /* The structure of loops might have changed. Some loops might get removed
187 (and their headers and latches were set to NULL), loop exists might get
188 removed (thus the loop nesting may be wrong), and some blocks and edges
189 were changed (so the information about bb --> loop mapping does not have
190 to be correct). But still for the remaining loops the header dominates
191 the latch, and loops did not get new subloops (new loops might possibly
192 get created, but we are not interested in them). Fix up the mess.
194 If CHANGED_BBS is not NULL, basic blocks whose loop depth has changed are
197 Returns the number of new discovered plus the number of removed loops. */
200 fix_loop_structure (bitmap changed_bbs
)
203 int record_exits
= 0;
204 unsigned old_nloops
, i
;
206 timevar_push (TV_LOOP_INIT
);
208 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
209 fprintf (dump_file
, "fix_loop_structure: fixing up loops for function\n");
211 /* We need exact and fast dominance info to be available. */
212 gcc_assert (dom_info_state (CDI_DOMINATORS
) == DOM_OK
);
214 if (loops_state_satisfies_p (LOOPS_HAVE_RECORDED_EXITS
))
216 release_recorded_exits (cfun
);
217 record_exits
= LOOPS_HAVE_RECORDED_EXITS
;
220 /* Remember the depth of the blocks in the loop hierarchy, so that we can
221 recognize blocks whose loop nesting relationship has changed. */
223 FOR_EACH_BB_FN (bb
, cfun
)
224 bb
->aux
= (void *) (size_t) loop_depth (bb
->loop_father
);
226 /* Remove the dead loops from structures. We start from the innermost
227 loops, so that when we remove the loops, we know that the loops inside
228 are preserved, and do not waste time relinking loops that will be
230 for (auto loop
: loops_list (cfun
, LI_FROM_INNERMOST
))
232 /* Detect the case that the loop is no longer present even though
233 it wasn't marked for removal.
234 ??? If we do that we can get away with not marking loops for
235 removal at all. And possibly avoid some spurious removals. */
237 && bb_loop_header_p (loop
->header
))
240 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
241 fprintf (dump_file
, "fix_loop_structure: removing loop %d\n",
246 class loop
*ploop
= loop
->inner
;
247 flow_loop_tree_node_remove (ploop
);
248 flow_loop_tree_node_add (loop_outer (loop
), ploop
);
251 /* Remove the loop. */
253 loop
->former_header
= loop
->header
;
255 gcc_assert (loop
->former_header
!= NULL
);
257 flow_loop_tree_node_remove (loop
);
260 /* Remember the number of loops so we can return how many new loops
261 flow_loops_find discovered. */
262 old_nloops
= number_of_loops (cfun
);
264 /* Re-compute loop structure in-place. */
265 flow_loops_find (current_loops
);
267 /* Mark the blocks whose loop has changed. */
270 FOR_EACH_BB_FN (bb
, cfun
)
272 if ((void *) (size_t) loop_depth (bb
->loop_father
) != bb
->aux
)
273 bitmap_set_bit (changed_bbs
, bb
->index
);
279 /* Finally free deleted loops. */
280 unsigned n_deleted
= 0;
282 FOR_EACH_VEC_ELT (*get_loops (cfun
), i
, loop
)
283 if (loop
&& loop
->header
== NULL
)
286 && ((unsigned) loop
->former_header
->index
287 < basic_block_info_for_fn (cfun
)->length ()))
289 basic_block former_header
290 = BASIC_BLOCK_FOR_FN (cfun
, loop
->former_header
->index
);
291 /* If the old header still exists we want to check if the
292 original loop is re-discovered or the old header is now
293 part of a newly discovered loop.
294 In both cases we should have avoided removing the loop. */
295 if (former_header
== loop
->former_header
)
297 if (former_header
->loop_father
->header
== former_header
)
298 fprintf (dump_file
, "fix_loop_structure: rediscovered "
299 "removed loop %d as loop %d with old header %d\n",
300 loop
->num
, former_header
->loop_father
->num
,
301 former_header
->index
);
302 else if ((unsigned) former_header
->loop_father
->num
304 fprintf (dump_file
, "fix_loop_structure: header %d of "
305 "removed loop %d is part of the newly "
306 "discovered loop %d with header %d\n",
307 former_header
->index
, loop
->num
,
308 former_header
->loop_father
->num
,
309 former_header
->loop_father
->header
->index
);
312 (*get_loops (cfun
))[i
] = NULL
;
313 flow_loop_free (loop
);
317 /* If we deleted loops then the cached scalar evolutions refering to
318 those loops become invalid. */
319 if (n_deleted
> 0 && scev_initialized_p ())
322 loops_state_clear (LOOPS_NEED_FIXUP
);
324 /* Apply flags to loops. */
325 apply_loop_flags (current_loops
->state
| record_exits
);
327 checking_verify_loop_structure ();
329 timevar_pop (TV_LOOP_INIT
);
331 return number_of_loops (cfun
) - old_nloops
+ n_deleted
;
334 /* The RTL loop superpass. The actual passes are subpasses. See passes.cc for
339 const pass_data pass_data_loop2
=
343 OPTGROUP_LOOP
, /* optinfo_flags */
345 0, /* properties_required */
346 0, /* properties_provided */
347 0, /* properties_destroyed */
348 0, /* todo_flags_start */
349 0, /* todo_flags_finish */
352 class pass_loop2
: public rtl_opt_pass
355 pass_loop2 (gcc::context
*ctxt
)
356 : rtl_opt_pass (pass_data_loop2
, ctxt
)
359 /* opt_pass methods: */
360 bool gate (function
*) final override
;
362 }; // class pass_loop2
365 pass_loop2::gate (function
*fun
)
368 && (flag_move_loop_invariants
369 || flag_unswitch_loops
371 || (flag_branch_on_count_reg
&& targetm
.have_doloop_end ())
372 || cfun
->has_unroll
))
376 /* No longer preserve loops, remove them now. */
377 fun
->curr_properties
&= ~PROP_loops
;
379 loop_optimizer_finalize ();
387 make_pass_loop2 (gcc::context
*ctxt
)
389 return new pass_loop2 (ctxt
);
393 /* Initialization of the RTL loop passes. */
397 gcc_assert (current_ir_type () == IR_RTL_CFGLAYOUT
);
401 dump_reg_info (dump_file
);
402 dump_flow_info (dump_file
, dump_flags
);
405 loop_optimizer_init (LOOPS_NORMAL
| LOOPS_HAVE_RECORDED_EXITS
);
411 const pass_data pass_data_rtl_loop_init
=
414 "loop2_init", /* name */
415 OPTGROUP_LOOP
, /* optinfo_flags */
417 0, /* properties_required */
418 0, /* properties_provided */
419 0, /* properties_destroyed */
420 0, /* todo_flags_start */
421 0, /* todo_flags_finish */
424 class pass_rtl_loop_init
: public rtl_opt_pass
427 pass_rtl_loop_init (gcc::context
*ctxt
)
428 : rtl_opt_pass (pass_data_rtl_loop_init
, ctxt
)
431 /* opt_pass methods: */
432 unsigned int execute (function
*) final override
{ return rtl_loop_init (); }
434 }; // class pass_rtl_loop_init
439 make_pass_rtl_loop_init (gcc::context
*ctxt
)
441 return new pass_rtl_loop_init (ctxt
);
445 /* Finalization of the RTL loop passes. */
449 const pass_data pass_data_rtl_loop_done
=
452 "loop2_done", /* name */
453 OPTGROUP_LOOP
, /* optinfo_flags */
455 0, /* properties_required */
456 0, /* properties_provided */
457 PROP_loops
, /* properties_destroyed */
458 0, /* todo_flags_start */
459 0, /* todo_flags_finish */
462 class pass_rtl_loop_done
: public rtl_opt_pass
465 pass_rtl_loop_done (gcc::context
*ctxt
)
466 : rtl_opt_pass (pass_data_rtl_loop_done
, ctxt
)
469 /* opt_pass methods: */
470 unsigned int execute (function
*) final override
;
472 }; // class pass_rtl_loop_done
475 pass_rtl_loop_done::execute (function
*fun
)
477 /* No longer preserve loops, remove them now. */
478 fun
->curr_properties
&= ~PROP_loops
;
479 loop_optimizer_finalize ();
480 free_dominance_info (CDI_DOMINATORS
);
485 dump_reg_info (dump_file
);
486 dump_flow_info (dump_file
, dump_flags
);
495 make_pass_rtl_loop_done (gcc::context
*ctxt
)
497 return new pass_rtl_loop_done (ctxt
);
501 /* Loop invariant code motion. */
505 const pass_data pass_data_rtl_move_loop_invariants
=
508 "loop2_invariant", /* name */
509 OPTGROUP_LOOP
, /* optinfo_flags */
510 TV_LOOP_MOVE_INVARIANTS
, /* tv_id */
511 0, /* properties_required */
512 0, /* properties_provided */
513 0, /* properties_destroyed */
514 0, /* todo_flags_start */
515 ( TODO_df_verify
| TODO_df_finish
), /* todo_flags_finish */
518 class pass_rtl_move_loop_invariants
: public rtl_opt_pass
521 pass_rtl_move_loop_invariants (gcc::context
*ctxt
)
522 : rtl_opt_pass (pass_data_rtl_move_loop_invariants
, ctxt
)
525 /* opt_pass methods: */
526 bool gate (function
*) final override
{ return flag_move_loop_invariants
; }
527 unsigned int execute (function
*fun
) final override
529 if (number_of_loops (fun
) > 1)
530 move_loop_invariants ();
534 }; // class pass_rtl_move_loop_invariants
539 make_pass_rtl_move_loop_invariants (gcc::context
*ctxt
)
541 return new pass_rtl_move_loop_invariants (ctxt
);
547 const pass_data pass_data_rtl_unroll_loops
=
550 "loop2_unroll", /* name */
551 OPTGROUP_LOOP
, /* optinfo_flags */
552 TV_LOOP_UNROLL
, /* tv_id */
553 0, /* properties_required */
554 0, /* properties_provided */
555 0, /* properties_destroyed */
556 0, /* todo_flags_start */
557 0, /* todo_flags_finish */
560 class pass_rtl_unroll_loops
: public rtl_opt_pass
563 pass_rtl_unroll_loops (gcc::context
*ctxt
)
564 : rtl_opt_pass (pass_data_rtl_unroll_loops
, ctxt
)
567 /* opt_pass methods: */
568 bool gate (function
*) final override
570 return (flag_unroll_loops
|| flag_unroll_all_loops
571 || cfun
->has_unroll
);
574 unsigned int execute (function
*) final override
;
576 }; // class pass_rtl_unroll_loops
579 pass_rtl_unroll_loops::execute (function
*fun
)
581 if (number_of_loops (fun
) > 1)
587 if (flag_unroll_loops
)
589 if (flag_unroll_all_loops
)
590 flags
|= UAP_UNROLL_ALL
;
592 unroll_loops (flags
);
600 make_pass_rtl_unroll_loops (gcc::context
*ctxt
)
602 return new pass_rtl_unroll_loops (ctxt
);
608 const pass_data pass_data_rtl_doloop
=
611 "loop2_doloop", /* name */
612 OPTGROUP_LOOP
, /* optinfo_flags */
613 TV_LOOP_DOLOOP
, /* tv_id */
614 0, /* properties_required */
615 0, /* properties_provided */
616 0, /* properties_destroyed */
617 0, /* todo_flags_start */
618 0, /* todo_flags_finish */
621 class pass_rtl_doloop
: public rtl_opt_pass
624 pass_rtl_doloop (gcc::context
*ctxt
)
625 : rtl_opt_pass (pass_data_rtl_doloop
, ctxt
)
628 /* opt_pass methods: */
629 bool gate (function
*) final override
;
630 unsigned int execute (function
*) final override
;
632 }; // class pass_rtl_doloop
635 pass_rtl_doloop::gate (function
*)
637 return (flag_branch_on_count_reg
&& targetm
.have_doloop_end ());
641 pass_rtl_doloop::execute (function
*fun
)
643 if (number_of_loops (fun
) > 1)
644 doloop_optimize_loops ();
651 make_pass_rtl_doloop (gcc::context
*ctxt
)
653 return new pass_rtl_doloop (ctxt
);