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