Home | History | Annotate | Line # | Download | only in gcc
graphds.cc revision 1.1
      1  1.1  mrg /* Graph representation and manipulation functions.
      2  1.1  mrg    Copyright (C) 2007-2022 Free Software Foundation, Inc.
      3  1.1  mrg 
      4  1.1  mrg This file is part of GCC.
      5  1.1  mrg 
      6  1.1  mrg GCC is free software; you can redistribute it and/or modify it under
      7  1.1  mrg the terms of the GNU General Public License as published by the Free
      8  1.1  mrg Software Foundation; either version 3, or (at your option) any later
      9  1.1  mrg version.
     10  1.1  mrg 
     11  1.1  mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     12  1.1  mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  1.1  mrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  1.1  mrg for more details.
     15  1.1  mrg 
     16  1.1  mrg You should have received a copy of the GNU General Public License
     17  1.1  mrg along with GCC; see the file COPYING3.  If not see
     18  1.1  mrg <http://www.gnu.org/licenses/>.  */
     19  1.1  mrg 
     20  1.1  mrg #include "config.h"
     21  1.1  mrg #include "system.h"
     22  1.1  mrg #include "coretypes.h"
     23  1.1  mrg #include "bitmap.h"
     24  1.1  mrg #include "graphds.h"
     25  1.1  mrg 
     26  1.1  mrg /* Dumps graph G into F.  */
     27  1.1  mrg 
     28  1.1  mrg void
     29  1.1  mrg dump_graph (FILE *f, struct graph *g)
     30  1.1  mrg {
     31  1.1  mrg   int i;
     32  1.1  mrg   struct graph_edge *e;
     33  1.1  mrg 
     34  1.1  mrg   for (i = 0; i < g->n_vertices; i++)
     35  1.1  mrg     {
     36  1.1  mrg       if (!g->vertices[i].pred
     37  1.1  mrg 	  && !g->vertices[i].succ)
     38  1.1  mrg 	continue;
     39  1.1  mrg 
     40  1.1  mrg       fprintf (f, "%d (%d)\t<-", i, g->vertices[i].component);
     41  1.1  mrg       for (e = g->vertices[i].pred; e; e = e->pred_next)
     42  1.1  mrg 	fprintf (f, " %d", e->src);
     43  1.1  mrg       fprintf (f, "\n");
     44  1.1  mrg 
     45  1.1  mrg       fprintf (f, "\t->");
     46  1.1  mrg       for (e = g->vertices[i].succ; e; e = e->succ_next)
     47  1.1  mrg 	fprintf (f, " %d", e->dest);
     48  1.1  mrg       fprintf (f, "\n");
     49  1.1  mrg     }
     50  1.1  mrg }
     51  1.1  mrg 
     52  1.1  mrg /* Creates a new graph with N_VERTICES vertices.  */
     53  1.1  mrg 
     54  1.1  mrg struct graph *
     55  1.1  mrg new_graph (int n_vertices)
     56  1.1  mrg {
     57  1.1  mrg   struct graph *g = XNEW (struct graph);
     58  1.1  mrg 
     59  1.1  mrg   gcc_obstack_init (&g->ob);
     60  1.1  mrg   g->n_vertices = n_vertices;
     61  1.1  mrg   g->vertices = XOBNEWVEC (&g->ob, struct vertex, n_vertices);
     62  1.1  mrg   memset (g->vertices, 0, sizeof (struct vertex) * n_vertices);
     63  1.1  mrg 
     64  1.1  mrg   return g;
     65  1.1  mrg }
     66  1.1  mrg 
     67  1.1  mrg /* Adds an edge from F to T to graph G.  The new edge is returned.  */
     68  1.1  mrg 
     69  1.1  mrg struct graph_edge *
     70  1.1  mrg add_edge (struct graph *g, int f, int t)
     71  1.1  mrg {
     72  1.1  mrg   struct graph_edge *e = XOBNEW (&g->ob, struct graph_edge);
     73  1.1  mrg   struct vertex *vf = &g->vertices[f], *vt = &g->vertices[t];
     74  1.1  mrg 
     75  1.1  mrg   e->src = f;
     76  1.1  mrg   e->dest = t;
     77  1.1  mrg 
     78  1.1  mrg   e->pred_next = vt->pred;
     79  1.1  mrg   vt->pred = e;
     80  1.1  mrg 
     81  1.1  mrg   e->succ_next = vf->succ;
     82  1.1  mrg   vf->succ = e;
     83  1.1  mrg 
     84  1.1  mrg   e->data = NULL;
     85  1.1  mrg   return e;
     86  1.1  mrg }
     87  1.1  mrg 
     88  1.1  mrg /* Moves all the edges incident with U to V.  */
     89  1.1  mrg 
     90  1.1  mrg void
     91  1.1  mrg identify_vertices (struct graph *g, int v, int u)
     92  1.1  mrg {
     93  1.1  mrg   struct vertex *vv = &g->vertices[v];
     94  1.1  mrg   struct vertex *uu = &g->vertices[u];
     95  1.1  mrg   struct graph_edge *e, *next;
     96  1.1  mrg 
     97  1.1  mrg   for (e = uu->succ; e; e = next)
     98  1.1  mrg     {
     99  1.1  mrg       next = e->succ_next;
    100  1.1  mrg 
    101  1.1  mrg       e->src = v;
    102  1.1  mrg       e->succ_next = vv->succ;
    103  1.1  mrg       vv->succ = e;
    104  1.1  mrg     }
    105  1.1  mrg   uu->succ = NULL;
    106  1.1  mrg 
    107  1.1  mrg   for (e = uu->pred; e; e = next)
    108  1.1  mrg     {
    109  1.1  mrg       next = e->pred_next;
    110  1.1  mrg 
    111  1.1  mrg       e->dest = v;
    112  1.1  mrg       e->pred_next = vv->pred;
    113  1.1  mrg       vv->pred = e;
    114  1.1  mrg     }
    115  1.1  mrg   uu->pred = NULL;
    116  1.1  mrg }
    117  1.1  mrg 
    118  1.1  mrg /* Helper function for graphds_dfs.  Returns the source vertex of E, in the
    119  1.1  mrg    direction given by FORWARD.  */
    120  1.1  mrg 
    121  1.1  mrg static inline int
    122  1.1  mrg dfs_edge_src (struct graph_edge *e, bool forward)
    123  1.1  mrg {
    124  1.1  mrg   return forward ? e->src : e->dest;
    125  1.1  mrg }
    126  1.1  mrg 
    127  1.1  mrg /* Helper function for graphds_dfs.  Returns the destination vertex of E, in
    128  1.1  mrg    the direction given by FORWARD.  */
    129  1.1  mrg 
    130  1.1  mrg static inline int
    131  1.1  mrg dfs_edge_dest (struct graph_edge *e, bool forward)
    132  1.1  mrg {
    133  1.1  mrg   return forward ? e->dest : e->src;
    134  1.1  mrg }
    135  1.1  mrg 
    136  1.1  mrg /* Helper function for graphds_dfs.  Returns the first edge after E (including
    137  1.1  mrg    E), in the graph direction given by FORWARD, that belongs to SUBGRAPH.  If
    138  1.1  mrg    SKIP_EDGE_P is not NULL, it points to a callback function.  Edge E will be
    139  1.1  mrg    skipped if callback function returns true.  */
    140  1.1  mrg 
    141  1.1  mrg static inline struct graph_edge *
    142  1.1  mrg foll_in_subgraph (struct graph_edge *e, bool forward, bitmap subgraph,
    143  1.1  mrg 		  skip_edge_callback skip_edge_p)
    144  1.1  mrg {
    145  1.1  mrg   int d;
    146  1.1  mrg 
    147  1.1  mrg   if (!e)
    148  1.1  mrg     return e;
    149  1.1  mrg 
    150  1.1  mrg   if (!subgraph && (!skip_edge_p || !skip_edge_p (e)))
    151  1.1  mrg     return e;
    152  1.1  mrg 
    153  1.1  mrg   while (e)
    154  1.1  mrg     {
    155  1.1  mrg       d = dfs_edge_dest (e, forward);
    156  1.1  mrg       /* Return edge if it belongs to subgraph and shouldn't be skipped.  */
    157  1.1  mrg       if ((!subgraph || bitmap_bit_p (subgraph, d))
    158  1.1  mrg 	  && (!skip_edge_p || !skip_edge_p (e)))
    159  1.1  mrg 	return e;
    160  1.1  mrg 
    161  1.1  mrg       e = forward ? e->succ_next : e->pred_next;
    162  1.1  mrg     }
    163  1.1  mrg 
    164  1.1  mrg   return e;
    165  1.1  mrg }
    166  1.1  mrg 
    167  1.1  mrg /* Helper function for graphds_dfs.  Select the first edge from V in G, in the
    168  1.1  mrg    direction given by FORWARD, that belongs to SUBGRAPH.  If SKIP_EDGE_P is not
    169  1.1  mrg    NULL, it points to a callback function.  Edge E will be skipped if callback
    170  1.1  mrg    function returns true.  */
    171  1.1  mrg 
    172  1.1  mrg static inline struct graph_edge *
    173  1.1  mrg dfs_fst_edge (struct graph *g, int v, bool forward, bitmap subgraph,
    174  1.1  mrg 	      skip_edge_callback skip_edge_p)
    175  1.1  mrg {
    176  1.1  mrg   struct graph_edge *e;
    177  1.1  mrg 
    178  1.1  mrg   e = (forward ? g->vertices[v].succ : g->vertices[v].pred);
    179  1.1  mrg   return foll_in_subgraph (e, forward, subgraph, skip_edge_p);
    180  1.1  mrg }
    181  1.1  mrg 
    182  1.1  mrg /* Helper function for graphds_dfs.  Returns the next edge after E, in the
    183  1.1  mrg    graph direction given by FORWARD, that belongs to SUBGRAPH.  If SKIP_EDGE_P
    184  1.1  mrg    is not NULL, it points to a callback function.  Edge E will be skipped if
    185  1.1  mrg    callback function returns true.  */
    186  1.1  mrg 
    187  1.1  mrg static inline struct graph_edge *
    188  1.1  mrg dfs_next_edge (struct graph_edge *e, bool forward, bitmap subgraph,
    189  1.1  mrg 	       skip_edge_callback skip_edge_p)
    190  1.1  mrg {
    191  1.1  mrg   return foll_in_subgraph (forward ? e->succ_next : e->pred_next,
    192  1.1  mrg 			   forward, subgraph, skip_edge_p);
    193  1.1  mrg }
    194  1.1  mrg 
    195  1.1  mrg /* Runs dfs search over vertices of G, from NQ vertices in queue QS.
    196  1.1  mrg    The vertices in postorder are stored into QT.  If FORWARD is false,
    197  1.1  mrg    backward dfs is run.  If SUBGRAPH is not NULL, it specifies the
    198  1.1  mrg    subgraph of G to run DFS on.  Returns the number of the components
    199  1.1  mrg    of the graph (number of the restarts of DFS).  If SKIP_EDGE_P is not
    200  1.1  mrg    NULL, it points to a callback function.  Edge E will be skipped if
    201  1.1  mrg    callback function returns true.  */
    202  1.1  mrg 
    203  1.1  mrg int
    204  1.1  mrg graphds_dfs (struct graph *g, int *qs, int nq, vec<int> *qt,
    205  1.1  mrg 	     bool forward, bitmap subgraph,
    206  1.1  mrg 	     skip_edge_callback skip_edge_p)
    207  1.1  mrg {
    208  1.1  mrg   int i, tick = 0, v, comp = 0, top;
    209  1.1  mrg   struct graph_edge *e;
    210  1.1  mrg   struct graph_edge **stack = XNEWVEC (struct graph_edge *, g->n_vertices);
    211  1.1  mrg   bitmap_iterator bi;
    212  1.1  mrg   unsigned av;
    213  1.1  mrg 
    214  1.1  mrg   if (subgraph)
    215  1.1  mrg     {
    216  1.1  mrg       EXECUTE_IF_SET_IN_BITMAP (subgraph, 0, av, bi)
    217  1.1  mrg 	{
    218  1.1  mrg 	  g->vertices[av].component = -1;
    219  1.1  mrg 	  g->vertices[av].post = -1;
    220  1.1  mrg 	}
    221  1.1  mrg     }
    222  1.1  mrg   else
    223  1.1  mrg     {
    224  1.1  mrg       for (i = 0; i < g->n_vertices; i++)
    225  1.1  mrg 	{
    226  1.1  mrg 	  g->vertices[i].component = -1;
    227  1.1  mrg 	  g->vertices[i].post = -1;
    228  1.1  mrg 	}
    229  1.1  mrg     }
    230  1.1  mrg 
    231  1.1  mrg   for (i = 0; i < nq; i++)
    232  1.1  mrg     {
    233  1.1  mrg       v = qs[i];
    234  1.1  mrg       if (g->vertices[v].post != -1)
    235  1.1  mrg 	continue;
    236  1.1  mrg 
    237  1.1  mrg       g->vertices[v].component = comp++;
    238  1.1  mrg       e = dfs_fst_edge (g, v, forward, subgraph, skip_edge_p);
    239  1.1  mrg       top = 0;
    240  1.1  mrg 
    241  1.1  mrg       while (1)
    242  1.1  mrg 	{
    243  1.1  mrg 	  while (e)
    244  1.1  mrg 	    {
    245  1.1  mrg 	      if (g->vertices[dfs_edge_dest (e, forward)].component
    246  1.1  mrg 		  == -1)
    247  1.1  mrg 		break;
    248  1.1  mrg 	      e = dfs_next_edge (e, forward, subgraph, skip_edge_p);
    249  1.1  mrg 	    }
    250  1.1  mrg 
    251  1.1  mrg 	  if (!e)
    252  1.1  mrg 	    {
    253  1.1  mrg 	      if (qt)
    254  1.1  mrg 		qt->safe_push (v);
    255  1.1  mrg 	      g->vertices[v].post = tick++;
    256  1.1  mrg 
    257  1.1  mrg 	      if (!top)
    258  1.1  mrg 		break;
    259  1.1  mrg 
    260  1.1  mrg 	      e = stack[--top];
    261  1.1  mrg 	      v = dfs_edge_src (e, forward);
    262  1.1  mrg 	      e = dfs_next_edge (e, forward, subgraph, skip_edge_p);
    263  1.1  mrg 	      continue;
    264  1.1  mrg 	    }
    265  1.1  mrg 
    266  1.1  mrg 	  stack[top++] = e;
    267  1.1  mrg 	  v = dfs_edge_dest (e, forward);
    268  1.1  mrg 	  e = dfs_fst_edge (g, v, forward, subgraph, skip_edge_p);
    269  1.1  mrg 	  g->vertices[v].component = comp - 1;
    270  1.1  mrg 	}
    271  1.1  mrg     }
    272  1.1  mrg 
    273  1.1  mrg   free (stack);
    274  1.1  mrg 
    275  1.1  mrg   return comp;
    276  1.1  mrg }
    277  1.1  mrg 
    278  1.1  mrg /* Determines the strongly connected components of G, using the algorithm of
    279  1.1  mrg    Tarjan -- first determine the postorder dfs numbering in reversed graph,
    280  1.1  mrg    then run the dfs on the original graph in the order given by decreasing
    281  1.1  mrg    numbers assigned by the previous pass.  If SUBGRAPH is not NULL, it
    282  1.1  mrg    specifies the subgraph of G whose strongly connected components we want
    283  1.1  mrg    to determine.  If SKIP_EDGE_P is not NULL, it points to a callback function.
    284  1.1  mrg    Edge E will be skipped if callback function returns true.
    285  1.1  mrg 
    286  1.1  mrg    After running this function, v->component is the number of the strongly
    287  1.1  mrg    connected component for each vertex of G.  Returns the number of the
    288  1.1  mrg    sccs of G.  */
    289  1.1  mrg 
    290  1.1  mrg int
    291  1.1  mrg graphds_scc (struct graph *g, bitmap subgraph,
    292  1.1  mrg 	     skip_edge_callback skip_edge_p)
    293  1.1  mrg {
    294  1.1  mrg   int *queue = XNEWVEC (int, g->n_vertices);
    295  1.1  mrg   vec<int> postorder = vNULL;
    296  1.1  mrg   int nq, i, comp;
    297  1.1  mrg   unsigned v;
    298  1.1  mrg   bitmap_iterator bi;
    299  1.1  mrg 
    300  1.1  mrg   if (subgraph)
    301  1.1  mrg     {
    302  1.1  mrg       nq = 0;
    303  1.1  mrg       EXECUTE_IF_SET_IN_BITMAP (subgraph, 0, v, bi)
    304  1.1  mrg 	{
    305  1.1  mrg 	  queue[nq++] = v;
    306  1.1  mrg 	}
    307  1.1  mrg     }
    308  1.1  mrg   else
    309  1.1  mrg     {
    310  1.1  mrg       for (i = 0; i < g->n_vertices; i++)
    311  1.1  mrg 	queue[i] = i;
    312  1.1  mrg       nq = g->n_vertices;
    313  1.1  mrg     }
    314  1.1  mrg 
    315  1.1  mrg   graphds_dfs (g, queue, nq, &postorder, false, subgraph, skip_edge_p);
    316  1.1  mrg   gcc_assert (postorder.length () == (unsigned) nq);
    317  1.1  mrg 
    318  1.1  mrg   for (i = 0; i < nq; i++)
    319  1.1  mrg     queue[i] = postorder[nq - i - 1];
    320  1.1  mrg   comp = graphds_dfs (g, queue, nq, NULL, true, subgraph, skip_edge_p);
    321  1.1  mrg 
    322  1.1  mrg   free (queue);
    323  1.1  mrg   postorder.release ();
    324  1.1  mrg 
    325  1.1  mrg   return comp;
    326  1.1  mrg }
    327  1.1  mrg 
    328  1.1  mrg /* Runs CALLBACK for all edges in G.  DATA is private data for CALLBACK.  */
    329  1.1  mrg 
    330  1.1  mrg void
    331  1.1  mrg for_each_edge (struct graph *g, graphds_edge_callback callback, void *data)
    332  1.1  mrg {
    333  1.1  mrg   struct graph_edge *e;
    334  1.1  mrg   int i;
    335  1.1  mrg 
    336  1.1  mrg   for (i = 0; i < g->n_vertices; i++)
    337  1.1  mrg     for (e = g->vertices[i].succ; e; e = e->succ_next)
    338  1.1  mrg       callback (g, e, data);
    339  1.1  mrg }
    340  1.1  mrg 
    341  1.1  mrg /* Releases the memory occupied by G.  */
    342  1.1  mrg 
    343  1.1  mrg void
    344  1.1  mrg free_graph (struct graph *g)
    345  1.1  mrg {
    346  1.1  mrg   obstack_free (&g->ob, NULL);
    347  1.1  mrg   free (g);
    348  1.1  mrg }
    349  1.1  mrg 
    350  1.1  mrg /* Returns the nearest common ancestor of X and Y in tree whose parent
    351  1.1  mrg    links are given by PARENT.  MARKS is the array used to mark the
    352  1.1  mrg    vertices of the tree, and MARK is the number currently used as a mark.  */
    353  1.1  mrg 
    354  1.1  mrg static int
    355  1.1  mrg tree_nca (int x, int y, int *parent, int *marks, int mark)
    356  1.1  mrg {
    357  1.1  mrg   if (x == -1 || x == y)
    358  1.1  mrg     return y;
    359  1.1  mrg 
    360  1.1  mrg   /* We climb with X and Y up the tree, marking the visited nodes.  When
    361  1.1  mrg      we first arrive to a marked node, it is the common ancestor.  */
    362  1.1  mrg   marks[x] = mark;
    363  1.1  mrg   marks[y] = mark;
    364  1.1  mrg 
    365  1.1  mrg   while (1)
    366  1.1  mrg     {
    367  1.1  mrg       x = parent[x];
    368  1.1  mrg       if (x == -1)
    369  1.1  mrg 	break;
    370  1.1  mrg       if (marks[x] == mark)
    371  1.1  mrg 	return x;
    372  1.1  mrg       marks[x] = mark;
    373  1.1  mrg 
    374  1.1  mrg       y = parent[y];
    375  1.1  mrg       if (y == -1)
    376  1.1  mrg 	break;
    377  1.1  mrg       if (marks[y] == mark)
    378  1.1  mrg 	return y;
    379  1.1  mrg       marks[y] = mark;
    380  1.1  mrg     }
    381  1.1  mrg 
    382  1.1  mrg   /* If we reached the root with one of the vertices, continue
    383  1.1  mrg      with the other one till we reach the marked part of the
    384  1.1  mrg      tree.  */
    385  1.1  mrg   if (x == -1)
    386  1.1  mrg     {
    387  1.1  mrg       for (y = parent[y]; marks[y] != mark; y = parent[y])
    388  1.1  mrg 	continue;
    389  1.1  mrg 
    390  1.1  mrg       return y;
    391  1.1  mrg     }
    392  1.1  mrg   else
    393  1.1  mrg     {
    394  1.1  mrg       for (x = parent[x]; marks[x] != mark; x = parent[x])
    395  1.1  mrg 	continue;
    396  1.1  mrg 
    397  1.1  mrg       return x;
    398  1.1  mrg     }
    399  1.1  mrg }
    400  1.1  mrg 
    401  1.1  mrg /* Determines the dominance tree of G (stored in the PARENT, SON and BROTHER
    402  1.1  mrg    arrays), where the entry node is ENTRY.  */
    403  1.1  mrg 
    404  1.1  mrg void
    405  1.1  mrg graphds_domtree (struct graph *g, int entry,
    406  1.1  mrg 		 int *parent, int *son, int *brother)
    407  1.1  mrg {
    408  1.1  mrg   vec<int> postorder = vNULL;
    409  1.1  mrg   int *marks = XCNEWVEC (int, g->n_vertices);
    410  1.1  mrg   int mark = 1, i, v, idom;
    411  1.1  mrg   bool changed = true;
    412  1.1  mrg   struct graph_edge *e;
    413  1.1  mrg 
    414  1.1  mrg   /* We use a slight modification of the standard iterative algorithm, as
    415  1.1  mrg      described in
    416  1.1  mrg 
    417  1.1  mrg      K. D. Cooper, T. J. Harvey and K. Kennedy: A Simple, Fast Dominance
    418  1.1  mrg 	Algorithm
    419  1.1  mrg 
    420  1.1  mrg      sort vertices in reverse postorder
    421  1.1  mrg      foreach v
    422  1.1  mrg        dom(v) = everything
    423  1.1  mrg      dom(entry) = entry;
    424  1.1  mrg 
    425  1.1  mrg      while (anything changes)
    426  1.1  mrg        foreach v
    427  1.1  mrg          dom(v) = {v} union (intersection of dom(p) over all predecessors of v)
    428  1.1  mrg 
    429  1.1  mrg      The sets dom(v) are represented by the parent links in the current version
    430  1.1  mrg      of the dominance tree.  */
    431  1.1  mrg 
    432  1.1  mrg   for (i = 0; i < g->n_vertices; i++)
    433  1.1  mrg     {
    434  1.1  mrg       parent[i] = -1;
    435  1.1  mrg       son[i] = -1;
    436  1.1  mrg       brother[i] = -1;
    437  1.1  mrg     }
    438  1.1  mrg   graphds_dfs (g, &entry, 1, &postorder, true, NULL);
    439  1.1  mrg   gcc_assert (postorder.length () == (unsigned) g->n_vertices);
    440  1.1  mrg   gcc_assert (postorder[g->n_vertices - 1] == entry);
    441  1.1  mrg 
    442  1.1  mrg   while (changed)
    443  1.1  mrg     {
    444  1.1  mrg       changed = false;
    445  1.1  mrg 
    446  1.1  mrg       for (i = g->n_vertices - 2; i >= 0; i--)
    447  1.1  mrg 	{
    448  1.1  mrg 	  v = postorder[i];
    449  1.1  mrg 	  idom = -1;
    450  1.1  mrg 	  for (e = g->vertices[v].pred; e; e = e->pred_next)
    451  1.1  mrg 	    {
    452  1.1  mrg 	      if (e->src != entry
    453  1.1  mrg 		  && parent[e->src] == -1)
    454  1.1  mrg 		continue;
    455  1.1  mrg 
    456  1.1  mrg 	      idom = tree_nca (idom, e->src, parent, marks, mark++);
    457  1.1  mrg 	    }
    458  1.1  mrg 
    459  1.1  mrg 	  if (idom != parent[v])
    460  1.1  mrg 	    {
    461  1.1  mrg 	      parent[v] = idom;
    462  1.1  mrg 	      changed = true;
    463  1.1  mrg 	    }
    464  1.1  mrg 	}
    465  1.1  mrg     }
    466  1.1  mrg 
    467  1.1  mrg   free (marks);
    468  1.1  mrg   postorder.release ();
    469  1.1  mrg 
    470  1.1  mrg   for (i = 0; i < g->n_vertices; i++)
    471  1.1  mrg     if (parent[i] != -1)
    472  1.1  mrg       {
    473  1.1  mrg 	brother[i] = son[parent[i]];
    474  1.1  mrg 	son[parent[i]] = i;
    475  1.1  mrg       }
    476  1.1  mrg }
    477