diff options
author | Kewen Lin <linkw@linux.ibm.com> | 2021-07-25 20:52:08 -0500 |
---|---|---|
committer | Kewen Lin <linkw@linux.ibm.com> | 2021-08-05 03:44:20 -0500 |
commit | d0a5624bb40470cb0ee03fe86530118ca6de0b3a (patch) | |
tree | 876feb4d59f64933f2dd59e335a6d85555fe50ab /gcc/cfgloop.c | |
parent | 4e3129b0caceec008a940aa5eada253cd0f0b3ec (diff) | |
download | gcc-d0a5624bb40470cb0ee03fe86530118ca6de0b3a.zip gcc-d0a5624bb40470cb0ee03fe86530118ca6de0b3a.tar.gz gcc-d0a5624bb40470cb0ee03fe86530118ca6de0b3a.tar.bz2 |
cfgloop: Make loops_list support an optional loop_p root
This patch follows Richi's suggestion to add one optional
argument class loop* root to loops_list's CTOR, it can
provide the ability to construct a visiting list starting
from the given class loop* ROOT rather than the default
tree_root of loops_for_fn (FN), for visiting a subset of
the loop tree.
It unifies all orders of walkings into walk_loop_tree, but
it still uses linear search for LI_ONLY_INNERMOST when
looking at the whole loop tree since it has a more stable
bound.
gcc/ChangeLog:
* cfgloop.h (loops_list::loops_list): Add one optional argument
root and adjust accordingly, update loop tree walking and factor
out to ...
* cfgloop.c (loops_list::walk_loop_tree): ... this. New function.
Diffstat (limited to 'gcc/cfgloop.c')
-rw-r--r-- | gcc/cfgloop.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c index 6284ae2..2ba9918 100644 --- a/gcc/cfgloop.c +++ b/gcc/cfgloop.c @@ -2104,3 +2104,69 @@ mark_loop_for_removal (loop_p loop) loop->latch = NULL; loops_state_set (LOOPS_NEED_FIXUP); } + +/* Starting from loop tree ROOT, walk loop tree as the visiting + order specified by FLAGS. The supported visiting orders + are: + - LI_ONLY_INNERMOST + - LI_FROM_INNERMOST + - Preorder (if neither of above is specified) */ + +void +loops_list::walk_loop_tree (class loop *root, unsigned flags) +{ + bool only_innermost_p = flags & LI_ONLY_INNERMOST; + bool from_innermost_p = flags & LI_FROM_INNERMOST; + bool preorder_p = !(only_innermost_p || from_innermost_p); + + /* Early handle root without any inner loops, make later + processing simpler, that is all loops processed in the + following while loop are impossible to be root. */ + if (!root->inner) + { + if (flags & LI_INCLUDE_ROOT) + this->to_visit.quick_push (root->num); + return; + } + else if (preorder_p && flags & LI_INCLUDE_ROOT) + this->to_visit.quick_push (root->num); + + class loop *aloop; + for (aloop = root->inner; + aloop->inner != NULL; + aloop = aloop->inner) + { + if (preorder_p) + this->to_visit.quick_push (aloop->num); + continue; + } + + while (1) + { + gcc_assert (aloop != root); + if (from_innermost_p || aloop->inner == NULL) + this->to_visit.quick_push (aloop->num); + + if (aloop->next) + { + for (aloop = aloop->next; + aloop->inner != NULL; + aloop = aloop->inner) + { + if (preorder_p) + this->to_visit.quick_push (aloop->num); + continue; + } + } + else if (loop_outer (aloop) == root) + break; + else + aloop = loop_outer (aloop); + } + + /* When visiting from innermost, we need to consider root here + since the previous while loop doesn't handle it. */ + if (from_innermost_p && flags & LI_INCLUDE_ROOT) + this->to_visit.quick_push (root->num); +} + |