3 #include <isl/union_map.h>
7 #include "dependence_graph_relation_options.h"
9 /* Print the dependence graph of the input program as a single relation.
10 * If type is "mem" (the default), then memory based dependences are
11 * computed, i.e., there is a dependence between two statement iterations
12 * if they (may) access the same memory location, where at least one
13 * of the accesses is a write, and if the first statement iteration is
14 * executed before the second.
15 * If type is "val", then value based dependence are computed.
16 * If type is "flow", then value based flow dependence are computed.
22 /* Compute and return the maximal iteration domain dimension.
24 int get_max_dim(PDG
*pdg
)
27 isl_ctx
*ctx
= pdg
->get_isl_ctx();
29 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
33 dom
= pdg
->nodes
[i
]->source
->get_isl_set(ctx
);
35 dim
= isl_set_dim(dom
, isl_dim_set
);
45 /* Return 2 * d + b, where d is the shared nesting level and b
46 * is true is first textually appears before second.
48 static int precedes_level_nodes(pdg::node
*first
, pdg::node
*second
)
52 for (int i
= 0; i
< first
->prefix
.size(); ++i
) {
53 if (i
>= second
->prefix
.size())
55 cmp
= first
->prefix
[i
] - second
->prefix
[i
];
58 if (first
->prefix
[i
] == -1)
61 return 2 * d
+ (cmp
< 0);
64 /* Pad either the input or the output dimension of the map to max_dim
65 * and add an extra dimension with as fixed value "nr".
67 isl_map
*normalize_dim(isl_map
*map
, enum isl_dim_type type
, int nr
,
68 int max_dim
, struct options
*options
)
72 sprintf(s
, "N_%d", nr
);
73 map
= isl_map_set_tuple_name(map
, type
, s
);
75 unsigned dim
= isl_map_dim(map
, type
);
76 map
= isl_map_add_dims(map
, type
, max_dim
- dim
+ 1);
77 for (int i
= dim
; i
< max_dim
; ++i
)
78 isl_map_fix_si(map
, type
, i
, 0);
79 isl_map_fix_si(map
, type
, max_dim
, nr
);
84 /* Compute memory based dependences from the given access to any
85 * other access and add them to "graph".
87 * If there are any data-dependent accesses, i.e., with nested
88 * accesses, then the nested access values are projected out.
90 isl_union_map
*add_dependences_from(isl_union_map
*graph
, PDG
*pdg
,
91 pdg::node
*from_node
, pdg::access
*from
, int max_dim
,
92 struct options
*options
)
94 isl_ctx
*ctx
= pdg
->get_isl_ctx();
96 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
97 pdg::node
*to_node
= pdg
->nodes
[i
];
98 pdg::statement
*s
= pdg
->nodes
[i
]->statement
;
99 int level
= precedes_level_nodes(from_node
, to_node
);
100 int before
= level
% 2;
103 for (int j
= 0; j
< s
->accesses
.size(); ++j
) {
104 pdg::access
*to
= s
->accesses
[j
];
109 int from_space
, to_dim
;
111 if (to
->array
!= from
->array
)
113 if (to
->type
== pdg::access::read
&&
114 from
->type
== pdg::access::read
)
117 r_from
= from
->map
->get_isl_map(ctx
);
118 r_to
= to
->map
->get_isl_map(ctx
);
120 from_space
= from_node
->source
->dim();
121 r_from
= isl_map_project_out(r_from
,
122 isl_dim_in
, from_space
,
123 from
->map
->input() - from_space
);
124 to_dim
= to_node
->source
->dim();
125 r_to
= isl_map_project_out(r_to
,
127 to
->map
->input() - to_dim
);
129 r_from
= isl_map_intersect_domain(r_from
,
130 from_node
->source
->get_isl_set(ctx
));
131 r_to
= isl_map_intersect_domain(r_to
,
132 to_node
->source
->get_isl_set(ctx
));
134 dep
= isl_map_apply_range(r_from
, isl_map_reverse(r_to
));
136 order
= isl_map_lex_le_first(
137 isl_map_get_space(dep
), level
);
139 order
= isl_map_lex_lt_first(
140 isl_map_get_space(dep
), level
);
141 dep
= isl_map_intersect(dep
, order
);
142 dep
= normalize_dim(dep
, isl_dim_in
,
143 from_node
->nr
, max_dim
, options
);
144 dep
= normalize_dim(dep
, isl_dim_out
,
145 to_node
->nr
, max_dim
, options
);
147 graph
= isl_union_map_add_map(graph
, dep
);
154 /* Compute all memory based dependences and add them to "graph".
156 isl_union_map
*add_mem_dependences(isl_union_map
*graph
, PDG
*pdg
, int max_dim
,
157 struct options
*options
)
159 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
160 pdg::node
*node
= pdg
->nodes
[i
];
161 pdg::statement
*s
= pdg
->nodes
[i
]->statement
;
163 for (int j
= 0; j
< s
->accesses
.size(); ++j
) {
164 pdg::access
*access
= s
->accesses
[j
];
165 graph
= add_dependences_from(graph
, pdg
, node
, access
,
173 /* Compute all value based flow dependences and add them to "graph".
175 * If there are any data-dependent accesses, i.e., with nested
176 * accesses, then the nested access values are projected out.
178 isl_union_map
*add_val_dependences(isl_union_map
*graph
, PDG
*pdg
, int max_dim
,
179 struct options
*options
)
181 isl_ctx
*ctx
= pdg
->get_isl_ctx();
183 for (int i
= 0; i
< pdg
->arrays
.size(); ++i
)
184 find_deps(pdg
, pdg
->arrays
[i
], flow
);
185 if (options
->type
!= TYPE_FLOW
) {
186 for (int i
= 0; i
< pdg
->arrays
.size(); ++i
)
187 find_deps(pdg
, pdg
->arrays
[i
], anti
);
188 for (int i
= 0; i
< pdg
->arrays
.size(); ++i
)
189 find_deps(pdg
, pdg
->arrays
[i
], output
);
192 for (int i
= 0; i
< pdg
->dependences
.size(); ++i
) {
193 int from_space
, to_dim
;
194 pdg::dependence
*dep
= pdg
->dependences
[i
];
195 if (dep
->type
== pdg::dependence::uninitialized
)
198 isl_map
*map
= dep
->relation
->get_isl_map(ctx
);
199 from_space
= dep
->from
->source
->dim();
200 to_dim
= dep
->to
->source
->dim();
201 map
= isl_map_project_out(map
, isl_dim_in
, from_space
,
202 dep
->relation
->input() - from_space
);
203 map
= isl_map_project_out(map
, isl_dim_out
, to_dim
,
204 dep
->relation
->output() - to_dim
);
205 map
= normalize_dim(map
, isl_dim_in
, dep
->from
->nr
, max_dim
,
207 map
= normalize_dim(map
, isl_dim_out
, dep
->to
->nr
, max_dim
,
210 graph
= isl_union_map_add_map(graph
, map
);
216 int main(int argc
, char *argv
[])
219 isl_ctx
*ctx
= isl_ctx_alloc();
224 isl_union_map
*graph
;
226 struct options
*options
= options_new_with_defaults();
228 argc
= options_parse(options
, argc
, argv
, ISL_ARG_ALL
);
230 if (options
->input
&& strcmp(options
->input
, "-"))
231 in
= fopen(options
->input
, "r");
234 pdg
= PDG::Load(in
, ctx
);
236 max_dim
= get_max_dim(pdg
);
238 nparam
= pdg
->params
.size();
239 dim
= isl_space_alloc(pdg
->get_isl_ctx(), nparam
, max_dim
+ 1, max_dim
+ 1);
240 isl_dim_set_parameter_names(dim
, pdg
->params
);
241 graph
= isl_union_map_empty(dim
);
243 if (options
->type
== TYPE_MEM
)
244 graph
= add_mem_dependences(graph
, pdg
, max_dim
, options
);
246 graph
= add_val_dependences(graph
, pdg
, max_dim
, options
);
248 p
= isl_printer_to_file(pdg
->get_isl_ctx(), stdout
);
249 p
= isl_printer_set_output_format(p
, ISL_FORMAT_ISL
);
250 p
= isl_printer_print_union_map(p
, graph
);
251 p
= isl_printer_end_line(p
);
254 isl_union_map_free(graph
);