123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782 |
- /* ET-trees data structure implementation.
- Contributed by Pavel Nejedly
- Copyright (C) 2002-2015 Free Software Foundation, Inc.
- This file is part of the libiberty library.
- Libiberty is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
- Libiberty is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
- You should have received a copy of the GNU Library General Public
- License along with libiberty; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>.
- The ET-forest structure is described in:
- D. D. Sleator and R. E. Tarjan. A data structure for dynamic trees.
- J. G'omput. System Sci., 26(3):362 381, 1983.
- */
- #include "config.h"
- #include "system.h"
- #include "coretypes.h"
- #include "et-forest.h"
- #include "alloc-pool.h"
- /* We do not enable this with ENABLE_CHECKING, since it is awfully slow. */
- #undef DEBUG_ET
- #ifdef DEBUG_ET
- #include "vec.h"
- #include "hashtab.h"
- #include "hash-set.h"
- #include "machmode.h"
- #include "tm.h"
- #include "hard-reg-set.h"
- #include "input.h"
- #include "function.h"
- #include "basic-block.h"
- #endif
- /* The occurrence of a node in the et tree. */
- struct et_occ
- {
- struct et_node *of; /* The node. */
- struct et_occ *parent; /* Parent in the splay-tree. */
- struct et_occ *prev; /* Left son in the splay-tree. */
- struct et_occ *next; /* Right son in the splay-tree. */
- int depth; /* The depth of the node is the sum of depth
- fields on the path to the root. */
- int min; /* The minimum value of the depth in the subtree
- is obtained by adding sum of depth fields
- on the path to the root. */
- struct et_occ *min_occ; /* The occurrence in the subtree with the minimal
- depth. */
- };
- static alloc_pool et_nodes;
- static alloc_pool et_occurrences;
- /* Changes depth of OCC to D. */
- static inline void
- set_depth (struct et_occ *occ, int d)
- {
- if (!occ)
- return;
- occ->min += d - occ->depth;
- occ->depth = d;
- }
- /* Adds D to the depth of OCC. */
- static inline void
- set_depth_add (struct et_occ *occ, int d)
- {
- if (!occ)
- return;
- occ->min += d;
- occ->depth += d;
- }
- /* Sets prev field of OCC to P. */
- static inline void
- set_prev (struct et_occ *occ, struct et_occ *t)
- {
- #ifdef DEBUG_ET
- gcc_assert (occ != t);
- #endif
- occ->prev = t;
- if (t)
- t->parent = occ;
- }
- /* Sets next field of OCC to P. */
- static inline void
- set_next (struct et_occ *occ, struct et_occ *t)
- {
- #ifdef DEBUG_ET
- gcc_assert (occ != t);
- #endif
- occ->next = t;
- if (t)
- t->parent = occ;
- }
- /* Recompute minimum for occurrence OCC. */
- static inline void
- et_recomp_min (struct et_occ *occ)
- {
- struct et_occ *mson = occ->prev;
- if (!mson
- || (occ->next
- && mson->min > occ->next->min))
- mson = occ->next;
- if (mson && mson->min < 0)
- {
- occ->min = mson->min + occ->depth;
- occ->min_occ = mson->min_occ;
- }
- else
- {
- occ->min = occ->depth;
- occ->min_occ = occ;
- }
- }
- #ifdef DEBUG_ET
- /* Checks whether neighborhood of OCC seems sane. */
- static void
- et_check_occ_sanity (struct et_occ *occ)
- {
- if (!occ)
- return;
- gcc_assert (occ->parent != occ);
- gcc_assert (occ->prev != occ);
- gcc_assert (occ->next != occ);
- gcc_assert (!occ->next || occ->next != occ->prev);
- if (occ->next)
- {
- gcc_assert (occ->next != occ->parent);
- gcc_assert (occ->next->parent == occ);
- }
- if (occ->prev)
- {
- gcc_assert (occ->prev != occ->parent);
- gcc_assert (occ->prev->parent == occ);
- }
- gcc_assert (!occ->parent
- || occ->parent->prev == occ
- || occ->parent->next == occ);
- }
- /* Checks whether tree rooted at OCC is sane. */
- static void
- et_check_sanity (struct et_occ *occ)
- {
- et_check_occ_sanity (occ);
- if (occ->prev)
- et_check_sanity (occ->prev);
- if (occ->next)
- et_check_sanity (occ->next);
- }
- /* Checks whether tree containing OCC is sane. */
- static void
- et_check_tree_sanity (struct et_occ *occ)
- {
- while (occ->parent)
- occ = occ->parent;
- et_check_sanity (occ);
- }
- /* For recording the paths. */
- /* An ad-hoc constant; if the function has more blocks, this won't work,
- but since it is used for debugging only, it does not matter. */
- #define MAX_NODES 100000
- static int len;
- static void *datas[MAX_NODES];
- static int depths[MAX_NODES];
- /* Records the path represented by OCC, with depth incremented by DEPTH. */
- static int
- record_path_before_1 (struct et_occ *occ, int depth)
- {
- int mn, m;
- depth += occ->depth;
- mn = depth;
- if (occ->prev)
- {
- m = record_path_before_1 (occ->prev, depth);
- if (m < mn)
- mn = m;
- }
- fprintf (stderr, "%d (%d); ", ((basic_block) occ->of->data)->index, depth);
- gcc_assert (len < MAX_NODES);
- depths[len] = depth;
- datas[len] = occ->of;
- len++;
- if (occ->next)
- {
- m = record_path_before_1 (occ->next, depth);
- if (m < mn)
- mn = m;
- }
- gcc_assert (mn == occ->min + depth - occ->depth);
- return mn;
- }
- /* Records the path represented by a tree containing OCC. */
- static void
- record_path_before (struct et_occ *occ)
- {
- while (occ->parent)
- occ = occ->parent;
- len = 0;
- record_path_before_1 (occ, 0);
- fprintf (stderr, "\n");
- }
- /* Checks whether the path represented by OCC, with depth incremented by DEPTH,
- was not changed since the last recording. */
- static int
- check_path_after_1 (struct et_occ *occ, int depth)
- {
- int mn, m;
- depth += occ->depth;
- mn = depth;
- if (occ->next)
- {
- m = check_path_after_1 (occ->next, depth);
- if (m < mn)
- mn = m;
- }
- len--;
- gcc_assert (depths[len] == depth && datas[len] == occ->of);
- if (occ->prev)
- {
- m = check_path_after_1 (occ->prev, depth);
- if (m < mn)
- mn = m;
- }
- gcc_assert (mn == occ->min + depth - occ->depth);
- return mn;
- }
- /* Checks whether the path represented by a tree containing OCC was
- not changed since the last recording. */
- static void
- check_path_after (struct et_occ *occ)
- {
- while (occ->parent)
- occ = occ->parent;
- check_path_after_1 (occ, 0);
- gcc_assert (!len);
- }
- #endif
- /* Splay the occurrence OCC to the root of the tree. */
- static void
- et_splay (struct et_occ *occ)
- {
- struct et_occ *f, *gf, *ggf;
- int occ_depth, f_depth, gf_depth;
- #ifdef DEBUG_ET
- record_path_before (occ);
- et_check_tree_sanity (occ);
- #endif
- while (occ->parent)
- {
- occ_depth = occ->depth;
- f = occ->parent;
- f_depth = f->depth;
- gf = f->parent;
- if (!gf)
- {
- set_depth_add (occ, f_depth);
- occ->min_occ = f->min_occ;
- occ->min = f->min;
- if (f->prev == occ)
- {
- /* zig */
- set_prev (f, occ->next);
- set_next (occ, f);
- set_depth_add (f->prev, occ_depth);
- }
- else
- {
- /* zag */
- set_next (f, occ->prev);
- set_prev (occ, f);
- set_depth_add (f->next, occ_depth);
- }
- set_depth (f, -occ_depth);
- occ->parent = NULL;
- et_recomp_min (f);
- #ifdef DEBUG_ET
- et_check_tree_sanity (occ);
- check_path_after (occ);
- #endif
- return;
- }
- gf_depth = gf->depth;
- set_depth_add (occ, f_depth + gf_depth);
- occ->min_occ = gf->min_occ;
- occ->min = gf->min;
- ggf = gf->parent;
- if (gf->prev == f)
- {
- if (f->prev == occ)
- {
- /* zig zig */
- set_prev (gf, f->next);
- set_prev (f, occ->next);
- set_next (occ, f);
- set_next (f, gf);
- set_depth (f, -occ_depth);
- set_depth_add (f->prev, occ_depth);
- set_depth (gf, -f_depth);
- set_depth_add (gf->prev, f_depth);
- }
- else
- {
- /* zag zig */
- set_prev (gf, occ->next);
- set_next (f, occ->prev);
- set_prev (occ, f);
- set_next (occ, gf);
- set_depth (f, -occ_depth);
- set_depth_add (f->next, occ_depth);
- set_depth (gf, -occ_depth - f_depth);
- set_depth_add (gf->prev, occ_depth + f_depth);
- }
- }
- else
- {
- if (f->prev == occ)
- {
- /* zig zag */
- set_next (gf, occ->prev);
- set_prev (f, occ->next);
- set_prev (occ, gf);
- set_next (occ, f);
- set_depth (f, -occ_depth);
- set_depth_add (f->prev, occ_depth);
- set_depth (gf, -occ_depth - f_depth);
- set_depth_add (gf->next, occ_depth + f_depth);
- }
- else
- {
- /* zag zag */
- set_next (gf, f->prev);
- set_next (f, occ->prev);
- set_prev (occ, f);
- set_prev (f, gf);
- set_depth (f, -occ_depth);
- set_depth_add (f->next, occ_depth);
- set_depth (gf, -f_depth);
- set_depth_add (gf->next, f_depth);
- }
- }
- occ->parent = ggf;
- if (ggf)
- {
- if (ggf->prev == gf)
- ggf->prev = occ;
- else
- ggf->next = occ;
- }
- et_recomp_min (gf);
- et_recomp_min (f);
- #ifdef DEBUG_ET
- et_check_tree_sanity (occ);
- #endif
- }
- #ifdef DEBUG_ET
- et_check_sanity (occ);
- check_path_after (occ);
- #endif
- }
- /* Create a new et tree occurrence of NODE. */
- static struct et_occ *
- et_new_occ (struct et_node *node)
- {
- struct et_occ *nw;
- if (!et_occurrences)
- et_occurrences = create_alloc_pool ("et_occ pool", sizeof (struct et_occ), 300);
- nw = (struct et_occ *) pool_alloc (et_occurrences);
- nw->of = node;
- nw->parent = NULL;
- nw->prev = NULL;
- nw->next = NULL;
- nw->depth = 0;
- nw->min_occ = nw;
- nw->min = 0;
- return nw;
- }
- /* Create a new et tree containing DATA. */
- struct et_node *
- et_new_tree (void *data)
- {
- struct et_node *nw;
- if (!et_nodes)
- et_nodes = create_alloc_pool ("et_node pool", sizeof (struct et_node), 300);
- nw = (struct et_node *) pool_alloc (et_nodes);
- nw->data = data;
- nw->father = NULL;
- nw->left = NULL;
- nw->right = NULL;
- nw->son = NULL;
- nw->rightmost_occ = et_new_occ (nw);
- nw->parent_occ = NULL;
- return nw;
- }
- /* Releases et tree T. */
- void
- et_free_tree (struct et_node *t)
- {
- while (t->son)
- et_split (t->son);
- if (t->father)
- et_split (t);
- pool_free (et_occurrences, t->rightmost_occ);
- pool_free (et_nodes, t);
- }
- /* Releases et tree T without maintaining other nodes. */
- void
- et_free_tree_force (struct et_node *t)
- {
- pool_free (et_occurrences, t->rightmost_occ);
- if (t->parent_occ)
- pool_free (et_occurrences, t->parent_occ);
- pool_free (et_nodes, t);
- }
- /* Release the alloc pools, if they are empty. */
- void
- et_free_pools (void)
- {
- free_alloc_pool_if_empty (&et_occurrences);
- free_alloc_pool_if_empty (&et_nodes);
- }
- /* Sets father of et tree T to FATHER. */
- void
- et_set_father (struct et_node *t, struct et_node *father)
- {
- struct et_node *left, *right;
- struct et_occ *rmost, *left_part, *new_f_occ, *p;
- /* Update the path represented in the splay tree. */
- new_f_occ = et_new_occ (father);
- rmost = father->rightmost_occ;
- et_splay (rmost);
- left_part = rmost->prev;
- p = t->rightmost_occ;
- et_splay (p);
- set_prev (new_f_occ, left_part);
- set_next (new_f_occ, p);
- p->depth++;
- p->min++;
- et_recomp_min (new_f_occ);
- set_prev (rmost, new_f_occ);
- if (new_f_occ->min + rmost->depth < rmost->min)
- {
- rmost->min = new_f_occ->min + rmost->depth;
- rmost->min_occ = new_f_occ->min_occ;
- }
- t->parent_occ = new_f_occ;
- /* Update the tree. */
- t->father = father;
- right = father->son;
- if (right)
- left = right->left;
- else
- left = right = t;
- left->right = t;
- right->left = t;
- t->left = left;
- t->right = right;
- father->son = t;
- #ifdef DEBUG_ET
- et_check_tree_sanity (rmost);
- record_path_before (rmost);
- #endif
- }
- /* Splits the edge from T to its father. */
- void
- et_split (struct et_node *t)
- {
- struct et_node *father = t->father;
- struct et_occ *r, *l, *rmost, *p_occ;
- /* Update the path represented by the splay tree. */
- rmost = t->rightmost_occ;
- et_splay (rmost);
- for (r = rmost->next; r->prev; r = r->prev)
- continue;
- et_splay (r);
- r->prev->parent = NULL;
- p_occ = t->parent_occ;
- et_splay (p_occ);
- t->parent_occ = NULL;
- l = p_occ->prev;
- p_occ->next->parent = NULL;
- set_prev (r, l);
- et_recomp_min (r);
- et_splay (rmost);
- rmost->depth = 0;
- rmost->min = 0;
- pool_free (et_occurrences, p_occ);
- /* Update the tree. */
- if (father->son == t)
- father->son = t->right;
- if (father->son == t)
- father->son = NULL;
- else
- {
- t->left->right = t->right;
- t->right->left = t->left;
- }
- t->left = t->right = NULL;
- t->father = NULL;
- #ifdef DEBUG_ET
- et_check_tree_sanity (rmost);
- record_path_before (rmost);
- et_check_tree_sanity (r);
- record_path_before (r);
- #endif
- }
- /* Finds the nearest common ancestor of the nodes N1 and N2. */
- struct et_node *
- et_nca (struct et_node *n1, struct et_node *n2)
- {
- struct et_occ *o1 = n1->rightmost_occ, *o2 = n2->rightmost_occ, *om;
- struct et_occ *l, *r, *ret;
- int mn;
- if (n1 == n2)
- return n1;
- et_splay (o1);
- l = o1->prev;
- r = o1->next;
- if (l)
- l->parent = NULL;
- if (r)
- r->parent = NULL;
- et_splay (o2);
- if (l == o2 || (l && l->parent != NULL))
- {
- ret = o2->next;
- set_prev (o1, o2);
- if (r)
- r->parent = o1;
- }
- else if (r == o2 || (r && r->parent != NULL))
- {
- ret = o2->prev;
- set_next (o1, o2);
- if (l)
- l->parent = o1;
- }
- else
- {
- /* O1 and O2 are in different components of the forest. */
- if (l)
- l->parent = o1;
- if (r)
- r->parent = o1;
- return NULL;
- }
- if (0 < o2->depth)
- {
- om = o1;
- mn = o1->depth;
- }
- else
- {
- om = o2;
- mn = o2->depth + o1->depth;
- }
- #ifdef DEBUG_ET
- et_check_tree_sanity (o2);
- #endif
- if (ret && ret->min + o1->depth + o2->depth < mn)
- return ret->min_occ->of;
- else
- return om->of;
- }
- /* Checks whether the node UP is an ancestor of the node DOWN. */
- bool
- et_below (struct et_node *down, struct et_node *up)
- {
- struct et_occ *u = up->rightmost_occ, *d = down->rightmost_occ;
- struct et_occ *l, *r;
- if (up == down)
- return true;
- et_splay (u);
- l = u->prev;
- r = u->next;
- if (!l)
- return false;
- l->parent = NULL;
- if (r)
- r->parent = NULL;
- et_splay (d);
- if (l == d || l->parent != NULL)
- {
- if (r)
- r->parent = u;
- set_prev (u, d);
- #ifdef DEBUG_ET
- et_check_tree_sanity (u);
- #endif
- }
- else
- {
- l->parent = u;
- /* In case O1 and O2 are in two different trees, we must just restore the
- original state. */
- if (r && r->parent != NULL)
- set_next (u, d);
- else
- set_next (u, r);
- #ifdef DEBUG_ET
- et_check_tree_sanity (u);
- #endif
- return false;
- }
- if (0 >= d->depth)
- return false;
- return !d->next || d->next->min + d->depth >= 0;
- }
- /* Returns the root of the tree that contains NODE. */
- struct et_node *
- et_root (struct et_node *node)
- {
- struct et_occ *occ = node->rightmost_occ, *r;
- /* The root of the tree corresponds to the rightmost occurrence in the
- represented path. */
- et_splay (occ);
- for (r = occ; r->next; r = r->next)
- continue;
- et_splay (r);
- return r->of;
- }
|