diff mbox series

[RFC/PATCH] Use range-based for loops for traversing loops

Message ID 0a8b77ba-1d54-1eff-b54d-d2cb1e769e09@linux.ibm.com
State New
Headers show
Series [RFC/PATCH] Use range-based for loops for traversing loops | expand

Commit Message

Kewen.Lin July 19, 2021, 6:20 a.m. UTC
Hi,

This patch follows Martin's suggestion here[1], to support
range-based for loops for traversing loops, analogously to
the patch for vec[2].

Bootstrapped and regtested on powerpc64le-linux-gnu P9,
x86_64-redhat-linux and aarch64-linux-gnu, also
bootstrapped on ppc64le P9 with bootstrap-O3 config.

Any comments are appreciated.

BR,
Kewen

[1] https://gcc.gnu.org/pipermail/gcc-patches/2021-June/573424.html
[2] https://gcc.gnu.org/pipermail/gcc-patches/2021-June/572315.html
-----
gcc/ChangeLog:

	* cfgloop.h (class loop_iterator): Rename to ...
	(class loops_list): ... this.
	(loop_iterator::next): Rename to ...
	(loops_list::iterator::fill_curr_loop): ... this and adjust.
	(loop_iterator::loop_iterator): Rename to ...
	(loops_list::loops_list): ... this and adjust.
	(FOR_EACH_LOOP): Rename to ...
	(ALL_LOOPS): ... this.
	(FOR_EACH_LOOP_FN): Rename to ...
	(ALL_LOOPS_FN): this.
	(loops_list::iterator): New class.
	(loops_list::begin): New function.
	(loops_list::end): Likewise.
	* cfgloop.c (flow_loops_dump): Adjust FOR_EACH_LOOP* with ALL_LOOPS*.
	(sort_sibling_loops): Likewise.
	(disambiguate_loops_with_multiple_latches): Likewise.
	(verify_loop_structure): Likewise.
	* cfgloopmanip.c (create_preheaders): Likewise.
	(force_single_succ_latches): Likewise.
	* config/aarch64/falkor-tag-collision-avoidance.c
	(execute_tag_collision_avoidance): Likewise.
	* config/mn10300/mn10300.c (mn10300_scan_for_setlb_lcc): Likewise.
	* config/s390/s390.c (s390_adjust_loops): Likewise.
	* doc/loop.texi: Likewise.
	* gimple-loop-interchange.cc (pass_linterchange::execute): Likewise.
	* gimple-loop-jam.c (tree_loop_unroll_and_jam): Likewise.
	* gimple-loop-versioning.cc (loop_versioning::analyze_blocks): Likewise.
	(loop_versioning::make_versioning_decisions): Likewise.
	* gimple-ssa-split-paths.c (split_paths): Likewise.
	* graphite-isl-ast-to-gimple.c (graphite_regenerate_ast_isl): Likewise.
	* graphite.c (canonicalize_loop_form): Likewise.
	(graphite_transform_loops): Likewise.
	* ipa-fnsummary.c (analyze_function_body): Likewise.
	* ipa-pure-const.c (analyze_function): Likewise.
	* loop-doloop.c (doloop_optimize_loops): Likewise.
	* loop-init.c (loop_optimizer_finalize): Likewise.
	(fix_loop_structure): Likewise.
	* loop-invariant.c (calculate_loop_reg_pressure): Likewise.
	(move_loop_invariants): Likewise.
	* loop-unroll.c (decide_unrolling): Likewise.
	(unroll_loops): Likewise.
	* modulo-sched.c (sms_schedule): Likewise.
	* predict.c (predict_loops): Likewise.
	(pass_profile::execute): Likewise.
	* profile.c (branch_prob): Likewise.
	* sel-sched-ir.c (sel_finish_pipelining): Likewise.
	(sel_find_rgns): Likewise.
	* tree-cfg.c (replace_loop_annotate): Likewise.
	(replace_uses_by): Likewise.
	(move_sese_region_to_fn): Likewise.
	* tree-if-conv.c (pass_if_conversion::execute): Likewise.
	* tree-loop-distribution.c (loop_distribution::execute): Likewise.
	* tree-parloops.c (parallelize_loops): Likewise.
	* tree-predcom.c (tree_predictive_commoning): Likewise.
	* tree-scalar-evolution.c (scev_initialize): Likewise.
	(scev_reset): Likewise.
	* tree-ssa-dce.c (find_obviously_necessary_stmts): Likewise.
	* tree-ssa-live.c (remove_unused_locals): Likewise.
	* tree-ssa-loop-ch.c (ch_base::copy_headers): Likewise.
	* tree-ssa-loop-im.c (analyze_memory_references): Likewise.
	(tree_ssa_lim_initialize): Likewise.
	* tree-ssa-loop-ivcanon.c (canonicalize_induction_variables): Likewise.
	* tree-ssa-loop-ivopts.c (tree_ssa_iv_optimize): Likewise.
	* tree-ssa-loop-manip.c (get_loops_exits): Likewise.
	* tree-ssa-loop-niter.c (estimate_numbers_of_iterations): Likewise.
	(free_numbers_of_iterations_estimates): Likewise.
	* tree-ssa-loop-prefetch.c (tree_ssa_prefetch_arrays): Likewise.
	* tree-ssa-loop-split.c (tree_ssa_split_loops): Likewise.
	* tree-ssa-loop-unswitch.c (tree_ssa_unswitch_loops): Likewise.
	* tree-ssa-loop.c (gate_oacc_kernels): Likewise.
	(pass_scev_cprop::execute): Likewise.
	* tree-ssa-propagate.c (clean_up_loop_closed_phi): Likewise.
	* tree-ssa-sccvn.c (do_rpo_vn): Likewise.
	* tree-ssa-threadupdate.c
	(jump_thread_path_registry::thread_through_all_blocks): Likewise.
	* tree-vectorizer.c (vectorize_loops): Likewise.
	* tree-vrp.c (vrp_asserts::find_assert_locations): Likewise.
---
 gcc/cfgloop.c                                 |  19 ++-
 gcc/cfgloop.h                                 | 115 +++++++++++++-----
 gcc/cfgloopmanip.c                            |   7 +-
 .../aarch64/falkor-tag-collision-avoidance.c  |   4 +-
 gcc/config/mn10300/mn10300.c                  |   4 +-
 gcc/config/s390/s390.c                        |   4 +-
 gcc/doc/loop.texi                             |   2 +-
 gcc/gimple-loop-interchange.cc                |   3 +-
 gcc/gimple-loop-jam.c                         |   3 +-
 gcc/gimple-loop-versioning.cc                 |   6 +-
 gcc/gimple-ssa-split-paths.c                  |   3 +-
 gcc/graphite-isl-ast-to-gimple.c              |   5 +-
 gcc/graphite.c                                |   6 +-
 gcc/ipa-fnsummary.c                           |   2 +-
 gcc/ipa-pure-const.c                          |   3 +-
 gcc/loop-doloop.c                             |   8 +-
 gcc/loop-init.c                               |   5 +-
 gcc/loop-invariant.c                          |  14 +--
 gcc/loop-unroll.c                             |   7 +-
 gcc/modulo-sched.c                            |   5 +-
 gcc/predict.c                                 |   5 +-
 gcc/profile.c                                 |   3 +-
 gcc/sel-sched-ir.c                            |  12 +-
 gcc/tree-cfg.c                                |  13 +-
 gcc/tree-if-conv.c                            |   3 +-
 gcc/tree-loop-distribution.c                  |   2 +-
 gcc/tree-parloops.c                           |   3 +-
 gcc/tree-predcom.c                            |   3 +-
 gcc/tree-scalar-evolution.c                   |  16 +--
 gcc/tree-ssa-dce.c                            |   3 +-
 gcc/tree-ssa-live.c                           |   3 +-
 gcc/tree-ssa-loop-ch.c                        |   3 +-
 gcc/tree-ssa-loop-im.c                        |   7 +-
 gcc/tree-ssa-loop-ivcanon.c                   |   3 +-
 gcc/tree-ssa-loop-ivopts.c                    |   3 +-
 gcc/tree-ssa-loop-manip.c                     |   3 +-
 gcc/tree-ssa-loop-niter.c                     |   8 +-
 gcc/tree-ssa-loop-prefetch.c                  |   3 +-
 gcc/tree-ssa-loop-split.c                     |   7 +-
 gcc/tree-ssa-loop-unswitch.c                  |   3 +-
 gcc/tree-ssa-loop.c                           |   6 +-
 gcc/tree-ssa-propagate.c                      |   3 +-
 gcc/tree-ssa-sccvn.c                          |   3 +-
 gcc/tree-ssa-threadupdate.c                   |   3 +-
 gcc/tree-vectorizer.c                         |   4 +-
 gcc/tree-vrp.c                                |   3 +-
 46 files changed, 164 insertions(+), 189 deletions(-)

Comments

Andrew Pinski July 19, 2021, 6:26 a.m. UTC | #1
On Sun, Jul 18, 2021 at 11:21 PM Kewen.Lin via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> Hi,
>
> This patch follows Martin's suggestion here[1], to support
> range-based for loops for traversing loops, analogously to
> the patch for vec[2].
>
> Bootstrapped and regtested on powerpc64le-linux-gnu P9,
> x86_64-redhat-linux and aarch64-linux-gnu, also
> bootstrapped on ppc64le P9 with bootstrap-O3 config.
>
> Any comments are appreciated.

+1 from me (note I did not review the patch but I like the idea).

Thanks,
Andrew

