1 /* Graph representation and manipulation functions.
3 Free Software Foundation, Inc.
5 This file is part of GCC.
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
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
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/>. */
23 #include "coretypes.h"
30 /* Dumps graph G into F. */
33 dump_graph (FILE *f, struct graph *g)
38 for (i = 0; i < g->n_vertices; i++)
40 if (!g->vertices[i].pred
41 && !g->vertices[i].succ)
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);
50 for (e = g->vertices[i].succ; e; e = e->succ_next)
51 fprintf (f, " %d", e->dest);
56 /* Creates a new graph with N_VERTICES vertices. */
59 new_graph (int n_vertices)
61 struct graph *g = XNEW (struct graph);
63 g->n_vertices = n_vertices;
64 g->vertices = XCNEWVEC (struct vertex, n_vertices);
69 /* Adds an edge from F to T to graph G. The new edge is returned. */
72 add_edge (struct graph *g, int f, int t)
74 struct graph_edge *e = XNEW (struct graph_edge);
75 struct vertex *vf = &g->vertices[f], *vt = &g->vertices[t];
81 e->pred_next = vt->pred;
84 e->succ_next = vf->succ;
90 /* Moves all the edges incident with U to V. */
93 identify_vertices (struct graph *g, int v, int u)
95 struct vertex *vv = &g->vertices[v];
96 struct vertex *uu = &g->vertices[u];
97 struct graph_edge *e, *next;
99 for (e = uu->succ; e; e = next)
104 e->succ_next = vv->succ;
109 for (e = uu->pred; e; e = next)
114 e->pred_next = vv->pred;
120 /* Helper function for graphds_dfs. Returns the source vertex of E, in the
121 direction given by FORWARD. */
124 dfs_edge_src (struct graph_edge *e, bool forward)
126 return forward ? e->src : e->dest;
129 /* Helper function for graphds_dfs. Returns the destination vertex of E, in
130 the direction given by FORWARD. */
133 dfs_edge_dest (struct graph_edge *e, bool forward)
135 return forward ? e->dest : e->src;
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. */
141 static inline struct graph_edge *
142 foll_in_subgraph (struct graph_edge *e, bool forward, bitmap subgraph)
151 d = dfs_edge_dest (e, forward);
152 if (bitmap_bit_p (subgraph, d))
155 e = forward ? e->succ_next : e->pred_next;
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. */
164 static inline struct graph_edge *
165 dfs_fst_edge (struct graph *g, int v, bool forward, bitmap subgraph)
167 struct graph_edge *e;
169 e = (forward ? g->vertices[v].succ : g->vertices[v].pred);
170 return foll_in_subgraph (e, forward, subgraph);
173 /* Helper function for graphds_dfs. Returns the next edge after E, in the
174 graph direction given by FORWARD, that belongs to SUBGRAPH. */
176 static inline struct graph_edge *
177 dfs_next_edge (struct graph_edge *e, bool forward, bitmap subgraph)
179 return foll_in_subgraph (forward ? e->succ_next : e->pred_next,
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). */
190 graphds_dfs (struct graph *g, int *qs, int nq, VEC (int, heap) **qt,
191 bool forward, bitmap subgraph)
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);
201 EXECUTE_IF_SET_IN_BITMAP (subgraph, 0, av, bi)
203 g->vertices[av].component = -1;
204 g->vertices[av].post = -1;
209 for (i = 0; i < g->n_vertices; i++)
211 g->vertices[i].component = -1;
212 g->vertices[i].post = -1;
216 for (i = 0; i < nq; i++)
219 if (g->vertices[v].post != -1)
222 g->vertices[v].component = comp++;
223 e = dfs_fst_edge (g, v, forward, subgraph);
230 if (g->vertices[dfs_edge_dest (e, forward)].component
233 e = dfs_next_edge (e, forward, subgraph);
239 VEC_safe_push (int, heap, *qt, v);
240 g->vertices[v].post = tick++;
246 v = dfs_edge_src (e, forward);
247 e = dfs_next_edge (e, forward, subgraph);
252 v = dfs_edge_dest (e, forward);
253 e = dfs_fst_edge (g, v, forward, subgraph);
254 g->vertices[v].component = comp - 1;
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
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
275 graphds_scc (struct graph *g, bitmap subgraph)
277 int *queue = XNEWVEC (int, g->n_vertices);
278 VEC (int, heap) *postorder = NULL;
286 EXECUTE_IF_SET_IN_BITMAP (subgraph, 0, v, bi)
293 for (i = 0; i < g->n_vertices; i++)
298 graphds_dfs (g, queue, nq, &postorder, false, subgraph);
299 gcc_assert (VEC_length (int, postorder) == (unsigned) nq);
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);
306 VEC_free (int, heap, postorder);
311 /* Runs CALLBACK for all edges in G. */
314 for_each_edge (struct graph *g, graphds_edge_callback callback)
316 struct graph_edge *e;
319 for (i = 0; i < g->n_vertices; i++)
320 for (e = g->vertices[i].succ; e; e = e->succ_next)
324 /* Releases the memory occupied by G. */
327 free_graph (struct graph *g)
329 struct graph_edge *e, *n;
333 for (i = 0; i < g->n_vertices; i++)
336 for (e = v->succ; e; e = n)
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. */
351 tree_nca (int x, int y, int *parent, int *marks, int mark)
353 if (x == -1 || x == y)
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. */
366 if (marks[x] == mark)
373 if (marks[y] == mark)
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
383 for (y = parent[y]; marks[y] != mark; y = parent[y])
390 for (x = parent[x]; marks[x] != mark; x = parent[x])
397 /* Determines the dominance tree of G (stored in the PARENT, SON and BROTHER
398 arrays), where the entry node is ENTRY. */
401 graphds_domtree (struct graph *g, int entry,
402 int *parent, int *son, int *brother)
404 VEC (int, heap) *postorder = NULL;
405 int *marks = XCNEWVEC (int, g->n_vertices);
406 int mark = 1, i, v, idom;
408 struct graph_edge *e;
410 /* We use a slight modification of the standard iterative algorithm, as
413 K. D. Cooper, T. J. Harvey and K. Kennedy: A Simple, Fast Dominance
416 sort vertices in reverse postorder
421 while (anything changes)
423 dom(v) = {v} union (intersection of dom(p) over all predecessors of v)
425 The sets dom(v) are represented by the parent links in the current version
426 of the dominance tree. */
428 for (i = 0; i < g->n_vertices; i++)
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);
442 for (i = g->n_vertices - 2; i >= 0; i--)
444 v = VEC_index (int, postorder, i);
446 for (e = g->vertices[v].pred; e; e = e->pred_next)
449 && parent[e->src] == -1)
452 idom = tree_nca (idom, e->src, parent, marks, mark++);
455 if (idom != parent[v])
464 VEC_free (int, heap, postorder);
466 for (i = 0; i < g->n_vertices; i++)
469 brother[i] = son[parent[i]];