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