>
> BR,
> Kewen
>
> [1] https://gcc.gnu.org/pipermail/gcc-patches/2021-June/573424.html
> [2] https://gcc.gnu.org/pipermail/gcc-patches/2021-June/572315.html
> -----
> gcc/ChangeLog:
>
>         * cfgloop.h (class loop_iterator): Rename to ...
>         (class loops_list): ... this.
>         (loop_iterator::next): Rename to ...
>         (loops_list::iterator::fill_curr_loop): ... this and adjust.
>         (loop_iterator::loop_iterator): Rename to ...
>         (loops_list::loops_list): ... this and adjust.
>         (FOR_EACH_LOOP): Rename to ...
>         (ALL_LOOPS): ... this.
>         (FOR_EACH_LOOP_FN): Rename to ...
>         (ALL_LOOPS_FN): this.
>         (loops_list::iterator): New class.
>         (loops_list::begin): New function.
>         (loops_list::end): Likewise.
>         * cfgloop.c (flow_loops_dump): Adjust FOR_EACH_LOOP* with ALL_LOOPS*.
>         (sort_sibling_loops): Likewise.
>         (disambiguate_loops_with_multiple_latches): Likewise.
>         (verify_loop_structure): Likewise.
>         * cfgloopmanip.c (create_preheaders): Likewise.
>         (force_single_succ_latches): Likewise.
>         * config/aarch64/falkor-tag-collision-avoidance.c
>         (execute_tag_collision_avoidance): Likewise.
>         * config/mn10300/mn10300.c (mn10300_scan_for_setlb_lcc): Likewise.
>         * config/s390/s390.c (s390_adjust_loops): Likewise.
>         * doc/loop.texi: Likewise.
>         * gimple-loop-interchange.cc (pass_linterchange::execute): Likewise.
>         * gimple-loop-jam.c (tree_loop_unroll_and_jam): Likewise.
>         * gimple-loop-versioning.cc (loop_versioning::analyze_blocks): Likewise.
>         (loop_versioning::make_versioning_decisions): Likewise.
>         * gimple-ssa-split-paths.c (split_paths): Likewise.
>         * graphite-isl-ast-to-gimple.c (graphite_regenerate_ast_isl): Likewise.
>         * graphite.c (canonicalize_loop_form): Likewise.
>         (graphite_transform_loops): Likewise.
>         * ipa-fnsummary.c (analyze_function_body): Likewise.
>         * ipa-pure-const.c (analyze_function): Likewise.
>         * loop-doloop.c (doloop_optimize_loops): Likewise.
>         * loop-init.c (loop_optimizer_finalize): Likewise.
>         (fix_loop_structure): Likewise.
>         * loop-invariant.c (calculate_loop_reg_pressure): Likewise.
>         (move_loop_invariants): Likewise.
>         * loop-unroll.c (decide_unrolling): Likewise.
>         (unroll_loops): Likewise.
>         * modulo-sched.c (sms_schedule): Likewise.
>         * predict.c (predict_loops): Likewise.
>         (pass_profile::execute): Likewise.
>         * profile.c (branch_prob): Likewise.
>         * sel-sched-ir.c (sel_finish_pipelining): Likewise.
>         (sel_find_rgns): Likewise.
>         * tree-cfg.c (replace_loop_annotate): Likewise.
>         (replace_uses_by): Likewise.
>         (move_sese_region_to_fn): Likewise.
>         * tree-if-conv.c (pass_if_conversion::execute): Likewise.
>         * tree-loop-distribution.c (loop_distribution::execute): Likewise.
>         * tree-parloops.c (parallelize_loops): Likewise.
>         * tree-predcom.c (tree_predictive_commoning): Likewise.
>         * tree-scalar-evolution.c (scev_initialize): Likewise.
>         (scev_reset): Likewise.
>         * tree-ssa-dce.c (find_obviously_necessary_stmts): Likewise.
>         * tree-ssa-live.c (remove_unused_locals): Likewise.
>         * tree-ssa-loop-ch.c (ch_base::copy_headers): Likewise.
>         * tree-ssa-loop-im.c (analyze_memory_references): Likewise.
>         (tree_ssa_lim_initialize): Likewise.
>         * tree-ssa-loop-ivcanon.c (canonicalize_induction_variables): Likewise.
>         * tree-ssa-loop-ivopts.c (tree_ssa_iv_optimize): Likewise.
>         * tree-ssa-loop-manip.c (get_loops_exits): Likewise.
>         * tree-ssa-loop-niter.c (estimate_numbers_of_iterations): Likewise.
>         (free_numbers_of_iterations_estimates): Likewise.
>         * tree-ssa-loop-prefetch.c (tree_ssa_prefetch_arrays): Likewise.
>         * tree-ssa-loop-split.c (tree_ssa_split_loops): Likewise.
>         * tree-ssa-loop-unswitch.c (tree_ssa_unswitch_loops): Likewise.
>         * tree-ssa-loop.c (gate_oacc_kernels): Likewise.
>         (pass_scev_cprop::execute): Likewise.
>         * tree-ssa-propagate.c (clean_up_loop_closed_phi): Likewise.
>         * tree-ssa-sccvn.c (do_rpo_vn): Likewise.
>         * tree-ssa-threadupdate.c
>         (jump_thread_path_registry::thread_through_all_blocks): Likewise.
>         * tree-vectorizer.c (vectorize_loops): Likewise.
>         * tree-vrp.c (vrp_asserts::find_assert_locations): Likewise.
Jonathan Wakely July 19, 2021, 2:08 p.m. UTC | #2
On Mon, 19 Jul 2021 at 07:20, Kewen.Lin <linkw@linux.ibm.com> wrote:
>
> Hi,
>
> This patch follows Martin's suggestion here[1], to support
> range-based for loops for traversing loops, analogously to
> the patch for vec[2].
>
> Bootstrapped and regtested on powerpc64le-linux-gnu P9,
> x86_64-redhat-linux and aarch64-linux-gnu, also
> bootstrapped on ppc64le P9 with bootstrap-O3 config.
>
> Any comments are appreciated.

In the loops_list::iterator type, this looks a little strange:

+    bool
+    operator!= (const iterator &rhs) const
+    {
+      return this->curr_idx < rhs.curr_idx;
+    }
+

This works fine when the iterator type is used implicitly in a
range-based for loop, but it wouldn't work for explicit uses of the
iterator type where somebody does the != comparison with the
past-the-end iterator on on the LHS:

auto&& list ALL_LOOPS(foo);
auto end = list.end();
auto begin = list.begin();
while (--end != begin)
Richard Biener July 19, 2021, 2:34 p.m. UTC | #3
On Mon, Jul 19, 2021 at 8:20 AM Kewen.Lin <linkw@linux.ibm.com> wrote:
>
> Hi,
>
> This patch follows Martin's suggestion here[1], to support
> range-based for loops for traversing loops, analogously to
> the patch for vec[2].
>
> Bootstrapped and regtested on powerpc64le-linux-gnu P9,
> x86_64-redhat-linux and aarch64-linux-gnu, also
> bootstrapped on ppc64le P9 with bootstrap-O3 config.
>
> Any comments are appreciated.

Since you are touching all FOR_EACH_LOOP please
make implicit 'cfun' uses explicit.  I'm not sure ALL_LOOPS
should scream, I think all_loops (function *, flags) would be
nicer.

Note I'm anticipating iteration over a subset of the loop tree
which would ask for specifying the 'root' of the loop tree to
iterate over so it could be

  loops_list (class loop *root, unsigned flags)

and the "all" cases use loops_list (loops_for_fn (cfun), flags) then.
Providing an overload with struct function is of course OK.

Richard.

> BR,
> Kewen
>
> [1] https://gcc.gnu.org/pipermail/gcc-patches/2021-June/573424.html
> [2] https://gcc.gnu.org/pipermail/gcc-patches/2021-June/572315.html
> -----
> gcc/ChangeLog:
>
>         * cfgloop.h (class loop_iterator): Rename to ...
>         (class loops_list): ... this.
>         (loop_iterator::next): Rename to ...
>         (loops_list::iterator::fill_curr_loop): ... this and adjust.
>         (loop_iterator::loop_iterator): Rename to ...
>         (loops_list::loops_list): ... this and adjust.
>         (FOR_EACH_LOOP): Rename to ...
>         (ALL_LOOPS): ... this.
>         (FOR_EACH_LOOP_FN): Rename to ...
>         (ALL_LOOPS_FN): this.
>         (loops_list::iterator): New class.
>         (loops_list::begin): New function.
>         (loops_list::end): Likewise.
>         * cfgloop.c (flow_loops_dump): Adjust FOR_EACH_LOOP* with ALL_LOOPS*.
>         (sort_sibling_loops): Likewise.
>         (disambiguate_loops_with_multiple_latches): Likewise.
>         (verify_loop_structure): Likewise.
>         * cfgloopmanip.c (create_preheaders): Likewise.
>         (force_single_succ_latches): Likewise.
>         * config/aarch64/falkor-tag-collision-avoidance.c
>         (execute_tag_collision_avoidance): Likewise.
>         * config/mn10300/mn10300.c (mn10300_scan_for_setlb_lcc): Likewise.
>         * config/s390/s390.c (s390_adjust_loops): Likewise.
>         * doc/loop.texi: Likewise.
>         * gimple-loop-interchange.cc (pass_linterchange::execute): Likewise.
>         * gimple-loop-jam.c (tree_loop_unroll_and_jam): Likewise.
>         * gimple-loop-versioning.cc (loop_versioning::analyze_blocks): Likewise.
>         (loop_versioning::make_versioning_decisions): Likewise.
>         * gimple-ssa-split-paths.c (split_paths): Likewise.
>         * graphite-isl-ast-to-gimple.c (graphite_regenerate_ast_isl): Likewise.
>         * graphite.c (canonicalize_loop_form): Likewise.
>         (graphite_transform_loops): Likewise.
>         * ipa-fnsummary.c (analyze_function_body): Likewise.
>         * ipa-pure-const.c (analyze_function): Likewise.
>         * loop-doloop.c (doloop_optimize_loops): Likewise.
>         * loop-init.c (loop_optimizer_finalize): Likewise.
>         (fix_loop_structure): Likewise.
>         * loop-invariant.c (calculate_loop_reg_pressure): Likewise.
>         (move_loop_invariants): Likewise.
>         * loop-unroll.c (decide_unrolling): Likewise.
>         (unroll_loops): Likewise.
>         * modulo-sched.c (sms_schedule): Likewise.
>         * predict.c (predict_loops): Likewise.
>         (pass_profile::execute): Likewise.
>         * profile.c (branch_prob): Likewise.
>         * sel-sched-ir.c (sel_finish_pipelining): Likewise.
>         (sel_find_rgns): Likewise.
>         * tree-cfg.c (replace_loop_annotate): Likewise.
>         (replace_uses_by): Likewise.
>         (move_sese_region_to_fn): Likewise.
>         * tree-if-conv.c (pass_if_conversion::execute): Likewise.
>         * tree-loop-distribution.c (loop_distribution::execute): Likewise.
>         * tree-parloops.c (parallelize_loops): Likewise.
>         * tree-predcom.c (tree_predictive_commoning): Likewise.
>         * tree-scalar-evolution.c (scev_initialize): Likewise.
>         (scev_reset): Likewise.
>         * tree-ssa-dce.c (find_obviously_necessary_stmts): Likewise.
>         * tree-ssa-live.c (remove_unused_locals): Likewise.
>         * tree-ssa-loop-ch.c (ch_base::copy_headers): Likewise.
>         * tree-ssa-loop-im.c (analyze_memory_references): Likewise.
>         (tree_ssa_lim_initialize): Likewise.
>         * tree-ssa-loop-ivcanon.c (canonicalize_induction_variables): Likewise.
>         * tree-ssa-loop-ivopts.c (tree_ssa_iv_optimize): Likewise.
>         * tree-ssa-loop-manip.c (get_loops_exits): Likewise.
>         * tree-ssa-loop-niter.c (estimate_numbers_of_iterations): Likewise.
>         (free_numbers_of_iterations_estimates): Likewise.
>         * tree-ssa-loop-prefetch.c (tree_ssa_prefetch_arrays): Likewise.
>         * tree-ssa-loop-split.c (tree_ssa_split_loops): Likewise.
>         * tree-ssa-loop-unswitch.c (tree_ssa_unswitch_loops): Likewise.
>         * tree-ssa-loop.c (gate_oacc_kernels): Likewise.
>         (pass_scev_cprop::execute): Likewise.
>         * tree-ssa-propagate.c (clean_up_loop_closed_phi): Likewise.
>         * tree-ssa-sccvn.c (do_rpo_vn): Likewise.
>         * tree-ssa-threadupdate.c
>         (jump_thread_path_registry::thread_through_all_blocks): Likewise.
>         * tree-vectorizer.c (vectorize_loops): Likewise.
>         * tree-vrp.c (vrp_asserts::find_assert_locations): Likewise.
Martin Sebor July 19, 2021, 3:59 p.m. UTC | #4
On 7/19/21 12:20 AM, Kewen.Lin wrote:
> Hi,
> 
> This patch follows Martin's suggestion here[1], to support
> range-based for loops for traversing loops, analogously to
> the patch for vec[2].
> 
> Bootstrapped and regtested on powerpc64le-linux-gnu P9,
> x86_64-redhat-linux and aarch64-linux-gnu, also
> bootstrapped on ppc64le P9 with bootstrap-O3 config.
> 
> Any comments are appreciated.

Thanks for this nice cleanup!  Just a few suggestions:

I would recommend against introducing new macros unless they
offer a significant advantage over alternatives (for the two
macros the patch adds I don't think they do).

If improving const-correctness is one of our a goals
the loops_list iterator type would need to a corresponding
const_iterator type, and const overloads of the begin()
and end() member functions.

Rather than introducing more instances of the loop_p typedef
I'd suggest to use loop *.  It has at least two advantages:
it's clearer (it's obvious it refers to a pointer), and lends
itself more readily to making code const-correct by declaring
the control variable const: for (const class loop *loop: ...)
while avoiding the mistake of using const loop_p loop to
declare a pointer to a const loop.

Martin

