/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/polly/lib/External/isl/isl_tarjan.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2010-2011 INRIA Saclay |
3 | | * Copyright 2012 Ecole Normale Superieure |
4 | | * |
5 | | * Use of this software is governed by the MIT license |
6 | | * |
7 | | * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France, |
8 | | * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod, |
9 | | * 91893 Orsay, France |
10 | | * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France |
11 | | */ |
12 | | |
13 | | #include <stdlib.h> |
14 | | #include <isl/ctx.h> |
15 | | #include <isl_tarjan.h> |
16 | | |
17 | | struct isl_tarjan_graph *isl_tarjan_graph_free(struct isl_tarjan_graph *g) |
18 | 965 | { |
19 | 965 | if (!g) |
20 | 0 | return NULL; |
21 | 965 | free(g->node); |
22 | 965 | free(g->stack); |
23 | 965 | free(g->order); |
24 | 965 | free(g); |
25 | 965 | return NULL; |
26 | 965 | } |
27 | | |
28 | | static struct isl_tarjan_graph *isl_tarjan_graph_alloc(isl_ctx *ctx, int len) |
29 | 965 | { |
30 | 965 | struct isl_tarjan_graph *g; |
31 | 965 | int i; |
32 | 965 | |
33 | 965 | g = isl_calloc_type(ctx, struct isl_tarjan_graph); |
34 | 965 | if (!g) |
35 | 0 | return NULL; |
36 | 965 | g->len = len; |
37 | 965 | g->node = isl_alloc_array(ctx, struct isl_tarjan_node, len); |
38 | 965 | if (len && !g->node) |
39 | 0 | goto error; |
40 | 2.76k | for (i = 0; 965 i < len; ++i1.80k ) |
41 | 1.80k | g->node[i].index = -1; |
42 | 965 | g->stack = isl_alloc_array(ctx, int, len); |
43 | 965 | if (len && !g->stack) |
44 | 0 | goto error; |
45 | 965 | g->order = isl_alloc_array(ctx, int, 2 * len); |
46 | 965 | if (len && !g->order) |
47 | 0 | goto error; |
48 | 965 | |
49 | 965 | g->sp = 0; |
50 | 965 | g->index = 0; |
51 | 965 | g->op = 0; |
52 | 965 | |
53 | 965 | return g; |
54 | 0 | error: |
55 | 0 | isl_tarjan_graph_free(g); |
56 | 0 | return NULL; |
57 | 965 | } |
58 | | |
59 | | /* Perform Tarjan's algorithm for computing the strongly connected components |
60 | | * in the graph with g->len nodes and with edges defined by "follows". |
61 | | */ |
62 | | static isl_stat isl_tarjan_components(struct isl_tarjan_graph *g, int i, |
63 | | isl_bool (*follows)(int i, int j, void *user), void *user) |
64 | 1.79k | { |
65 | 1.79k | int j; |
66 | 1.79k | |
67 | 1.79k | g->node[i].index = g->index; |
68 | 1.79k | g->node[i].min_index = g->index; |
69 | 1.79k | g->node[i].on_stack = 1; |
70 | 1.79k | g->index++; |
71 | 1.79k | g->stack[g->sp++] = i; |
72 | 1.79k | |
73 | 6.69k | for (j = g->len - 1; j >= 0; --j4.89k ) { |
74 | 4.89k | isl_bool f; |
75 | 4.89k | |
76 | 4.89k | if (j == i) |
77 | 1.79k | continue; |
78 | 3.09k | if (g->node[j].index >= 0 && |
79 | 3.09k | (1.76k !g->node[j].on_stack1.76k || |
80 | 1.76k | g->node[j].index > g->node[i].min_index1.08k )) |
81 | 1.11k | continue; |
82 | 1.98k | |
83 | 1.98k | f = follows(i, j, user); |
84 | 1.98k | if (f < 0) |
85 | 0 | return isl_stat_error; |
86 | 1.98k | if (!f) |
87 | 877 | continue; |
88 | 1.10k | |
89 | 1.10k | if (g->node[j].index < 0) { |
90 | 608 | isl_tarjan_components(g, j, follows, user); |
91 | 608 | if (g->node[j].min_index < g->node[i].min_index) |
92 | 2 | g->node[i].min_index = g->node[j].min_index; |
93 | 608 | } else if (501 g->node[j].index < g->node[i].min_index501 ) |
94 | 501 | g->node[i].min_index = g->node[j].index; |
95 | 1.10k | } |
96 | 1.79k | |
97 | 1.79k | if (g->node[i].index != g->node[i].min_index) |
98 | 503 | return isl_stat_ok; |
99 | 1.29k | |
100 | 1.79k | do 1.29k { |
101 | 1.79k | j = g->stack[--g->sp]; |
102 | 1.79k | g->node[j].on_stack = 0; |
103 | 1.79k | g->order[g->op++] = j; |
104 | 1.79k | } while (j != i); |
105 | 1.29k | g->order[g->op++] = -1; |
106 | 1.29k | |
107 | 1.29k | return isl_stat_ok; |
108 | 1.29k | } |
109 | | |
110 | | /* Decompose the graph with "len" nodes and edges defined by "follows" |
111 | | * into strongly connected components (SCCs). |
112 | | * follows(i, j, user) should return 1 if "i" follows "j" and 0 otherwise. |
113 | | * It should return -1 on error. |
114 | | * |
115 | | * If SCC a contains a node i that follows a node j in another SCC b |
116 | | * (i.e., follows(i, j, user) returns 1), then SCC a will appear after SCC b |
117 | | * in the result. |
118 | | */ |
119 | | struct isl_tarjan_graph *isl_tarjan_graph_init(isl_ctx *ctx, int len, |
120 | | isl_bool (*follows)(int i, int j, void *user), void *user) |
121 | 929 | { |
122 | 929 | int i; |
123 | 929 | struct isl_tarjan_graph *g = NULL; |
124 | 929 | |
125 | 929 | g = isl_tarjan_graph_alloc(ctx, len); |
126 | 929 | if (!g) |
127 | 0 | return NULL; |
128 | 2.63k | for (i = len - 1; 929 i >= 0; --i1.71k ) { |
129 | 1.71k | if (g->node[i].index >= 0) |
130 | 558 | continue; |
131 | 1.15k | if (isl_tarjan_components(g, i, follows, user) < 0) |
132 | 0 | return isl_tarjan_graph_free(g); |
133 | 1.15k | } |
134 | 929 | |
135 | 929 | return g; |
136 | 929 | } |
137 | | |
138 | | /* Decompose the graph with "len" nodes and edges defined by "follows" |
139 | | * into the strongly connected component (SCC) that contains "node" |
140 | | * as well as all SCCs that are followed by this SCC. |
141 | | * follows(i, j, user) should return 1 if "i" follows "j" and 0 otherwise. |
142 | | * It should return -1 on error. |
143 | | * |
144 | | * The SCC containing "node" will appear as the last component |
145 | | * in g->order. |
146 | | */ |
147 | | struct isl_tarjan_graph *isl_tarjan_graph_component(isl_ctx *ctx, int len, |
148 | | int node, isl_bool (*follows)(int i, int j, void *user), void *user) |
149 | 36 | { |
150 | 36 | struct isl_tarjan_graph *g; |
151 | 36 | |
152 | 36 | g = isl_tarjan_graph_alloc(ctx, len); |
153 | 36 | if (!g) |
154 | 0 | return NULL; |
155 | 36 | if (isl_tarjan_components(g, node, follows, user) < 0) |
156 | 0 | return isl_tarjan_graph_free(g); |
157 | 36 | |
158 | 36 | return g; |
159 | 36 | } |