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