> 
> BR,
> Kewen
> 
> [1] https://gcc.gnu.org/pipermail/gcc-patches/2021-June/573424.html
> [2] https://gcc.gnu.org/pipermail/gcc-patches/2021-June/572315.html
> -----
> gcc/ChangeLog:
> 
> 	* cfgloop.h (class loop_iterator): Rename to ...
> 	(class loops_list): ... this.
> 	(loop_iterator::next): Rename to ...
> 	(loops_list::iterator::fill_curr_loop): ... this and adjust.
> 	(loop_iterator::loop_iterator): Rename to ...
> 	(loops_list::loops_list): ... this and adjust.
> 	(FOR_EACH_LOOP): Rename to ...
> 	(ALL_LOOPS): ... this.
> 	(FOR_EACH_LOOP_FN): Rename to ...
> 	(ALL_LOOPS_FN): this.
> 	(loops_list::iterator): New class.
> 	(loops_list::begin): New function.
> 	(loops_list::end): Likewise.
> 	* cfgloop.c (flow_loops_dump): Adjust FOR_EACH_LOOP* with ALL_LOOPS*.
> 	(sort_sibling_loops): Likewise.
> 	(disambiguate_loops_with_multiple_latches): Likewise.
> 	(verify_loop_structure): Likewise.
> 	* cfgloopmanip.c (create_preheaders): Likewise.
> 	(force_single_succ_latches): Likewise.
> 	* config/aarch64/falkor-tag-collision-avoidance.c
> 	(execute_tag_collision_avoidance): Likewise.
> 	* config/mn10300/mn10300.c (mn10300_scan_for_setlb_lcc): Likewise.
> 	* config/s390/s390.c (s390_adjust_loops): Likewise.
> 	* doc/loop.texi: Likewise.
> 	* gimple-loop-interchange.cc (pass_linterchange::execute): Likewise.
> 	* gimple-loop-jam.c (tree_loop_unroll_and_jam): Likewise.
> 	* gimple-loop-versioning.cc (loop_versioning::analyze_blocks): Likewise.
> 	(loop_versioning::make_versioning_decisions): Likewise.
> 	* gimple-ssa-split-paths.c (split_paths): Likewise.
> 	* graphite-isl-ast-to-gimple.c (graphite_regenerate_ast_isl): Likewise.
> 	* graphite.c (canonicalize_loop_form): Likewise.
> 	(graphite_transform_loops): Likewise.
> 	* ipa-fnsummary.c (analyze_function_body): Likewise.
> 	* ipa-pure-const.c (analyze_function): Likewise.
> 	* loop-doloop.c (doloop_optimize_loops): Likewise.
> 	* loop-init.c (loop_optimizer_finalize): Likewise.
> 	(fix_loop_structure): Likewise.
> 	* loop-invariant.c (calculate_loop_reg_pressure): Likewise.
> 	(move_loop_invariants): Likewise.
> 	* loop-unroll.c (decide_unrolling): Likewise.
> 	(unroll_loops): Likewise.
> 	* modulo-sched.c (sms_schedule): Likewise.
> 	* predict.c (predict_loops): Likewise.
> 	(pass_profile::execute): Likewise.
> 	* profile.c (branch_prob): Likewise.
> 	* sel-sched-ir.c (sel_finish_pipelining): Likewise.
> 	(sel_find_rgns): Likewise.
> 	* tree-cfg.c (replace_loop_annotate): Likewise.
> 	(replace_uses_by): Likewise.
> 	(move_sese_region_to_fn): Likewise.
> 	* tree-if-conv.c (pass_if_conversion::execute): Likewise.
> 	* tree-loop-distribution.c (loop_distribution::execute): Likewise.
> 	* tree-parloops.c (parallelize_loops): Likewise.
> 	* tree-predcom.c (tree_predictive_commoning): Likewise.
> 	* tree-scalar-evolution.c (scev_initialize): Likewise.
> 	(scev_reset): Likewise.
> 	* tree-ssa-dce.c (find_obviously_necessary_stmts): Likewise.
> 	* tree-ssa-live.c (remove_unused_locals): Likewise.
> 	* tree-ssa-loop-ch.c (ch_base::copy_headers): Likewise.
> 	* tree-ssa-loop-im.c (analyze_memory_references): Likewise.
> 	(tree_ssa_lim_initialize): Likewise.
> 	* tree-ssa-loop-ivcanon.c (canonicalize_induction_variables): Likewise.
> 	* tree-ssa-loop-ivopts.c (tree_ssa_iv_optimize): Likewise.
> 	* tree-ssa-loop-manip.c (get_loops_exits): Likewise.
> 	* tree-ssa-loop-niter.c (estimate_numbers_of_iterations): Likewise.
> 	(free_numbers_of_iterations_estimates): Likewise.
> 	* tree-ssa-loop-prefetch.c (tree_ssa_prefetch_arrays): Likewise.
> 	* tree-ssa-loop-split.c (tree_ssa_split_loops): Likewise.
> 	* tree-ssa-loop-unswitch.c (tree_ssa_unswitch_loops): Likewise.
> 	* tree-ssa-loop.c (gate_oacc_kernels): Likewise.
> 	(pass_scev_cprop::execute): Likewise.
> 	* tree-ssa-propagate.c (clean_up_loop_closed_phi): Likewise.
> 	* tree-ssa-sccvn.c (do_rpo_vn): Likewise.
> 	* tree-ssa-threadupdate.c
> 	(jump_thread_path_registry::thread_through_all_blocks): Likewise.
> 	* tree-vectorizer.c (vectorize_loops): Likewise.
> 	* tree-vrp.c (vrp_asserts::find_assert_locations): Likewise.
>
Kewen.Lin July 20, 2021, 8:56 a.m. UTC | #5
on 2021/7/19 下午2:26, Andrew Pinski wrote:
> On Sun, Jul 18, 2021 at 11:21 PM Kewen.Lin via Gcc-patches
> <gcc-patches@gcc.gnu.org> wrote:
>>
>> Hi,
>>
>> This patch follows Martin's suggestion here[1], to support
>> range-based for loops for traversing loops, analogously to
>> the patch for vec[2].
>>
>> Bootstrapped and regtested on powerpc64le-linux-gnu P9,
>> x86_64-redhat-linux and aarch64-linux-gnu, also
>> bootstrapped on ppc64le P9 with bootstrap-O3 config.
>>
>> Any comments are appreciated.
> 
> +1 from me (note I did not review the patch but I like the idea).
> 

Thanks Andrew!  It's actually Martin's idea.  :)

BR,
Kewen

> Thanks,
> Andrew
> 
>>
>> BR,
>> Kewen
>>
>> [1] https://gcc.gnu.org/pipermail/gcc-patches/2021-June/573424.html
>> [2] https://gcc.gnu.org/pipermail/gcc-patches/2021-June/572315.html
>> -----
>> gcc/ChangeLog:
>>
>>         * cfgloop.h (class loop_iterator): Rename to ...
>>         (class loops_list): ... this.
>>         (loop_iterator::next): Rename to ...
>>         (loops_list::iterator::fill_curr_loop): ... this and adjust.
>>         (loop_iterator::loop_iterator): Rename to ...
>>         (loops_list::loops_list): ... this and adjust.
>>         (FOR_EACH_LOOP): Rename to ...
>>         (ALL_LOOPS): ... this.
>>         (FOR_EACH_LOOP_FN): Rename to ...
>>         (ALL_LOOPS_FN): this.
>>         (loops_list::iterator): New class.
>>         (loops_list::begin): New function.
>>         (loops_list::end): Likewise.
>>         * cfgloop.c (flow_loops_dump): Adjust FOR_EACH_LOOP* with ALL_LOOPS*.
>>         (sort_sibling_loops): Likewise.
>>         (disambiguate_loops_with_multiple_latches): Likewise.
>>         (verify_loop_structure): Likewise.
>>         * cfgloopmanip.c (create_preheaders): Likewise.
>>         (force_single_succ_latches): Likewise.
>>         * config/aarch64/falkor-tag-collision-avoidance.c
>>         (execute_tag_collision_avoidance): Likewise.
>>         * config/mn10300/mn10300.c (mn10300_scan_for_setlb_lcc): Likewise.
>>         * config/s390/s390.c (s390_adjust_loops): Likewise.
>>         * doc/loop.texi: Likewise.
>>         * gimple-loop-interchange.cc (pass_linterchange::execute): Likewise.
>>         * gimple-loop-jam.c (tree_loop_unroll_and_jam): Likewise.
>>         * gimple-loop-versioning.cc (loop_versioning::analyze_blocks): Likewise.
>>         (loop_versioning::make_versioning_decisions): Likewise.
>>         * gimple-ssa-split-paths.c (split_paths): Likewise.
>>         * graphite-isl-ast-to-gimple.c (graphite_regenerate_ast_isl): Likewise.
>>         * graphite.c (canonicalize_loop_form): Likewise.
>>         (graphite_transform_loops): Likewise.
>>         * ipa-fnsummary.c (analyze_function_body): Likewise.
>>         * ipa-pure-const.c (analyze_function): Likewise.
>>         * loop-doloop.c (doloop_optimize_loops): Likewise.
>>         * loop-init.c (loop_optimizer_finalize): Likewise.
>>         (fix_loop_structure): Likewise.
>>         * loop-invariant.c (calculate_loop_reg_pressure): Likewise.
>>         (move_loop_invariants): Likewise.
>>         * loop-unroll.c (decide_unrolling): Likewise.
>>         (unroll_loops): Likewise.
>>         * modulo-sched.c (sms_schedule): Likewise.
>>         * predict.c (predict_loops): Likewise.
>>         (pass_profile::execute): Likewise.
>>         * profile.c (branch_prob): Likewise.
>>         * sel-sched-ir.c (sel_finish_pipelining): Likewise.
>>         (sel_find_rgns): Likewise.
>>         * tree-cfg.c (replace_loop_annotate): Likewise.
>>         (replace_uses_by): Likewise.
>>         (move_sese_region_to_fn): Likewise.
>>         * tree-if-conv.c (pass_if_conversion::execute): Likewise.
>>         * tree-loop-distribution.c (loop_distribution::execute): Likewise.
>>         * tree-parloops.c (parallelize_loops): Likewise.
>>         * tree-predcom.c (tree_predictive_commoning): Likewise.
>>         * tree-scalar-evolution.c (scev_initialize): Likewise.
>>         (scev_reset): Likewise.
>>         * tree-ssa-dce.c (find_obviously_necessary_stmts): Likewise.
>>         * tree-ssa-live.c (remove_unused_locals): Likewise.
>>         * tree-ssa-loop-ch.c (ch_base::copy_headers): Likewise.
>>         * tree-ssa-loop-im.c (analyze_memory_references): Likewise.
>>         (tree_ssa_lim_initialize): Likewise.
>>         * tree-ssa-loop-ivcanon.c (canonicalize_induction_variables): Likewise.
>>         * tree-ssa-loop-ivopts.c (tree_ssa_iv_optimize): Likewise.
>>         * tree-ssa-loop-manip.c (get_loops_exits): Likewise.
>>         * tree-ssa-loop-niter.c (estimate_numbers_of_iterations): Likewise.
>>         (free_numbers_of_iterations_estimates): Likewise.
>>         * tree-ssa-loop-prefetch.c (tree_ssa_prefetch_arrays): Likewise.
>>         * tree-ssa-loop-split.c (tree_ssa_split_loops): Likewise.
>>         * tree-ssa-loop-unswitch.c (tree_ssa_unswitch_loops): Likewise.
>>         * tree-ssa-loop.c (gate_oacc_kernels): Likewise.
>>         (pass_scev_cprop::execute): Likewise.
>>         * tree-ssa-propagate.c (clean_up_loop_closed_phi): Likewise.
>>         * tree-ssa-sccvn.c (do_rpo_vn): Likewise.
>>         * tree-ssa-threadupdate.c
>>         (jump_thread_path_registry::thread_through_all_blocks): Likewise.
>>         * tree-vectorizer.c (vectorize_loops): Likewise.
>>         * tree-vrp.c (vrp_asserts::find_assert_locations): Likewise.
Kewen.Lin July 20, 2021, 8:56 a.m. UTC | #6
on 2021/7/19 下午10:08, Jonathan Wakely wrote:
> On Mon, 19 Jul 2021 at 07:20, Kewen.Lin <linkw@linux.ibm.com> wrote:
>>
>> Hi,
>>
>> This patch follows Martin's suggestion here[1], to support
>> range-based for loops for traversing loops, analogously to
>> the patch for vec[2].
>>
>> Bootstrapped and regtested on powerpc64le-linux-gnu P9,
>> x86_64-redhat-linux and aarch64-linux-gnu, also
>> bootstrapped on ppc64le P9 with bootstrap-O3 config.
>>
>> Any comments are appreciated.
> 
> In the loops_list::iterator type, this looks a little strange:
> 
> +    bool
> +    operator!= (const iterator &rhs) const
> +    {
> +      return this->curr_idx < rhs.curr_idx;
> +    }
> +
> 
> This works fine when the iterator type is used implicitly in a
> range-based for loop, but it wouldn't work for explicit uses of the
> iterator type where somebody does the != comparison with the
> past-the-end iterator on on the LHS:
> 
> auto&& list ALL_LOOPS(foo);
> auto end = list.end();
> auto begin = list.begin();
> while (--end != begin)
> 

