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