9 extern "C" char *strndup(const char *s
, size_t n
);
16 dumper::visit(tree_node
*t
)
18 if (t
->peek_annote(k_static_root
)) {
19 /* Only dump a single domain */
30 if (t
->kind() == TREE_INSTR
) {
31 instruction
*in
= ((tree_instr
*)t
)->instr();
32 d
= (domain_ann
*)in
->peek_annote(k_iteration_domain
);
34 d
= (domain_ann
*)t
->peek_annote(k_iteration_domain
);
45 string
c_type(type_node
*tn
)
47 std::ostringstream strm
;
51 base_type
*bt
= (base_type
*) tn
;
55 switch (c_int_type(tn
)) {
79 switch (c_float_type(tn
)) {
87 strm
<< "long double";
95 struct_type
*st
= (struct_type
*) tn
;
96 strm
<< "struct " << st
->name();
106 static int compute_total_read(struct stmt_node
*node
, int c
)
108 if (node
->is_access()) {
109 stmt_access
*sa
= static_cast<stmt_access
*>(node
);
110 return c
+ !sa
->write
;
113 stmt_call
*sc
= static_cast<stmt_call
*>(node
);
115 for (int i
= 0; i
< sc
->arg
.size(); ++i
)
116 c
= compute_total_read(sc
->arg
[i
], c
);
121 static int compute_total_read(struct stmt
*s
)
123 return compute_total_read(s
->tree
, 0);
126 static type_node
*dereference_type(type_node
*tn
, array
*a
)
128 while (tn
->is_array() || tn
->is_ptr()) {
129 if (tn
->is_array()) {
130 array_type
*an
= dynamic_cast<array_type
*>(tn
);
131 assert(an
->lower_bound().is_constant());
132 assert(an
->upper_bound().is_constant());
133 tn
= an
->elem_type();
134 a
->dims
.push_back(an
->upper_bound().constant() -
135 an
->lower_bound().constant() + 1);
137 ptr_type
*an
= dynamic_cast<ptr_type
*>(tn
);
139 a
->dims
.push_back(-1);
145 pdg::access
*dumper::add_access(pdg::node
*pn
, stmt_access
*sa
)
147 isl_ctx
*ctx
= pdg
->get_isl_ctx();
148 pdg::access
*a
= new pdg::access
;
149 for (int i
= 0; i
< sa
->map
->nested
.size(); ++i
)
150 a
->nested
.push_back(scan_stmt(pn
, sa
->map
->nested
[i
]));
151 var_sym
*av
= sa
->array
;
152 if (av
&& arrays
.find(av
) == arrays
.end()) {
153 array
*a
= new array();
154 a
->id
= av
->sym_id();
155 a
->name
= new str(av
->name());
156 type_node
*tn
= av
->type();
157 tn
= dereference_type(tn
, a
);
158 a
->element_type
= new str(c_type(tn
));
160 bounds
= (SRelation
*)av
->peek_annote(k_array_bounds
);
162 isl_set
*set
= relation2set(ctx
, *bounds
);
163 set
= isl_set_align_params(set
, isl_space_copy(dim
));
164 a
->value_bounds
= new pdg::IslSet(set
);
166 pdg
->arrays
.push_back(a
);
169 a
->array
= av
? arrays
[av
] : NULL
;
170 bool write
= sa
->write
;
171 a
->type
= write
? pdg::access::write
: pdg::access::read
;
172 isl_map
*map
= relation2map(ctx
, *sa
->map
);
173 map
= isl_map_align_params(map
, isl_space_copy(dim
));
174 if (sa
->map
->nested
.size() > 0) {
175 isl_space
*dim
= isl_space_domain(isl_map_get_space(map
));
177 int in
= isl_space_dim(dim
, isl_dim_set
) - sa
->map
->nested
.size();
178 dim
= isl_space_from_domain(dim
);
179 dim
= isl_space_move_dims(dim
, isl_dim_out
, 0,
180 isl_dim_in
, in
, sa
->map
->nested
.size());
181 dim
= isl_space_wrap(dim
);
182 flatten
= isl_set_flatten_map(isl_set_universe(dim
));
183 map
= isl_map_apply_domain(map
, isl_map_reverse(flatten
));
185 a
->map
= new pdg::IslMap(map
);
187 a
->nr
= totalread
+ nwrite
++;
190 pn
->statement
->accesses
.push_back(a
);
194 pdg::call_or_access
*dumper::scan_stmt(pdg::node
*pn
, stmt_node
*n
)
196 pdg::call_or_access
*coa
= new pdg::call_or_access
;
198 if (n
->is_access()) {
199 coa
->type
= pdg::call_or_access::t_access
;
200 coa
->access
= add_access(pn
, static_cast<stmt_access
*>(n
));
202 stmt_call
*sc
= static_cast<stmt_call
*>(n
);
203 coa
->type
= pdg::call_or_access::t_call
;
204 coa
->call
= new pdg::function_call
;
205 coa
->call
->name
= new str(string(sc
->name
));
207 for (int i
= 0; i
< sc
->arg
.size(); ++i
) {
208 pdg::call_or_access
*child
;
209 child
= scan_stmt(pn
, sc
->arg
[i
]);
210 coa
->call
->arguments
.push_back(child
);
217 /* Convert stmt to pdg::function_call and add all accesses to ps */
218 pdg::function_call
*dumper::scan_stmt(pdg::node
*pn
, stmt
*s
)
220 totalread
= compute_total_read(s
);
224 pdg::function_call
*call
;
225 pdg::call_or_access
*coa
= scan_stmt(pn
, s
->tree
);
227 for (int i
= 0; i
< s
->out
.size(); ++i
)
228 pn
->statement
->top_outputs
.push_back(add_access(pn
, s
->out
[i
]));
230 if (coa
->type
== pdg::call_or_access::t_access
) {
231 call
= new pdg::function_call
;
232 call
->arguments
.push_back(coa
);
233 call
->name
= new str(string(""));
241 void dumper::dump(int argc
, char * argv
[])
248 isl_ctx
= isl_ctx_alloc();
249 pdg
= new PDG(isl_ctx
);
250 pdg
->placement
= new str(string("original"));
253 const char *name
= tp
->proc()->file()->name();
254 const char *dot
= strrchr(name
, '.');
256 pdg
->name
= new str(string(name
));
258 char *basename
= strndup(name
, dot
-name
);
259 pdg
->name
= new str(string(basename
));
263 map
<var_sym
*, Param_Iterator
*>::iterator gi
;
264 for (gi
= sa
->vars
.begin(); gi
!= sa
->vars
.end(); ++gi
) {
265 if ((*gi
).second
->iterator
)
267 if ((*gi
).second
->assigned
)
269 if ((*gi
).second
->temp
)
271 pdg::parameter
*p
= new pdg::parameter
;
272 p
->id
= (*gi
).first
->sym_id();
273 p
->name
= new str((*gi
).second
->base_name());
274 if ((*gi
).second
->lb_set
)
275 p
->value
= new integer((*gi
).second
->lb
);
277 file_symtab
*symtab
= tp
->proc()->file()->symtab();
278 var_def_list_iter
j(symtab
->var_defs());
279 while (!j
.is_empty()) {
280 var_def
*def
= j
.step();
281 if (def
->variable() != (*gi
).first
)
283 annote_list_iter
i(def
->annotes());
284 while (!i
.is_empty()) {
285 annote
*an
= i
.step();
286 if (an
->name() != k_repeat_init
)
288 immed_list
*ims
= an
->immeds();
289 if ((*ims
)[2].kind() != im_int
)
291 p
->value
= new integer((*ims
)[2].integer());
295 pdg
->params
.push_back(p
);
298 dim
= isl_space_alloc(isl_ctx
, pdg
->params
.size(), 0, 0);
299 isl_dim_set_parameter_names(dim
, pdg
->params
);
302 isl_set
*set
= relation2set(isl_ctx
, *ctx
->ctx
);
303 set
= isl_set_align_params(set
, isl_space_copy(dim
));
304 set
= isl_set_params(set
);
305 pdg
->context
= new pdg::IslSet(set
);
309 for (int i
= 0; i
< nodes
.size(); ++i
) {
310 domain_ann
*n
= nodes
[i
];
311 if (!n
->domain
->is_satisfiable())
313 pdg::node
* pn
= new pdg::node
;
314 pdg::statement
* ps
= new pdg::statement
;
315 pdg
->nodes
.push_back(pn
);
318 ps
->operation
= n
->insn
? n
->insn
->number() : -1;
320 isl_set
*set
= relation2set(isl_ctx
, *n
->domain
);
321 set
= isl_set_align_params(set
, isl_space_copy(dim
));
322 pn
->source
= new pdg::IslSet(set
);
323 for (int j
= 0; j
< n
->plevel
; ++j
)
324 pn
->prefix
.push_back(n
->prefix
[j
]);
325 ps
->top_function
= scan_stmt(pn
, n
->statement
);
328 pdg
->add_history_line("pers", argc
, argv
);
333 isl_ctx_free(isl_ctx
);
337 visit (tree_node
*t
, void *d
)
339 ((dumper
*)d
)->visit(t
);
345 tp
->map(::visit
, (void *) this);
348 void dump(tree_proc
*tp
, context_info
*ctx
, int argc
, char * argv
[])