Thanks for the comments, Jonathan.  Yeah, to use "!=" is better
for clear meaning and later extension.  It was under the assumption
that the index can only increase (only supports operator++()), so
I simply used "<".  Will fix it in V2.

BR,
Kewen
Kewen.Lin July 20, 2021, 8:57 a.m. UTC | #7
on 2021/7/19 下午10:34, Richard Biener wrote:
> On Mon, Jul 19, 2021 at 8:20 AM Kewen.Lin <linkw@linux.ibm.com> wrote:
>>
>> Hi,
>>
>> This patch follows Martin's suggestion here[1], to support
>> range-based for loops for traversing loops, analogously to
>> the patch for vec[2].
>>
>> Bootstrapped and regtested on powerpc64le-linux-gnu P9,
>> x86_64-redhat-linux and aarch64-linux-gnu, also
>> bootstrapped on ppc64le P9 with bootstrap-O3 config.
>>
>> Any comments are appreciated.
> 
> Since you are touching all FOR_EACH_LOOP please
> make implicit 'cfun' uses explicit.  I'm not sure ALL_LOOPS
> should scream, I think all_loops (function *, flags) would be
> nicer.
> 
> Note I'm anticipating iteration over a subset of the loop tree
> which would ask for specifying the 'root' of the loop tree to
> iterate over so it could be
> 
>   loops_list (class loop *root, unsigned flags)
> 
> and the "all" cases use loops_list (loops_for_fn (cfun), flags) then.
> Providing an overload with struct function is of course OK.
> 

Thanks for the comments, Richi.  Will update them in V2. 
I noticed the current loop_iterator requires a struct loops*
for LI_ONLY_INNERMOST, if you don't mind, I will use

  loops_list (class loops *loops, unsigned flags)

instead to make LI_ONLY_INNERMOST happy.  Your mentioned root can
be just the tree_root of the input loops.

BR,
Kewen
Kewen.Lin July 20, 2021, 8:58 a.m. UTC | #8
on 2021/7/19 下午11:59, Martin Sebor wrote:
> On 7/19/21 12:20 AM, Kewen.Lin wrote:
>> Hi,
>>
>> This patch follows Martin's suggestion here[1], to support
>> range-based for loops for traversing loops, analogously to
>> the patch for vec[2].
>>
>> Bootstrapped and regtested on powerpc64le-linux-gnu P9,
>> x86_64-redhat-linux and aarch64-linux-gnu, also
>> bootstrapped on ppc64le P9 with bootstrap-O3 config.
>>
>> Any comments are appreciated.
> 
> Thanks for this nice cleanup!  Just a few suggestions:
> 
> I would recommend against introducing new macros unless they
> offer a significant advantage over alternatives (for the two
> macros the patch adds I don't think they do).
> 
> If improving const-correctness is one of our a goals
> the loops_list iterator type would need to a corresponding
> const_iterator type, and const overloads of the begin()
> and end() member functions.
> 
> Rather than introducing more instances of the loop_p typedef
> I'd suggest to use loop *.  It has at least two advantages:
> it's clearer (it's obvious it refers to a pointer), and lends
> itself more readily to making code const-correct by declaring
> the control variable const: for (const class loop *loop: ...)
> while avoiding the mistake of using const loop_p loop to
> declare a pointer to a const loop.
> 

Thanks for the suggestions, Martin!  Will update them in V2.

With some experiments, I noticed that even provided const_iterator
like:

   iterator
   begin ()
   {
     return iterator (*this, 0);
   }

+  const_iterator
+  begin () const
+  {
+    return const_iterator (*this, 0);
+  }

for (const class loop *loop: ...) will still use iterator instead
of const_iterator pair.  We have to make the code look like:

  const auto& const_loops = loops_list (...);
  for (const class loop *loop: const_loops)

or
  template<typename T> constexpr const T &as_const(T &t) noexcept { return t; }
  for (const class loop *loop: as_const(loops_list...)) 

Does it look good to add below as_const along with loops_list in cfgloop.h?

+/* Provide the functionality of std::as_const to support range-based for
+   to use const iterator.  (We can't use std::as_const itself because it's
+   a C++17 feature.)  */
+template <typename T>
+constexpr const T &
+as_const (T &t) noexcept
+{
+  return t;
+}
+

BR,
Kewen
Jonathan Wakely July 20, 2021, 9:49 a.m. UTC | #9
On Tue, 20 Jul 2021 at 09:58, Kewen.Lin <linkw@linux.ibm.com> wrote:
>
> on 2021/7/19 下午11:59, Martin Sebor wrote:
> > On 7/19/21 12:20 AM, Kewen.Lin wrote:
> >> Hi,
> >>
> >> This patch follows Martin's suggestion here[1], to support
> >> range-based for loops for traversing loops, analogously to
> >> the patch for vec[2].
> >>
> >> Bootstrapped and regtested on powerpc64le-linux-gnu P9,
> >> x86_64-redhat-linux and aarch64-linux-gnu, also
> >> bootstrapped on ppc64le P9 with bootstrap-O3 config.
> >>
> >> Any comments are appreciated.
> >
> > Thanks for this nice cleanup!  Just a few suggestions:
> >
> > I would recommend against introducing new macros unless they
> > offer a significant advantage over alternatives (for the two
> > macros the patch adds I don't think they do).
> >
> > If improving const-correctness is one of our a goals
> > the loops_list iterator type would need to a corresponding
> > const_iterator type, and const overloads of the begin()
> > and end() member functions.
> >
> > Rather than introducing more instances of the loop_p typedef
> > I'd suggest to use loop *.  It has at least two advantages:
> > it's clearer (it's obvious it refers to a pointer), and lends
> > itself more readily to making code const-correct by declaring
> > the control variable const: for (const class loop *loop: ...)
> > while avoiding the mistake of using const loop_p loop to
> > declare a pointer to a const loop.
> >
>
> Thanks for the suggestions, Martin!  Will update them in V2.
>
> With some experiments, I noticed that even provided const_iterator
> like:
>
>    iterator
>    begin ()
>    {
>      return iterator (*this, 0);
>    }
>
> +  const_iterator
> +  begin () const
> +  {
> +    return const_iterator (*this, 0);
> +  }
>
> for (const class loop *loop: ...) will still use iterator instead
> of const_iterator pair.  We have to make the code look like:
>
>   const auto& const_loops = loops_list (...);
>   for (const class loop *loop: const_loops)
>
> or
>   template<typename T> constexpr const T &as_const(T &t) noexcept { return t; }
>   for (const class loop *loop: as_const(loops_list...))
>
> Does it look good to add below as_const along with loops_list in cfgloop.h?
>
> +/* Provide the functionality of std::as_const to support range-based for
> +   to use const iterator.  (We can't use std::as_const itself because it's
> +   a C++17 feature.)  */
> +template <typename T>
> +constexpr const T &
> +as_const (T &t) noexcept

The noexcept is not needed because GCC is built -fno-exceptions. For
consistency with all the other code that doesn't use noexcept, it
should probably not be there.

> +{
> +  return t;
> +}
> +

That's one option. Another option (which could coexist with as_const)
is to add cbegin() and cend() members, which are not overloaded for
const and non-const, and so always return a const_iterator:

const_iterator cbegin () const { return const_iterator (*this, 0); }
iterator begin () const { return cbegin(); }

And similarly for `end () const` and `cend () const`.
Jonathan Wakely July 20, 2021, 9:50 a.m. UTC | #10
On Tue, 20 Jul 2021 at 10:49, Jonathan Wakely <jwakely.gcc@gmail.com> wrote:
>
> On Tue, 20 Jul 2021 at 09:58, Kewen.Lin <linkw@linux.ibm.com> wrote:
> >
> > on 2021/7/19 下午11:59, Martin Sebor wrote:
> > > On 7/19/21 12:20 AM, Kewen.Lin wrote:
> > >> Hi,
> > >>
> > >> This patch follows Martin's suggestion here[1], to support
> > >> range-based for loops for traversing loops, analogously to
> > >> the patch for vec[2].
> > >>
> > >> Bootstrapped and regtested on powerpc64le-linux-gnu P9,
> > >> x86_64-redhat-linux and aarch64-linux-gnu, also
> > >> bootstrapped on ppc64le P9 with bootstrap-O3 config.
> > >>
> > >> Any comments are appreciated.
> > >
> > > Thanks for this nice cleanup!  Just a few suggestions:
> > >
> > > I would recommend against introducing new macros unless they
> > > offer a significant advantage over alternatives (for the two
> > > macros the patch adds I don't think they do).
> > >
> > > If improving const-correctness is one of our a goals
> > > the loops_list iterator type would need to a corresponding
> > > const_iterator type, and const overloads of the begin()
> > > and end() member functions.
> > >
> > > Rather than introducing more instances of the loop_p typedef
> > > I'd suggest to use loop *.  It has at least two advantages:
> > > it's clearer (it's obvious it refers to a pointer), and lends
> > > itself more readily to making code const-correct by declaring
> > > the control variable const: for (const class loop *loop: ...)
> > > while avoiding the mistake of using const loop_p loop to
> > > declare a pointer to a const loop.
> > >
> >
> > Thanks for the suggestions, Martin!  Will update them in V2.
> >
> > With some experiments, I noticed that even provided const_iterator
> > like:
> >
> >    iterator
> >    begin ()
> >    {
> >      return iterator (*this, 0);
> >    }
> >
> > +  const_iterator
> > +  begin () const
> > +  {
> > +    return const_iterator (*this, 0);
> > +  }
> >
> > for (const class loop *loop: ...) will still use iterator instead
> > of const_iterator pair.  We have to make the code look like:
> >
> >   const auto& const_loops = loops_list (...);
> >   for (const class loop *loop: const_loops)
> >
> > or
> >   template<typename T> constexpr const T &as_const(T &t) noexcept { return t; }
> >   for (const class loop *loop: as_const(loops_list...))
> >
> > Does it look good to add below as_const along with loops_list in cfgloop.h?
> >
> > +/* Provide the functionality of std::as_const to support range-based for
> > +   to use const iterator.  (We can't use std::as_const itself because it's
> > +   a C++17 feature.)  */
> > +template <typename T>
> > +constexpr const T &
> > +as_const (T &t) noexcept
>
> The noexcept is not needed because GCC is built -fno-exceptions. For
> consistency with all the other code that doesn't use noexcept, it
> should probably not be there.
>
> > +{
> > +  return t;
> > +}
> > +
>
> That's one option. Another option (which could coexist with as_const)
> is to add cbegin() and cend() members, which are not overloaded for
> const and non-const, and so always return a const_iterator:
>
> const_iterator cbegin () const { return const_iterator (*this, 0); }
> iterator begin () const { return cbegin(); }
>
> And similarly for `end () const` and `cend () const`.

