1 /* Convert a PDG extracted using c2pdg and possibly transformed back to C code.
11 #include <isl/union_map.h>
13 #include <isl/ast_build.h>
14 #include <isl/id_to_ast_expr.h>
15 #include <isl/printer.h>
19 #include "pdg2c_options.h"
23 /* Find the element in scop->stmts that has the given "name".
25 static struct pet_stmt
*find_stmt(struct pet_scop
*scop
, const char *name
)
29 for (i
= 0; i
< scop
->n_stmt
; ++i
) {
30 struct pet_stmt
*stmt
= scop
->stmts
[i
];
33 name_i
= isl_set_get_tuple_name(stmt
->domain
);
34 if (!strcmp(name
, name_i
))
42 static __isl_give
void free_isl_id_to_ast_expr(void *user
);
43 static __isl_give isl_multi_pw_aff
*pullback_index(
44 __isl_take isl_multi_pw_aff
*mpa
, __isl_keep isl_id
*id
, void *user
);
45 static __isl_give isl_ast_node
*at_each_domain(__isl_take isl_ast_node
*node
,
46 __isl_keep isl_ast_build
*build
, void *user
);
47 static __isl_give isl_printer
*transform(__isl_take isl_printer
*p
,
48 struct pet_scop
*scop
, void *user
);
49 static __isl_give isl_printer
*print_user(__isl_take isl_printer
*p
,
50 __isl_take isl_ast_print_options
*print_options
,
51 __isl_keep isl_ast_node
*node
, void *user
);
54 static __isl_give
void free_isl_id_to_ast_expr(void *user
)
56 isl_id_to_ast_expr_free((isl_id_to_ast_expr
*) user
);
59 /* Find the element in scop->stmts that the same name
60 * as the function call by the given user node.
61 * These names are determined by the names of the domains
62 * of the schedule constructed in transform().
64 static pet_stmt
*extract_pet_stmt(__isl_keep isl_ast_node
*node
,
65 struct pet_scop
*scop
)
67 isl_ast_expr
*expr
, *arg
;
71 expr
= isl_ast_node_user_get_expr(node
);
72 arg
= isl_ast_expr_get_op_arg(expr
, 0);
73 isl_ast_expr_free(expr
);
74 id
= isl_ast_expr_get_id(arg
);
75 isl_ast_expr_free(arg
);
76 stmt
= find_stmt(scop
, isl_id_get_name(id
));
82 /* Index transformation callback for pet_stmt_build_ast_exprs.
84 * "index" expresses the array indices in terms of statement iterators
85 * "iterator_map" expresses the statement iterators in terms of
88 * The result expresses the array indices in terms of
91 static __isl_give isl_multi_pw_aff
*pullback_index(
92 __isl_take isl_multi_pw_aff
*index
, __isl_keep isl_id
*id
, void *user
)
94 isl_pw_multi_aff
*iterator_map
= (isl_pw_multi_aff
*) user
;
96 iterator_map
= isl_pw_multi_aff_copy(iterator_map
);
97 return isl_multi_pw_aff_pullback_pw_multi_aff(index
, iterator_map
);
100 /* Transform the accesses in the statement associated to the domain
101 * called by "node" to refer to the AST loop iterators, construct
102 * corresponding AST expressions using "build" and attach them
105 static __isl_give isl_ast_node
*at_each_domain(__isl_take isl_ast_node
*node
,
106 __isl_keep isl_ast_build
*build
, void *user
)
113 isl_pw_multi_aff
*iterator_map
;
114 isl_id_to_ast_expr
*ref2expr
;
115 struct pet_scop
*scop
= (struct pet_scop
*) user
;
117 ctx
= isl_ast_node_get_ctx(node
);
119 stmt
= extract_pet_stmt(node
, scop
);
121 isl_die(ctx
, isl_error_internal
, "cannot find statement",
122 isl_ast_node_free(node
); node
= NULL
);
124 map
= isl_map_from_union_map(isl_ast_build_get_schedule(build
));
125 map
= isl_map_reverse(map
);
126 iterator_map
= isl_pw_multi_aff_from_map(map
);
127 ref2expr
= pet_stmt_build_ast_exprs(stmt
, build
,
128 &pullback_index
, iterator_map
, NULL
, NULL
);
129 isl_pw_multi_aff_free(iterator_map
);
131 id
= isl_id_alloc(ctx
, NULL
, ref2expr
);
132 id
= isl_id_set_free_user(id
, &free_isl_id_to_ast_expr
);
134 return isl_ast_node_set_annotation(node
, id
);
137 /* Print the statement corresponding to "node" to "p".
138 * We look for the statement in the pet_scop passed through "user".
139 * The AST expressions for all references in the statement
140 * have been attached to the node by at_each_domain().
142 static __isl_give isl_printer
*print_user(__isl_take isl_printer
*p
,
143 __isl_take isl_ast_print_options
*print_options
,
144 __isl_keep isl_ast_node
*node
, void *user
)
146 isl_id_to_ast_expr
*ref2expr
;
148 struct pet_stmt
*stmt
;
149 struct pet_scop
*scop
= (struct pet_scop
*) user
;
151 stmt
= extract_pet_stmt(node
, scop
);
153 id
= isl_ast_node_get_annotation(node
);
154 ref2expr
= (isl_id_to_ast_expr
*) isl_id_get_user(id
);
157 p
= pet_stmt_print_body(stmt
, p
, ref2expr
);
159 isl_ast_print_options_free(print_options
);
164 /* Transform "scop" based on the schedule stored in "pdg" and
165 * print the result to "p".
167 static __isl_give isl_printer
*transform(__isl_take isl_printer
*p
,
168 struct pet_scop
*scop
, void *user
)
170 PDG
*pdg
= (PDG
*) user
;
172 isl_ast_build
*build
;
174 isl_ast_print_options
*print_options
;
175 isl_union_map
*sched
;
177 ctx
= isl_printer_get_ctx(p
);
178 build
= isl_ast_build_from_context(pdg
->get_context_isl_set());
179 build
= isl_ast_build_set_at_each_domain(build
, &at_each_domain
, scop
);
180 sched
= isl_union_map_empty(isl_space_params_alloc(ctx
, 0));
182 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
188 if (!pdg
->nodes
[i
]->schedule
)
189 isl_die(ctx
, isl_error_internal
, "Missing schedule",
190 isl_union_map_free(sched
); sched
= NULL
);
191 if (!pdg
->nodes
[i
]->name
)
192 isl_die(ctx
, isl_error_internal
, "Missing node name",
193 isl_union_map_free(sched
); sched
= NULL
);
197 name
= pdg
->nodes
[i
]->name
->s
.c_str();
199 source
= pdg
->nodes
[i
]->source
->get_isl_set(ctx
);
201 map
= pdg
->nodes
[i
]->schedule
->get_isl_map(ctx
);
202 map
= isl_map_intersect_domain(map
, source
);
203 id
= isl_id_alloc(ctx
, name
, NULL
);
204 map
= isl_map_set_tuple_id(map
, isl_dim_in
, id
);
206 sched
= isl_union_map_add_map(sched
, map
);
209 tree
= isl_ast_build_ast_from_schedule(build
, sched
);
210 isl_ast_build_free(build
);
212 p
= isl_ast_node_print_macros(tree
, p
);
214 print_options
= isl_ast_print_options_alloc(ctx
);
215 print_options
= isl_ast_print_options_set_print_user(print_options
,
217 p
= isl_ast_node_print(tree
, p
, print_options
);
219 isl_ast_node_free(tree
);
225 /* Given a C source code file and a PDG that is assumed to correspond
226 * to the first and only scop in this source code, print out the transformed
227 * C code based on the schedule of the PDG.
228 * The original PDG is assumed to have been extracted using c2pdg from
229 * the same source file.
231 int main(int argc
, char **argv
)
236 FILE *output
= stdout
;
237 struct options
*options
= options_new_with_defaults();
239 ctx
= isl_ctx_alloc_with_options(&options_args
, options
);
241 fprintf(stderr
, "Unable to allocate ctx\n");
245 pet_options_set_autodetect(ctx
, 1);
246 argc
= options_parse(options
, argc
, argv
, ISL_ARG_ALL
);
248 if (options
->input_pdg
&& strcmp(options
->input_pdg
, "-")) {
249 input
= fopen(options
->input_pdg
, "r");
252 if (options
->output
&& strcmp(options
->output
, "-")) {
253 output
= fopen(options
->output
, "w");
256 pdg
= PDG::Load(input
, ctx
);
259 if (pet_transform_C_source(ctx
, options
->input_C
, output
,
260 &transform
, pdg
) < 0)
266 if (output
!= stdout
)