gcc/testsuite/
[official-gcc.git] / gcc / graphds.c
blobe19f564f7ca82b1c95d1014003f37a853b93ded0
1 /* Graph representation and manipulation functions.
2 Copyright (C) 2007-2014 Free Software Foundation, Inc.
4 This file is part of GCC.
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.
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.
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/>. */
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"
28 /* Dumps graph G into F. */
30 void
31 dump_graph (FILE *f, struct graph *g)
33 int i;
34 struct graph_edge *e;
36 for (i = 0; i < g->n_vertices; i++)
38 if (!g->vertices[i].pred
39 && !g->vertices[i].succ)
40 continue;
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");
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");
54 /* Creates a new graph with N_VERTICES vertices. */
56 struct graph *
57 new_graph (int n_vertices)
59 struct graph *g = XNEW (struct graph);
61 gcc_obstack_init (&g->ob);
62 g->n_vertices = n_vertices;
63 g->vertices = XOBNEWVEC (&g->ob, struct vertex, n_vertices);
64 memset (g->vertices, 0, sizeof (struct vertex) * n_vertices);
66 return g;
69 /* Adds an edge from F to T to graph G. The new edge is returned. */
71 struct graph_edge *
72 add_edge (struct graph *g, int f, int t)
74 struct graph_edge *e = XOBNEW (&g->ob, struct graph_edge);
75 struct vertex *vf = &g->vertices[f], *vt = &g->vertices[t];
77 e->src = f;
78 e->dest = t;
80 e->pred_next = vt->pred;
81 vt->pred = e;
83 e->succ_next = vf->succ;
84 vf->succ = e;
86 return e;
89 /* Moves all the edges incident with U to V. */
91 void
92 identify_vertices (struct graph *g, int v, int u)
94 struct vertex *vv = &g->vertices[v];
95 struct vertex *uu = &g->vertices[u];
96 struct graph_edge *e, *next;
98 for (e = uu->succ; e; e = next)
100 next = e->succ_next;
102 e->src = v;
103 e->succ_next = vv->succ;
104 vv->succ = e;
106 uu->succ = NULL;
108 for (e = uu->pred; e; e = next)
110 next = e->pred_next;
112 e->dest = v;
113 e->pred_next = vv->pred;
114 vv->pred = e;
116 uu->pred = NULL;
119 /* Helper function for graphds_dfs. Returns the source vertex of E, in the
120 direction given by FORWARD. */
122 static inline int
123 dfs_edge_src (struct graph_edge *e, bool forward)
125 return forward ? e->src : e->dest;
128 /* Helper function for graphds_dfs. Returns the destination vertex of E, in
129 the direction given by FORWARD. */
131 static inline int
132 dfs_edge_dest (struct graph_edge *e, bool forward)
134 return forward ? e->dest : e->src;
137 /* Helper function for graphds_dfs. Returns the first edge after E (including
138 E), in the graph direction given by FORWARD, that belongs to SUBGRAPH. */
140 static inline struct graph_edge *
141 foll_in_subgraph (struct graph_edge *e, bool forward, bitmap subgraph)
143 int d;
145 if (!subgraph)
146 return e;
148 while (e)
150 d = dfs_edge_dest (e, forward);
151 if (bitmap_bit_p (subgraph, d))
152 return e;
154 e = forward ? e->succ_next : e->pred_next;
157 return e;
160 /* Helper function for graphds_dfs. Select the first edge from V in G, in the
161 direction given by FORWARD, that belongs to SUBGRAPH. */
163 static inline struct graph_edge *
164 dfs_fst_edge (struct graph *g, int v, bool forward, bitmap subgraph)
166 struct graph_edge *e;
168 e = (forward ? g->vertices[v].succ : g->vertices[v].pred);
169 return foll_in_subgraph (e, forward, subgraph);
172 /* Helper function for graphds_dfs. Returns the next edge after E, in the
173 graph direction given by FORWARD, that belongs to SUBGRAPH. */
175 static inline struct graph_edge *
176 dfs_next_edge (struct graph_edge *e, bool forward, bitmap subgraph)
178 return foll_in_subgraph (forward ? e->succ_next : e->pred_next,
179 forward, subgraph);
182 /* Runs dfs search over vertices of G, from NQ vertices in queue QS.
183 The vertices in postorder are stored into QT. If FORWARD is false,
184 backward dfs is run. If SUBGRAPH is not NULL, it specifies the
185 subgraph of G to run DFS on. Returns the number of the components
186 of the graph (number of the restarts of DFS). */
189 graphds_dfs (struct graph *g, int *qs, int nq, vec<int> *qt,
190 bool forward, bitmap subgraph)
192 int i, tick = 0, v, comp = 0, top;
193 struct graph_edge *e;
194 struct graph_edge **stack = XNEWVEC (struct graph_edge *, g->n_vertices);
195 bitmap_iterator bi;
196 unsigned av;
198 if (subgraph)
200 EXECUTE_IF_SET_IN_BITMAP (subgraph, 0, av, bi)
202 g->vertices[av].component = -1;
203 g->vertices[av].post = -1;
206 else
208 for (i = 0; i < g->n_vertices; i++)
210 g->vertices[i].component = -1;
211 g->vertices[i].post = -1;
215 for (i = 0; i < nq; i++)
217 v = qs[i];
218 if (g->vertices[v].post != -1)
219 continue;
221 g->vertices[v].component = comp++;
222 e = dfs_fst_edge (g, v, forward, subgraph);
223 top = 0;
225 while (1)
227 while (e)
229 if (g->vertices[dfs_edge_dest (e, forward)].component
230 == -1)
231 break;
232 e = dfs_next_edge (e, forward, subgraph);
235 if (!e)
237 if (qt)
238 qt->safe_push (v);
239 g->vertices[v].post = tick++;
241 if (!top)
242 break;
244 e = stack[--top];
245 v = dfs_edge_src (e, forward);
246 e = dfs_next_edge (e, forward, subgraph);
247 continue;
250 stack[top++] = e;
251 v = dfs_edge_dest (e, forward);
252 e = dfs_fst_edge (g, v, forward, subgraph);
253 g->vertices[v].component = comp - 1;
257 free (stack);
259 return comp;
262 /* Determines the strongly connected components of G, using the algorithm of
263 Tarjan -- first determine the postorder dfs numbering in reversed graph,
264 then run the dfs on the original graph in the order given by decreasing
265 numbers assigned by the previous pass. If SUBGRAPH is not NULL, it
266 specifies the subgraph of G whose strongly connected components we want
267 to determine.
269 After running this function, v->component is the number of the strongly
270 connected component for each vertex of G. Returns the number of the
271 sccs of G. */
274 graphds_scc (struct graph *g, bitmap subgraph)
276 int *queue = XNEWVEC (int, g->n_vertices);
277 vec<int> postorder = vNULL;
278 int nq, i, comp;
279 unsigned v;
280 bitmap_iterator bi;
282 if (subgraph)
284 nq = 0;
285 EXECUTE_IF_SET_IN_BITMAP (subgraph, 0, v, bi)
287 queue[nq++] = v;
290 else
292 for (i = 0; i < g->n_vertices; i++)
293 queue[i] = i;
294 nq = g->n_vertices;
297 graphds_dfs (g, queue, nq, &postorder, false, subgraph);
298 gcc_assert (postorder.length () == (unsigned) nq);
300 for (i = 0; i < nq; i++)
301 queue[i] = postorder[nq - i - 1];
302 comp = graphds_dfs (g, queue, nq, NULL, true, subgraph);
304 free (queue);
305 postorder.release ();
307 return comp;
310 /* Runs CALLBACK for all edges in G. */
312 void
313 for_each_edge (struct graph *g, graphds_edge_callback callback)
315 struct graph_edge *e;
316 int i;
318 for (i = 0; i < g->n_vertices; i++)
319 for (e = g->vertices[i].succ; e; e = e->succ_next)
320 callback (g, e);
323 /* Releases the memory occupied by G. */
325 void
326 free_graph (struct graph *g)
328 obstack_free (&g->ob, NULL);
329 free (g);
332 /* Returns the nearest common ancestor of X and Y in tree whose parent
333 links are given by PARENT. MARKS is the array used to mark the
334 vertices of the tree, and MARK is the number currently used as a mark. */
336 static int
337 tree_nca (int x, int y, int *parent, int *marks, int mark)
339 if (x == -1 || x == y)
340 return y;
342 /* We climb with X and Y up the tree, marking the visited nodes. When
343 we first arrive to a marked node, it is the common ancestor. */
344 marks[x] = mark;
345 marks[y] = mark;
347 while (1)
349 x = parent[x];
350 if (x == -1)
351 break;
352 if (marks[x] == mark)
353 return x;
354 marks[x] = mark;
356 y = parent[y];
357 if (y == -1)
358 break;
359 if (marks[y] == mark)
360 return y;
361 marks[y] = mark;
364 /* If we reached the root with one of the vertices, continue
365 with the other one till we reach the marked part of the
366 tree. */
367 if (x == -1)
369 for (y = parent[y]; marks[y] != mark; y = parent[y])
370 continue;
372 return y;
374 else
376 for (x = parent[x]; marks[x] != mark; x = parent[x])
377 continue;
379 return x;
383 /* Determines the dominance tree of G (stored in the PARENT, SON and BROTHER
384 arrays), where the entry node is ENTRY. */
386 void
387 graphds_domtree (struct graph *g, int entry,
388 int *parent, int *son, int *brother)
390 vec<int> postorder = vNULL;
391 int *marks = XCNEWVEC (int, g->n_vertices);
392 int mark = 1, i, v, idom;
393 bool changed = true;
394 struct graph_edge *e;
396 /* We use a slight modification of the standard iterative algorithm, as
397 described in
399 K. D. Cooper, T. J. Harvey and K. Kennedy: A Simple, Fast Dominance
400 Algorithm
402 sort vertices in reverse postorder
403 foreach v
404 dom(v) = everything
405 dom(entry) = entry;
407 while (anything changes)
408 foreach v
409 dom(v) = {v} union (intersection of dom(p) over all predecessors of v)
411 The sets dom(v) are represented by the parent links in the current version
412 of the dominance tree. */
414 for (i = 0; i < g->n_vertices; i++)
416 parent[i] = -1;
417 son[i] = -1;
418 brother[i] = -1;
420 graphds_dfs (g, &entry, 1, &postorder, true, NULL);
421 gcc_assert (postorder.length () == (unsigned) g->n_vertices);
422 gcc_assert (postorder[g->n_vertices - 1] == entry);
424 while (changed)
426 changed = false;
428 for (i = g->n_vertices - 2; i >= 0; i--)
430 v = postorder[i];
431 idom = -1;
432 for (e = g->vertices[v].pred; e; e = e->pred_next)
434 if (e->src != entry
435 && parent[e->src] == -1)
436 continue;
438 idom = tree_nca (idom, e->src, parent, marks, mark++);
441 if (idom != parent[v])
443 parent[v] = idom;
444 changed = true;
449 free (marks);
450 postorder.release ();
452 for (i = 0; i < g->n_vertices; i++)
453 if (parent[i] != -1)
455 brother[i] = son[parent[i]];
456 son[parent[i]] = i;