The range-based for loop would not use cbegin and cend, so you'd still
want to use as_const for that purpose.
Kewen.Lin July 20, 2021, 2:42 p.m. UTC | #11
on 2021/7/20 下午5:49, Jonathan Wakely wrote:
> On Tue, 20 Jul 2021 at 09:58, Kewen.Lin <linkw@linux.ibm.com> wrote:
>>
>> on 2021/7/19 下午11:59, Martin Sebor wrote:
>>> On 7/19/21 12:20 AM, Kewen.Lin wrote:
>>>> Hi,
>>>>
>>>> This patch follows Martin's suggestion here[1], to support
>>>> range-based for loops for traversing loops, analogously to
>>>> the patch for vec[2].
>>>>
>>>> Bootstrapped and regtested on powerpc64le-linux-gnu P9,
>>>> x86_64-redhat-linux and aarch64-linux-gnu, also
>>>> bootstrapped on ppc64le P9 with bootstrap-O3 config.
>>>>
>>>> Any comments are appreciated.
>>>
>>> Thanks for this nice cleanup!  Just a few suggestions:
>>>
>>> I would recommend against introducing new macros unless they
>>> offer a significant advantage over alternatives (for the two
>>> macros the patch adds I don't think they do).
>>>
>>> If improving const-correctness is one of our a goals
>>> the loops_list iterator type would need to a corresponding
>>> const_iterator type, and const overloads of the begin()
>>> and end() member functions.
>>>
>>> Rather than introducing more instances of the loop_p typedef
>>> I'd suggest to use loop *.  It has at least two advantages:
>>> it's clearer (it's obvious it refers to a pointer), and lends
>>> itself more readily to making code const-correct by declaring
>>> the control variable const: for (const class loop *loop: ...)
>>> while avoiding the mistake of using const loop_p loop to
>>> declare a pointer to a const loop.
>>>
>>
>> Thanks for the suggestions, Martin!  Will update them in V2.
>>
>> With some experiments, I noticed that even provided const_iterator
>> like:
>>
>>    iterator
>>    begin ()
>>    {
>>      return iterator (*this, 0);
>>    }
>>
>> +  const_iterator
>> +  begin () const
>> +  {
>> +    return const_iterator (*this, 0);
>> +  }
>>
>> for (const class loop *loop: ...) will still use iterator instead
>> of const_iterator pair.  We have to make the code look like:
>>
>>   const auto& const_loops = loops_list (...);
>>   for (const class loop *loop: const_loops)
>>
>> or
>>   template<typename T> constexpr const T &as_const(T &t) noexcept { return t; }
>>   for (const class loop *loop: as_const(loops_list...))
>>
>> Does it look good to add below as_const along with loops_list in cfgloop.h?
>>
>> +/* Provide the functionality of std::as_const to support range-based for
>> +   to use const iterator.  (We can't use std::as_const itself because it's
>> +   a C++17 feature.)  */
>> +template <typename T>
>> +constexpr const T &
>> +as_const (T &t) noexcept
> 
> The noexcept is not needed because GCC is built -fno-exceptions. For
> consistency with all the other code that doesn't use noexcept, it
> should probably not be there.
> 

Thanks for pointing out!   Fixed it in v2.

>> +{
>> +  return t;
>> +}
>> +
> 
> That's one option. Another option (which could coexist with as_const)
> is to add cbegin() and cend() members, which are not overloaded for
> const and non-const, and so always return a const_iterator:
> 
> const_iterator cbegin () const { return const_iterator (*this, 0); }
> iterator begin () const { return cbegin(); }
> 
> And similarly for `end () const` and `cend () const`.
> 

Thanks for the suggestion.  As you pointed out in the later reply, the
range-based for loop doesn't use cbegin and cend, so I didn't add them
in v2.

BR,
Kewen
diff mbox series

Patch

diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c
index f094538b9ff..5fce39042c4 100644
--- a/gcc/cfgloop.c
+++ b/gcc/cfgloop.c
@@ -162,14 +162,12 @@  flow_loop_dump (const class loop *loop, FILE *file,
 void
 flow_loops_dump (FILE *file, void (*loop_dump_aux) (const class loop *, FILE *, int), int verbose)
 {
-  class loop *loop;
-
   if (!current_loops || ! file)
     return;
 
   fprintf (file, ";; %d loops found\n", number_of_loops (cfun));
 
-  FOR_EACH_LOOP (loop, LI_INCLUDE_ROOT)
+  for (loop_p loop : ALL_LOOPS (LI_INCLUDE_ROOT))
     {
       flow_loop_dump (loop, file, loop_dump_aux, verbose);
     }
@@ -559,8 +557,7 @@  sort_sibling_loops (function *fn)
   free (rc_order);
 
   auto_vec<loop_p, 3> siblings;
-  loop_p loop;
-  FOR_EACH_LOOP_FN (fn, loop, LI_INCLUDE_ROOT)
+  for (loop_p loop : ALL_LOOPS_FN (fn, LI_INCLUDE_ROOT))
     if (loop->inner && loop->inner->next)
       {
 	loop_p sibling = loop->inner;
@@ -836,9 +833,7 @@  disambiguate_multiple_latches (class loop *loop)
 void
 disambiguate_loops_with_multiple_latches (void)
 {
-  class loop *loop;
-
-  FOR_EACH_LOOP (loop, 0)
+  for (loop_p loop : ALL_LOOPS (0))
     {
       if (!loop->latch)
 	disambiguate_multiple_latches (loop);
@@ -1457,7 +1452,7 @@  verify_loop_structure (void)
   auto_sbitmap visited (last_basic_block_for_fn (cfun));
   bitmap_clear (visited);
   bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun));
-  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
     {
       unsigned n;
 
@@ -1503,7 +1498,7 @@  verify_loop_structure (void)
   free (bbs);
 
   /* Check headers and latches.  */
-  FOR_EACH_LOOP (loop, 0)
+  for (loop_p loop : ALL_LOOPS (0))
     {
       i = loop->num;
       if (loop->header == NULL)
@@ -1629,7 +1624,7 @@  verify_loop_structure (void)
     }
 
   /* Check the recorded loop exits.  */
-  FOR_EACH_LOOP (loop, 0)
+  for (loop_p loop : ALL_LOOPS (0))
     {
       if (!loop->exits || loop->exits->e != NULL)
 	{
@@ -1723,7 +1718,7 @@  verify_loop_structure (void)
 	  err = 1;
 	}
 
-      FOR_EACH_LOOP (loop, 0)
+      for (loop_p loop : ALL_LOOPS (0))
 	{
 	  eloops = 0;
 	  for (exit = loop->exits->next; exit->e; exit = exit->next)
diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index 5e699276c88..2cb1a1f0d5d 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -658,55 +658,115 @@  enum li_flags
   LI_ONLY_INNERMOST = 4		/* Iterate only over innermost loops.  */
 };
 
-/* The iterator for loops.  */
+/* A list for visiting loops, which contains the loop numbers instead of
+   the loop pointers.  The scope is restricted in function FN and the
+   visiting order is specified by FLAGS.  */
 
-class loop_iterator
+class loops_list
 {
 public:
-  loop_iterator (function *fn, loop_p *loop, unsigned flags);
+  loops_list (function *fn, unsigned flags);
 
-  inline loop_p next ();
+  class iterator
+  {
+  public:
+    iterator (const loops_list &l, unsigned idx) : list (l), curr_idx (idx)
+    {
+      fill_curr_loop ();
+    }
+
+    loop_p operator* () const { return curr_loop; }
+
+    iterator &
+    operator++ ()
+    {
+      if (curr_idx < list.to_visit.length ())
+	{
+	  /* Bump the index and fill a new one.  */
+	  curr_idx++;
+	  fill_curr_loop ();
+	}
+      else
+	gcc_assert (!curr_loop);
+
+      return *this;
+    }
+
+    bool
+    operator!= (const iterator &rhs) const
+    {
+      return this->curr_idx < rhs.curr_idx;
+    }
+
+  private:
+    /* Fill the current loop starting from the current index.  */
+    void fill_curr_loop ();
+
+    /* Reference to the loop list to visit.  */
+    const loops_list &list;
+
+    /* The current index in the list to visit.  */
+    unsigned curr_idx;
 
+    /* The loop implied by the current index.  */
+    loop_p curr_loop;
+  };
+
+  iterator
+  begin () const
+  {
+    return iterator (*this, 0);
+  }
+
+  iterator
+  end () const
+  {
+    return iterator (*this, to_visit.length ());
+  }
+
+private:
   /* The function we are visiting.  */
   function *fn;
 
   /* The list of loops to visit.  */
   auto_vec<int, 16> to_visit;
-
-  /* The index of the actual loop.  */
-  unsigned idx;
 };
 
-inline loop_p
-loop_iterator::next ()
+/* Starting from current index CURR_IDX (inclusive), find one index
+   which stands for one valid loop and fill the found loop as CURR_LOOP,
+   if we can't find one, set CURR_LOOP as null.  */
+
+inline void
+loops_list::iterator::fill_curr_loop ()
 {
   int anum;
 
-  while (this->to_visit.iterate (this->idx, &anum))
+  while (this->list.to_visit.iterate (this->curr_idx, &anum))
     {
-      this->idx++;
-      loop_p loop = get_loop (fn, anum);
+      loop_p loop = get_loop (this->list.fn, anum);
       if (loop)
-	return loop;
+	{
+	  curr_loop = loop;
+	  return;
+	}
+      this->curr_idx++;
     }
 
-  return NULL;
+  curr_loop = nullptr;
 }
 
-inline
-loop_iterator::loop_iterator (function *fn, loop_p *loop, unsigned flags)
+/* Set up the loops list to visit according to the specified
+   function scope FN and iterating order FLAGS.  */
+
+inline loops_list::loops_list (function *fn, unsigned flags)
 {
   class loop *aloop;
   unsigned i;
   int mn;
 
-  this->idx = 0;
   this->fn = fn;
   if (!loops_for_fn (fn))
-    {
-      *loop = NULL;
-      return;
-    }
+    return;
 
   this->to_visit.reserve_exact (number_of_loops (fn));
   mn = (flags & LI_INCLUDE_ROOT) ? 0 : 1;
@@ -766,19 +826,10 @@  loop_iterator::loop_iterator (function *fn, loop_p *loop, unsigned flags)
 	    }
 	}
     }
-
-  *loop = this->next ();
 }
 
-#define FOR_EACH_LOOP(LOOP, FLAGS) \
-  for (loop_iterator li(cfun, &(LOOP), FLAGS); \
-       (LOOP); \
-       (LOOP) = li.next ())
-
-#define FOR_EACH_LOOP_FN(FN, LOOP, FLAGS) \
-  for (loop_iterator li(FN, &(LOOP), FLAGS); \
-       (LOOP); \
-       (LOOP) = li.next ())
+#define ALL_LOOPS(FLAGS) loops_list (cfun, FLAGS)
+#define ALL_LOOPS_FN(FN, FLAGS) loops_list (FN, FLAGS)
 
 /* The properties of the target.  */
 struct target_cfgloop {
diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c
index 2af59fedc92..bf4f666a1f2 100644
--- a/gcc/cfgloopmanip.c
+++ b/gcc/cfgloopmanip.c
@@ -1572,12 +1572,10 @@  create_preheader (class loop *loop, int flags)
 void
 create_preheaders (int flags)
 {
-  class loop *loop;
-
   if (!current_loops)
     return;
 
-  FOR_EACH_LOOP (loop, 0)
+  for (loop_p loop : ALL_LOOPS (0))
     create_preheader (loop, flags);
   loops_state_set (LOOPS_HAVE_PREHEADERS);
 }
@@ -1587,10 +1585,9 @@  create_preheaders (int flags)
 void
 force_single_succ_latches (void)
 {
-  class loop *loop;
   edge e;
 
-  FOR_EACH_LOOP (loop, 0)
+  for (loop_p loop : ALL_LOOPS (0))
     {
       if (loop->latch != loop->header && single_succ_p (loop->latch))
 	continue;
diff --git a/gcc/config/aarch64/falkor-tag-collision-avoidance.c b/gcc/config/aarch64/falkor-tag-collision-avoidance.c
index de214e4a0f7..141afa23f2b 100644
--- a/gcc/config/aarch64/falkor-tag-collision-avoidance.c
+++ b/gcc/config/aarch64/falkor-tag-collision-avoidance.c
@@ -808,8 +808,6 @@  record_loads (tag_map_t &tag_map, struct loop *loop)
 void
 execute_tag_collision_avoidance ()
 {
-  struct loop *loop;
-
   df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
   df_chain_add_problem (DF_UD_CHAIN);
   df_compute_regs_ever_live (true);
@@ -824,7 +822,7 @@  execute_tag_collision_avoidance ()
   calculate_dominance_info (CDI_DOMINATORS);
   loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
 
-  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
     {
       tag_map_t tag_map (512);
 
diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c
index 6f842a3ad32..b977104bd07 100644
--- a/gcc/config/mn10300/mn10300.c
+++ b/gcc/config/mn10300/mn10300.c
@@ -3234,8 +3234,6 @@  mn10300_loop_contains_call_insn (loop_p loop)
 static void
 mn10300_scan_for_setlb_lcc (void)
 {
-  loop_p loop;
-
   DUMP ("Looking for loops that can use the SETLB insn", NULL_RTX);
 
   df_analyze ();
@@ -3248,7 +3246,7 @@  mn10300_scan_for_setlb_lcc (void)
      if an inner loop is not suitable for use with the SETLB/Lcc insns, it may
      be the case that its parent loop is suitable.  Thus we should check all
      loops, but work from the innermost outwards.  */
-  FOR_EACH_LOOP (loop, LI_ONLY_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_ONLY_INNERMOST))
     {
       const char * reason = NULL;
 
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index b1d3b99784d..df3c4361a7e 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -14479,15 +14479,13 @@  s390_adjust_loop_scan_osc (struct loop* loop)
 static void
 s390_adjust_loops ()
 {
-  struct loop *loop = NULL;
-
   df_analyze ();
   compute_bb_for_insn ();
 
   /* Find the loops.  */
   loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
 
-  FOR_EACH_LOOP (loop, LI_ONLY_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_ONLY_INNERMOST))
     {
       if (dump_file)
 	{
diff --git a/gcc/doc/loop.texi b/gcc/doc/loop.texi
index a135656ed01..310889702ec 100644
--- a/gcc/doc/loop.texi
+++ b/gcc/doc/loop.texi
@@ -80,7 +80,7 @@  and its subloops in the numbering.  The index of a loop never changes.
 The entries of the @code{larray} field should not be accessed directly.
 The function @code{get_loop} returns the loop description for a loop with
 the given index.  @code{number_of_loops} function returns number of
-loops in the function.  To traverse all loops, use @code{FOR_EACH_LOOP}
+loops in the function.  To traverse all loops, use @code{ALL_LOOPS}
 macro.  The @code{flags} argument of the macro is used to determine
 the direction of traversal and the set of loops visited.  Each loop is
 guaranteed to be visited exactly once, regardless of the changes to the
diff --git a/gcc/gimple-loop-interchange.cc b/gcc/gimple-loop-interchange.cc
index 7a88faa2c07..960885371e1 100644
--- a/gcc/gimple-loop-interchange.cc
+++ b/gcc/gimple-loop-interchange.cc
@@ -2089,8 +2089,7 @@  pass_linterchange::execute (function *fun)
     return 0;
 
   bool changed_p = false;
-  class loop *loop;
-  FOR_EACH_LOOP (loop, LI_ONLY_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_ONLY_INNERMOST))
     {
       vec<loop_p> loop_nest = vNULL;
       vec<data_reference_p> datarefs = vNULL;
diff --git a/gcc/gimple-loop-jam.c b/gcc/gimple-loop-jam.c
index 4842f0dff80..26ac06f1b8f 100644
--- a/gcc/gimple-loop-jam.c
+++ b/gcc/gimple-loop-jam.c
@@ -486,13 +486,12 @@  adjust_unroll_factor (class loop *inner, struct data_dependence_relation *ddr,
 static unsigned int
 tree_loop_unroll_and_jam (void)
 {
-  class loop *loop;
   bool changed = false;
 
   gcc_assert (scev_initialized_p ());
 
   /* Go through all innermost loops.  */
-  FOR_EACH_LOOP (loop, LI_ONLY_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_ONLY_INNERMOST))
     {
       class loop *outer = loop_outer (loop);
 
diff --git a/gcc/gimple-loop-versioning.cc b/gcc/gimple-loop-versioning.cc
index 4b70c5a4aab..d021d31b4f9 100644
--- a/gcc/gimple-loop-versioning.cc
+++ b/gcc/gimple-loop-versioning.cc
@@ -1428,8 +1428,7 @@  loop_versioning::analyze_blocks ()
      versioning at that level could be useful in some cases.  */
   get_loop_info (get_loop (m_fn, 0)).rejected_p = true;
 
-  class loop *loop;
-  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
     {
       loop_info &linfo = get_loop_info (loop);
 
@@ -1650,8 +1649,7 @@  loop_versioning::make_versioning_decisions ()
   AUTO_DUMP_SCOPE ("make_versioning_decisions",
 		   dump_user_location_t::from_function_decl (m_fn->decl));
 
-  class loop *loop;
-  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
     {
       loop_info &linfo = get_loop_info (loop);
       if (decide_whether_loop_is_versionable (loop))
diff --git a/gcc/gimple-ssa-split-paths.c b/gcc/gimple-ssa-split-paths.c
index 2dd953d5ef9..53d7924e393 100644
--- a/gcc/gimple-ssa-split-paths.c
+++ b/gcc/gimple-ssa-split-paths.c
@@ -473,13 +473,12 @@  static bool
 split_paths ()
 {
   bool changed = false;
-  loop_p loop;
 
   loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS);
   initialize_original_copy_tables ();
   calculate_dominance_info (CDI_DOMINATORS);
 
-  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
     {
       /* Only split paths if we are optimizing this loop for speed.  */
       if (!optimize_loop_for_speed_p (loop))
diff --git a/gcc/graphite-isl-ast-to-gimple.c b/gcc/graphite-isl-ast-to-gimple.c
index c202213f39b..41042a190a2 100644
--- a/gcc/graphite-isl-ast-to-gimple.c
+++ b/gcc/graphite-isl-ast-to-gimple.c
@@ -1535,9 +1535,8 @@  graphite_regenerate_ast_isl (scop_p scop)
       if_region->false_region->region.entry->flags |= EDGE_FALLTHRU;
       /* remove_edge_and_dominated_blocks marks loops for removal but
 	 doesn't actually remove them (fix that...).  */
-      loop_p loop;
-      FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
-	if (! loop->header)
+      for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
+	if (!loop->header)
 	  delete_loop (loop);
     }
 
diff --git a/gcc/graphite.c b/gcc/graphite.c
index 6c4fb42282b..13f3d74ae15 100644
--- a/gcc/graphite.c
+++ b/gcc/graphite.c
@@ -377,8 +377,7 @@  canonicalize_loop_closed_ssa (loop_p loop, edge e)
 static void
 canonicalize_loop_form (void)
 {
-  loop_p loop;
-  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
     {
       edge e = single_exit (loop);
       if (!e || (e->flags & (EDGE_COMPLEX|EDGE_FAKE)))
@@ -494,10 +493,9 @@  graphite_transform_loops (void)
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
-      loop_p loop;
       int num_no_dependency = 0;
 
-      FOR_EACH_LOOP (loop, 0)
+      for (loop_p loop : ALL_LOOPS (0))
 	if (loop->can_be_parallel)
 	  num_no_dependency++;
 
diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c
index 95d28757f95..c8e9eb4a004 100644
--- a/gcc/ipa-fnsummary.c
+++ b/gcc/ipa-fnsummary.c
@@ -2923,7 +2923,7 @@  analyze_function_body (struct cgraph_node *node, bool early)
       if (dump_file && (dump_flags & TDF_DETAILS))
 	flow_loops_dump (dump_file, NULL, 0);
       scev_initialize ();
-      FOR_EACH_LOOP (loop, 0)
+      for (loop_p loop : ALL_LOOPS (0))
 	{
 	  predicate loop_iterations = true;
 	  sreal header_freq;
diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index f045108af21..7bfb8ce2216 100644
--- a/gcc/ipa-pure-const.c
+++ b/gcc/ipa-pure-const.c
@@ -1087,9 +1087,8 @@  end:
 	    }
 	  else
 	    {
-	      class loop *loop;
 	      scev_initialize ();
-	      FOR_EACH_LOOP (loop, 0)
+	      for (loop_p loop : ALL_LOOPS (0))
 		if (!finite_loop_p (loop))
 		  {
 		    if (dump_file)
diff --git a/gcc/loop-doloop.c b/gcc/loop-doloop.c
index dda7b9e268f..9cdf6c0c942 100644
--- a/gcc/loop-doloop.c
+++ b/gcc/loop-doloop.c
@@ -789,18 +789,14 @@  doloop_optimize (class loop *loop)
 void
 doloop_optimize_loops (void)
 {
-  class loop *loop;
-
   if (optimize == 1)
     {
       df_live_add_problem ();
       df_live_set_all_dirty ();
     }
 
-  FOR_EACH_LOOP (loop, 0)
-    {
-      doloop_optimize (loop);
-    }
+  for (loop_p loop : ALL_LOOPS (0))
+    doloop_optimize (loop);
 
   if (optimize == 1)
     df_remove_problem (df_live);
diff --git a/gcc/loop-init.c b/gcc/loop-init.c
index 1fde0ede441..54ea1b6bb55 100644
--- a/gcc/loop-init.c
+++ b/gcc/loop-init.c
@@ -137,7 +137,6 @@  loop_optimizer_init (unsigned flags)
 void
 loop_optimizer_finalize (struct function *fn, bool clean_loop_closed_phi)
 {
-  class loop *loop;
   basic_block bb;
 
   timevar_push (TV_LOOP_FINI);
@@ -167,7 +166,7 @@  loop_optimizer_finalize (struct function *fn, bool clean_loop_closed_phi)
       goto loop_fini_done;
     }
 
-  FOR_EACH_LOOP_FN (fn, loop, 0)
+  for (loop_p loop : ALL_LOOPS_FN (fn, 0))
     free_simple_loop_desc (loop);
 
   /* Clean up.  */
@@ -229,7 +228,7 @@  fix_loop_structure (bitmap changed_bbs)
      loops, so that when we remove the loops, we know that the loops inside
      are preserved, and do not waste time relinking loops that will be
      removed later.  */
-  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
     {
       /* Detect the case that the loop is no longer present even though
          it wasn't marked for removal.
diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c
index bdc7b59dd5f..1da9d855dc9 100644
--- a/gcc/loop-invariant.c
+++ b/gcc/loop-invariant.c
@@ -2136,7 +2136,7 @@  calculate_loop_reg_pressure (void)
   rtx link;
   class loop *loop, *parent;
 
-  FOR_EACH_LOOP (loop, 0)
+  for (loop_p loop : ALL_LOOPS (0))
     if (loop->aux == NULL)
       {
 	loop->aux = xcalloc (1, sizeof (class loop_data));
@@ -2203,7 +2203,7 @@  calculate_loop_reg_pressure (void)
   bitmap_release (&curr_regs_live);
   if (flag_ira_region == IRA_REGION_MIXED
       || flag_ira_region == IRA_REGION_ALL)
-    FOR_EACH_LOOP (loop, 0)
+    for (loop_p loop : ALL_LOOPS (0))
       {
 	EXECUTE_IF_SET_IN_BITMAP (&LOOP_DATA (loop)->regs_live, 0, j, bi)
 	  if (! bitmap_bit_p (&LOOP_DATA (loop)->regs_ref, j))
@@ -2217,7 +2217,7 @@  calculate_loop_reg_pressure (void)
       }
   if (dump_file == NULL)
     return;
-  FOR_EACH_LOOP (loop, 0)
+  for (loop_p loop : ALL_LOOPS (0))
     {
       parent = loop_outer (loop);
       fprintf (dump_file, "\n  Loop %d (parent %d, header bb%d, depth %d)\n",
@@ -2251,8 +2251,6 @@  calculate_loop_reg_pressure (void)
 void
 move_loop_invariants (void)
 {
-  class loop *loop;
-
   if (optimize == 1)
     df_live_add_problem ();
   /* ??? This is a hack.  We should only need to call df_live_set_all_dirty
@@ -2271,7 +2269,7 @@  move_loop_invariants (void)
     }
   df_set_flags (DF_EQ_NOTES + DF_DEFER_INSN_RESCAN);
   /* Process the loops, innermost first.  */
-  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
     {
       curr_loop = loop;
       /* move_single_loop_invariants for very large loops is time consuming
@@ -2284,10 +2282,8 @@  move_loop_invariants (void)
 	move_single_loop_invariants (loop);
     }
 
-  FOR_EACH_LOOP (loop, 0)
-    {
+  for (loop_p loop : ALL_LOOPS (0))
       free_loop_data (loop);
-    }
 
   if (flag_ira_loop_pressure)
     /* There is no sense to keep this info because it was most
diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c
index 66d93487e29..a833f340d4f 100644
--- a/gcc/loop-unroll.c
+++ b/gcc/loop-unroll.c
@@ -214,10 +214,8 @@  report_unroll (class loop *loop, dump_location_t locus)
 static void
 decide_unrolling (int flags)
 {
-  class loop *loop;
-
   /* Scan the loops, inner ones first.  */
-  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
     {
       loop->lpt_decision.decision = LPT_NONE;
       dump_user_location_t locus = get_loop_location (loop);
@@ -278,14 +276,13 @@  decide_unrolling (int flags)
 void
 unroll_loops (int flags)
 {
-  class loop *loop;
   bool changed = false;
 
   /* Now decide rest of unrolling.  */
   decide_unrolling (flags);
 
   /* Scan the loops, inner ones first.  */
-  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
     {
       /* And perform the appropriate transformations.  */
       switch (loop->lpt_decision.decision)
diff --git a/gcc/modulo-sched.c b/gcc/modulo-sched.c
index e72e46db387..8a5d5eace35 100644
--- a/gcc/modulo-sched.c
+++ b/gcc/modulo-sched.c
@@ -1353,7 +1353,6 @@  sms_schedule (void)
   int maxii, max_asap;
   partial_schedule_ptr ps;
   basic_block bb = NULL;
-  class loop *loop;
   basic_block condition_bb = NULL;
   edge latch_edge;
   HOST_WIDE_INT trip_count, max_trip_count;
@@ -1397,7 +1396,7 @@  sms_schedule (void)
 
   /* Build DDGs for all the relevant loops and hold them in G_ARR
      indexed by the loop index.  */
-  FOR_EACH_LOOP (loop, 0)
+  for (loop_p loop : ALL_LOOPS (0))
     {
       rtx_insn *head, *tail;
       rtx count_reg;
@@ -1543,7 +1542,7 @@  sms_schedule (void)
   }
 
   /* We don't want to perform SMS on new loops - created by versioning.  */
-  FOR_EACH_LOOP (loop, 0)
+  for (loop_p loop : ALL_LOOPS (0))
     {
       rtx_insn *head, *tail;
       rtx count_reg;
diff --git a/gcc/predict.c b/gcc/predict.c
index d751e6cecce..acd7be0011e 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -1949,7 +1949,7 @@  predict_loops (void)
 
   /* Try to predict out blocks in a loop that are not part of a
      natural loop.  */
-  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
     {
       basic_block bb, *bbs;
       unsigned j, n_exits = 0;
@@ -4111,8 +4111,7 @@  pass_profile::execute (function *fun)
     profile_status_for_fn (fun) = PROFILE_GUESSED;
  if (dump_file && (dump_flags & TDF_DETAILS))
    {
-     class loop *loop;
-     FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+     for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
        if (loop->header->count.initialized_p ())
          fprintf (dump_file, "Loop got predicted %d to iterate %i times.\n",
        	   loop->num,
diff --git a/gcc/profile.c b/gcc/profile.c
index 1fa4196fa16..a00925079e9 100644
--- a/gcc/profile.c
+++ b/gcc/profile.c
@@ -1466,13 +1466,12 @@  branch_prob (bool thunk)
   if (flag_branch_probabilities
       && (profile_status_for_fn (cfun) == PROFILE_READ))
     {
-      class loop *loop;
       if (dump_file && (dump_flags & TDF_DETAILS))
 	report_predictor_hitrates ();
 
       /* At this moment we have precise loop iteration count estimates.
 	 Record them to loop structure before the profile gets out of date. */
-      FOR_EACH_LOOP (loop, 0)
+      for (loop_p loop : ALL_LOOPS (0))
 	if (loop->header->count > 0 && loop->header->count.reliable_p ())
 	  {
 	    gcov_type nit = expected_loop_iterations_unbounded (loop);
diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c
index eef9d6969f4..0479756e5dc 100644
--- a/gcc/sel-sched-ir.c
+++ b/gcc/sel-sched-ir.c
@@ -6247,10 +6247,8 @@  make_regions_from_the_rest (void)
 /* Free data structures used in pipelining of loops.  */
 void sel_finish_pipelining (void)
 {
-  class loop *loop;
-
   /* Release aux fields so we don't free them later by mistake.  */
-  FOR_EACH_LOOP (loop, 0)
+  for (loop_p loop : ALL_LOOPS (0))
     loop->aux = NULL;
 
   loop_optimizer_finalize ();
@@ -6271,11 +6269,11 @@  sel_find_rgns (void)
 
   if (current_loops)
     {
-      loop_p loop;
+      unsigned flags = flag_sel_sched_pipelining_outer_loops
+			 ? LI_FROM_INNERMOST
+			 : LI_ONLY_INNERMOST;
 
-      FOR_EACH_LOOP (loop, (flag_sel_sched_pipelining_outer_loops
-			    ? LI_FROM_INNERMOST
-			    : LI_ONLY_INNERMOST))
+      for (loop_p loop : ALL_LOOPS (flags))
 	make_regions_from_loop_nest (loop);
     }
 
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index c8b0f7b33e1..5226b265938 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -312,12 +312,11 @@  replace_loop_annotate_in_block (basic_block bb, class loop *loop)
 static void
 replace_loop_annotate (void)
 {
-  class loop *loop;
   basic_block bb;
   gimple_stmt_iterator gsi;
   gimple *stmt;
 
-  FOR_EACH_LOOP (loop, 0)
+  for (loop_p loop : ALL_LOOPS (0))
     {
       /* First look into the header.  */
       replace_loop_annotate_in_block (loop->header, loop);
@@ -2027,12 +2026,8 @@  replace_uses_by (tree name, tree val)
   /* Also update the trees stored in loop structures.  */
   if (current_loops)
     {
-      class loop *loop;
-
-      FOR_EACH_LOOP (loop, 0)
-	{
+      for (loop_p loop : ALL_LOOPS (0))
 	  substitute_in_loop_info (loop, name, val);
-	}
     }
 }
 
@@ -7752,9 +7747,9 @@  move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
 
   /* Fix up orig_loop_num.  If the block referenced in it has been moved
      to dest_cfun, update orig_loop_num field, otherwise clear it.  */
-  class loop *dloop;
+  class loop *dloop = NULL;
   signed char *moved_orig_loop_num = NULL;
-  FOR_EACH_LOOP_FN (dest_cfun, dloop, 0)
+  for (loop_p dloop : ALL_LOOPS_FN (dest_cfun, 0))
     if (dloop->orig_loop_num)
       {
 	if (moved_orig_loop_num == NULL)
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index 345488e2a19..4a359e038d0 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -3300,14 +3300,13 @@  pass_if_conversion::gate (function *fun)
 unsigned int
 pass_if_conversion::execute (function *fun)
 {
-  class loop *loop;
   unsigned todo = 0;
 
   if (number_of_loops (fun) <= 1)
     return 0;
 
   auto_vec<gimple *> preds;
-  FOR_EACH_LOOP (loop, 0)
+  for (loop_p loop : ALL_LOOPS (0))
     if (flag_tree_loop_if_convert == 1
 	|| ((flag_tree_loop_vectorize || loop->force_vectorize)
 	    && !loop->dont_vectorize))
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index 65aa1df4aba..cd79a836540 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -3312,7 +3312,7 @@  loop_distribution::execute (function *fun)
 
   /* We can at the moment only distribute non-nested loops, thus restrict
      walking to innermost loops.  */
-  FOR_EACH_LOOP (loop, LI_ONLY_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_ONLY_INNERMOST))
     {
       /* Don't distribute multiple exit edges loop, or cold loop when
          not doing pattern detection.  */
diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
index fe1baef32a7..4a880287229 100644
--- a/gcc/tree-parloops.c
+++ b/gcc/tree-parloops.c
@@ -3989,7 +3989,6 @@  parallelize_loops (bool oacc_kernels_p)
 {
   unsigned n_threads;
   bool changed = false;
-  class loop *loop;
   class loop *skip_loop = NULL;
   class tree_niter_desc niter_desc;
   struct obstack parloop_obstack;
@@ -4020,7 +4019,7 @@  parallelize_loops (bool oacc_kernels_p)
 
   calculate_dominance_info (CDI_DOMINATORS);
 
-  FOR_EACH_LOOP (loop, 0)
+  for (loop_p loop : ALL_LOOPS (0))
     {
       if (loop == skip_loop)
 	{
diff --git a/gcc/tree-predcom.c b/gcc/tree-predcom.c
index cf85517e1c7..ac7c3bed5c4 100644
--- a/gcc/tree-predcom.c
+++ b/gcc/tree-predcom.c
@@ -3419,11 +3419,10 @@  pcom_worker::tree_predictive_commoning_loop (bool allow_unroll_p)
 unsigned
 tree_predictive_commoning (bool allow_unroll_p)
 {
-  class loop *loop;
   unsigned ret = 0, changed = 0;
 
   initialize_original_copy_tables ();
-  FOR_EACH_LOOP (loop, LI_ONLY_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_ONLY_INNERMOST))
     if (optimize_loop_for_speed_p (loop))
       {
 	pcom_worker w(loop);
diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
index b22d49a0ab6..4e514f55f7f 100644
--- a/gcc/tree-scalar-evolution.c
+++ b/gcc/tree-scalar-evolution.c
@@ -2977,16 +2977,12 @@  gather_stats_on_scev_database (void)
 void
 scev_initialize (void)
 {
-  class loop *loop;
-
   gcc_assert (! scev_initialized_p ());
 
   scalar_evolution_info = hash_table<scev_info_hasher>::create_ggc (100);
 
-  FOR_EACH_LOOP (loop, 0)
-    {
-      loop->nb_iterations = NULL_TREE;
-    }
+  for (loop_p loop : ALL_LOOPS (0))
+    loop->nb_iterations = NULL_TREE;
 }
 
 /* Return true if SCEV is initialized.  */
@@ -3015,14 +3011,10 @@  scev_reset_htab (void)
 void
 scev_reset (void)
 {
-  class loop *loop;
-
   scev_reset_htab ();
 
-  FOR_EACH_LOOP (loop, 0)
-    {
-      loop->nb_iterations = NULL_TREE;
-    }
+  for (loop_p loop : ALL_LOOPS (0))
+    loop->nb_iterations = NULL_TREE;
 }
 
 /* Return true if the IV calculation in TYPE can overflow based on the knowledge
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index e2d3b63a30c..8a42242e06e 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -417,7 +417,6 @@  find_obviously_necessary_stmts (bool aggressive)
   /* Prevent the empty possibly infinite loops from being removed.  */
   if (aggressive)
     {
-      class loop *loop;
       if (mark_irreducible_loops ())
 	FOR_EACH_BB_FN (bb, cfun)
 	  {
@@ -433,7 +432,7 @@  find_obviously_necessary_stmts (bool aggressive)
 		}
 	  }
 
-      FOR_EACH_LOOP (loop, 0)
+      for (loop_p loop : ALL_LOOPS (0))
 	if (!finite_loop_p (loop))
 	  {
 	    if (dump_file)
diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c
index a2aab25e862..dccf395c72f 100644
--- a/gcc/tree-ssa-live.c
+++ b/gcc/tree-ssa-live.c
@@ -908,8 +908,7 @@  remove_unused_locals (void)
 
   if (cfun->has_simduid_loops)
     {
-      class loop *loop;
-      FOR_EACH_LOOP (loop, 0)
+      for (loop_p loop : ALL_LOOPS (0))
 	if (loop->simduid && !is_used_p (loop->simduid))
 	  loop->simduid = NULL_TREE;
     }
diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c
index dfa5dc87c34..f39ff204b35 100644
--- a/gcc/tree-ssa-loop-ch.c
+++ b/gcc/tree-ssa-loop-ch.c
@@ -348,7 +348,6 @@  protected:
 unsigned int
 ch_base::copy_headers (function *fun)
 {
-  class loop *loop;
   basic_block header;
   edge exit, entry;
   basic_block *bbs, *copied_bbs;
@@ -365,7 +364,7 @@  ch_base::copy_headers (function *fun)
 
   auto_vec<std::pair<edge, loop_p> > copied;
 
-  FOR_EACH_LOOP (loop, 0)
+  for (loop_p loop : ALL_LOOPS (0))
     {
       int initial_limit = param_max_loop_header_insns;
       int remaining_limit = initial_limit;
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 81b4ec21d6e..b18a2fabbd8 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -1662,7 +1662,7 @@  analyze_memory_references (bool store_motion)
 {
   gimple_stmt_iterator bsi;
   basic_block bb, *bbs;
-  class loop *loop, *outer;
+  class loop *outer;
   unsigned i, n;
 
   /* Collect all basic-blocks in loops and sort them after their
@@ -1706,7 +1706,7 @@  analyze_memory_references (bool store_motion)
 
   /* Propagate the information about accessed memory references up
      the loop hierarchy.  */
-  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
     {
       /* Finalize the overall touched references (including subloops).  */
       bitmap_ior_into (&memory_accesses.all_refs_stored_in_loop[loop->num],
@@ -3133,7 +3133,6 @@  fill_always_executed_in (void)
 static void
 tree_ssa_lim_initialize (bool store_motion)
 {
-  class loop *loop;
   unsigned i;
 
   bitmap_obstack_initialize (&lim_bitmap_obstack);
@@ -3177,7 +3176,7 @@  tree_ssa_lim_initialize (bool store_motion)
      its postorder index.  */
   i = 0;
   bb_loop_postorder = XNEWVEC (unsigned, number_of_loops (cfun));
-  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
     bb_loop_postorder[loop->num] = i++;
 }
 
diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c
index b1971f83544..289f9fb9dd1 100644
--- a/gcc/tree-ssa-loop-ivcanon.c
+++ b/gcc/tree-ssa-loop-ivcanon.c
@@ -1285,14 +1285,13 @@  canonicalize_loop_induction_variables (class loop *loop,
 unsigned int
 canonicalize_induction_variables (void)
 {
-  class loop *loop;
   bool changed = false;
   bool irred_invalidated = false;
   bitmap loop_closed_ssa_invalidated = BITMAP_ALLOC (NULL);
 
   estimate_numbers_of_iterations (cfun);
 
-  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
     {
       changed |= canonicalize_loop_induction_variables (loop,
 							true, UL_SINGLE_ITER,
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 12a8a49a307..7d15e316d6c 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -8066,14 +8066,13 @@  finish:
 void
 tree_ssa_iv_optimize (void)
 {
-  class loop *loop;
   struct ivopts_data data;
   auto_bitmap toremove;
 
   tree_ssa_iv_optimize_init (&data);
 
   /* Optimize the loops starting with the innermost ones.  */
-  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
     {
       if (!dbg_cnt (ivopts_loop))
 	continue;
diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c
index 28ae1316fa0..78aecc355c8 100644
--- a/gcc/tree-ssa-loop-manip.c
+++ b/gcc/tree-ssa-loop-manip.c
@@ -362,11 +362,10 @@  add_exit_phis (bitmap names_to_rename, bitmap *use_blocks, bitmap *loop_exits)
 static void
 get_loops_exits (bitmap *loop_exits)
 {
-  class loop *loop;
   unsigned j;
   edge e;
 
-  FOR_EACH_LOOP (loop, 0)
+  for (loop_p loop : ALL_LOOPS (0))
     {
       auto_vec<edge> exit_edges = get_loop_exit_edges (loop);
       loop_exits[loop->num] = BITMAP_ALLOC (&loop_renamer_obstack);
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 6fabf10a215..4bc5e392c1f 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -4559,13 +4559,11 @@  estimated_stmt_executions (class loop *loop, widest_int *nit)
 void
 estimate_numbers_of_iterations (function *fn)
 {
-  class loop *loop;
-
   /* We don't want to issue signed overflow warnings while getting
      loop iteration estimates.  */
   fold_defer_overflow_warnings ();
 
-  FOR_EACH_LOOP_FN (fn, loop, 0)
+  for (loop_p loop : ALL_LOOPS_FN (fn, 0))
     estimate_numbers_of_iterations (loop);
 
   fold_undefer_and_ignore_overflow_warnings ();
@@ -5031,9 +5029,7 @@  free_numbers_of_iterations_estimates (class loop *loop)
 void
 free_numbers_of_iterations_estimates (function *fn)
 {
-  class loop *loop;
-
-  FOR_EACH_LOOP_FN (fn, loop, 0)
+  for (loop_p loop : ALL_LOOPS_FN (fn, 0))
     free_numbers_of_iterations_estimates (loop);
 }
 
diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c
index 98062eb4616..fb142093f48 100644
--- a/gcc/tree-ssa-loop-prefetch.c
+++ b/gcc/tree-ssa-loop-prefetch.c
@@ -1980,7 +1980,6 @@  fail:
 unsigned int
 tree_ssa_prefetch_arrays (void)
 {
-  class loop *loop;
   bool unrolled = false;
   int todo_flags = 0;
 
@@ -2025,7 +2024,7 @@  tree_ssa_prefetch_arrays (void)
       set_builtin_decl (BUILT_IN_PREFETCH, decl, false);
     }
 
-  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
 	fprintf (dump_file, "Processing loop %d:\n", loop->num);
diff --git a/gcc/tree-ssa-loop-split.c b/gcc/tree-ssa-loop-split.c
index 3a09bbc39e5..b4043d72cbf 100644
--- a/gcc/tree-ssa-loop-split.c
+++ b/gcc/tree-ssa-loop-split.c
@@ -1598,18 +1598,17 @@  split_loop_on_cond (struct loop *loop)
 static unsigned int
 tree_ssa_split_loops (void)
 {
-  class loop *loop;
   bool changed = false;
 
   gcc_assert (scev_initialized_p ());
 
   calculate_dominance_info (CDI_POST_DOMINATORS);
 
-  FOR_EACH_LOOP (loop, LI_INCLUDE_ROOT)
+  for (loop_p loop : ALL_LOOPS (LI_INCLUDE_ROOT))
     loop->aux = NULL;
 
   /* Go through all loops starting from innermost.  */
-  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
     {
       if (loop->aux)
 	{
@@ -1630,7 +1629,7 @@  tree_ssa_split_loops (void)
 	}
     }
 
-  FOR_EACH_LOOP (loop, LI_INCLUDE_ROOT)
+  for (loop_p loop : ALL_LOOPS (LI_INCLUDE_ROOT))
     loop->aux = NULL;
 
   clear_aux_for_blocks ();
diff --git a/gcc/tree-ssa-loop-unswitch.c b/gcc/tree-ssa-loop-unswitch.c
index 04d4553f13e..58472b29b7b 100644
--- a/gcc/tree-ssa-loop-unswitch.c
+++ b/gcc/tree-ssa-loop-unswitch.c
@@ -90,11 +90,10 @@  static tree get_vop_from_header (class loop *);
 unsigned int
 tree_ssa_unswitch_loops (void)
 {
-  class loop *loop;
   bool changed = false;
 
   /* Go through all loops starting from innermost.  */
-  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
     {
       if (!loop->inner)
 	/* Unswitch innermost loop.  */
diff --git a/gcc/tree-ssa-loop.c b/gcc/tree-ssa-loop.c
index 957ac0f3baa..5eee25ea17f 100644
--- a/gcc/tree-ssa-loop.c
+++ b/gcc/tree-ssa-loop.c
@@ -157,8 +157,7 @@  gate_oacc_kernels (function *fn)
   if (!lookup_attribute ("oacc kernels", DECL_ATTRIBUTES (fn->decl)))
     return false;
 
-  class loop *loop;
-  FOR_EACH_LOOP (loop, 0)
+  for (loop_p loop : ALL_LOOPS (0))
     if (loop->in_oacc_kernels_region)
       return true;
 
@@ -455,12 +454,11 @@  public:
 unsigned
 pass_scev_cprop::execute (function *)
 {
-  class loop *loop;
   bool any = false;
 
   /* Perform final value replacement in loops, in case the replacement
      expressions are cheap.  */
-  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
     any |= final_value_replacement_loop (loop);
 
   return any ? TODO_cleanup_cfg | TODO_update_ssa_only_virtuals : 0;
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index d93ec90b002..579be874888 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -1262,7 +1262,6 @@  clean_up_loop_closed_phi (function *fun)
   tree rhs;
   tree lhs;
   gphi_iterator gsi;
-  struct loop *loop;
 
   /* Avoid possibly quadratic work when scanning for loop exits across
    all loops of a nest.  */
@@ -1274,7 +1273,7 @@  clean_up_loop_closed_phi (function *fun)
   calculate_dominance_info  (CDI_DOMINATORS);
 
   /* Walk over loop in function.  */
-  FOR_EACH_LOOP_FN (fun, loop, 0)
+  for (loop_p loop : ALL_LOOPS_FN (fun, 0))
     {
       /* Check each exit edege of loop.  */
       auto_vec<edge> exits = get_loop_exit_edges (loop);
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 7900df946f4..480be4f3935 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -7637,9 +7637,8 @@  do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
      loops and the outermost one optimistically.  */
   if (iterate)
     {
-      loop_p loop;
       unsigned max_depth = param_rpo_vn_max_loop_depth;
-      FOR_EACH_LOOP (loop, LI_ONLY_INNERMOST)
+      for (loop_p loop : ALL_LOOPS (LI_ONLY_INNERMOST))
 	if (loop_depth (loop) > max_depth)
 	  for (unsigned i = 2;
 	       i < loop_depth (loop) - max_depth; ++i)
diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c
index f496dd3eb8c..3381aadc325 100644
--- a/gcc/tree-ssa-threadupdate.c
+++ b/gcc/tree-ssa-threadupdate.c
@@ -2561,7 +2561,6 @@  jump_thread_path_registry::thread_through_all_blocks
 {
   bool retval = false;
   unsigned int i;
-  class loop *loop;
   auto_bitmap threaded_blocks;
   hash_set<edge> visited_starting_edges;
 
@@ -2702,7 +2701,7 @@  jump_thread_path_registry::thread_through_all_blocks
   /* Then perform the threading through loop headers.  We start with the
      innermost loop, so that the changes in cfg we perform won't affect
      further threading.  */
-  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+  for (loop_p loop : ALL_LOOPS (LI_FROM_INNERMOST))
     {
       if (!loop->header
 	  || !bitmap_bit_p (threaded_blocks, loop->header->index))
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index f1035a83826..b0bf98fc667 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -1194,7 +1194,7 @@  vectorize_loops (void)
   /* If some loop was duplicated, it gets bigger number
      than all previously defined loops.  This fact allows us to run
      only over initial loops skipping newly generated ones.  */
-  FOR_EACH_LOOP (loop, 0)
+  for (loop_p loop : ALL_LOOPS (0))
     if (loop->dont_vectorize)
       {
 	any_ifcvt_loops = true;
@@ -1213,7 +1213,7 @@  vectorize_loops (void)
 		  loop4 (copy of loop2)
 		else
 		  loop5 (copy of loop4)
-	   If FOR_EACH_LOOP gives us loop3 first (which has
+	   If ALL_LOOPS gives us loop3 first (which has
 	   dont_vectorize set), make sure to process loop1 before loop4;
 	   so that we can prevent vectorization of loop4 if loop1
 	   is successfully vectorized.  */
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 0565c9b5073..2e268aedd94 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -3337,8 +3337,7 @@  vrp_asserts::find_assert_locations (void)
   /* Pre-seed loop latch liveness from loop header PHI nodes.  Due to
      the order we compute liveness and insert asserts we otherwise
      fail to insert asserts into the loop latch.  */
-  loop_p loop;
-  FOR_EACH_LOOP (loop, 0)
+  for (loop_p loop : ALL_LOOPS (0))
     {
       i = loop->latch->index;
       unsigned int j = single_succ_edge (loop->latch)->dest_idx;