1 /* Convert a PDG extracted using c2pdg and possibly transformed back to C code.
8 #include <isl/ast_build.h>
12 #include "pdg2c_options.h"
16 /* Find the element in scop->stmts that has the given "name".
18 static struct pet_stmt
*find_stmt(struct pet_scop
*scop
, const char *name
)
22 for (i
= 0; i
< scop
->n_stmt
; ++i
) {
23 struct pet_stmt
*stmt
= scop
->stmts
[i
];
26 name_i
= isl_set_get_tuple_name(stmt
->domain
);
27 if (!strcmp(name
, name_i
))
35 static __isl_give
void free_isl_id_to_ast_expr(void *user
);
36 static __isl_give isl_multi_pw_aff
*pullback_index(
37 __isl_take isl_multi_pw_aff
*mpa
, __isl_keep isl_id
*id
, void *user
);
38 static __isl_give isl_ast_node
*at_each_domain(__isl_take isl_ast_node
*node
,
39 __isl_keep isl_ast_build
*build
, void *user
);
40 static __isl_give isl_printer
*transform(__isl_take isl_printer
*p
,
41 struct pet_scop
*scop
, void *user
);
42 static __isl_give isl_printer
*print_user(__isl_take isl_printer
*p
,
43 __isl_take isl_ast_print_options
*print_options
,
44 __isl_keep isl_ast_node
*node
, void *user
);
47 static __isl_give
void free_isl_id_to_ast_expr(void *user
)
49 isl_id_to_ast_expr_free((isl_id_to_ast_expr
*) user
);
52 /* Find the element in scop->stmts that the same name
53 * as the function call by the given user node.
54 * These names are determined by the names of the domains
55 * of the schedule constructed in transform().
57 static pet_stmt
*extract_pet_stmt(__isl_keep isl_ast_node
*node
,
58 struct pet_scop
*scop
)
60 isl_ast_expr
*expr
, *arg
;
64 expr
= isl_ast_node_user_get_expr(node
);
65 arg
= isl_ast_expr_get_op_arg(expr
, 0);
66 isl_ast_expr_free(expr
);
67 id
= isl_ast_expr_get_id(arg
);
68 isl_ast_expr_free(arg
);
69 stmt
= find_stmt(scop
, isl_id_get_name(id
));
75 /* Index transformation callback for pet_stmt_build_ast_exprs.
77 * "index" expresses the array indices in terms of statement iterators
78 * "iterator_map" expresses the statement iterators in terms of
81 * The result expresses the array indices in terms of
84 static __isl_give isl_multi_pw_aff
*pullback_index(
85 __isl_take isl_multi_pw_aff
*index
, __isl_keep isl_id
*id
, void *user
)
87 isl_pw_multi_aff
*iterator_map
= (isl_pw_multi_aff
*) user
;
89 iterator_map
= isl_pw_multi_aff_copy(iterator_map
);
90 return isl_multi_pw_aff_pullback_pw_multi_aff(index
, iterator_map
);
93 /* Transform the accesses in the statement associated to the domain
94 * called by "node" to refer to the AST loop iterators, construct
95 * corresponding AST expressions using "build" and attach them
98 static __isl_give isl_ast_node
*at_each_domain(__isl_take isl_ast_node
*node
,
99 __isl_keep isl_ast_build
*build
, void *user
)
106 isl_pw_multi_aff
*iterator_map
;
107 isl_id_to_ast_expr
*ref2expr
;
108 struct pet_scop
*scop
= (struct pet_scop
*) user
;
110 ctx
= isl_ast_node_get_ctx(node
);
112 stmt
= extract_pet_stmt(node
, scop
);
114 isl_die(ctx
, isl_error_internal
, "cannot find statement",
115 isl_ast_node_free(node
); node
= NULL
);
117 map
= isl_map_from_union_map(isl_ast_build_get_schedule(build
));
118 map
= isl_map_reverse(map
);
119 iterator_map
= isl_pw_multi_aff_from_map(map
);
120 ref2expr
= pet_stmt_build_ast_exprs(stmt
, build
,
121 &pullback_index
, iterator_map
, NULL
, NULL
);
122 isl_pw_multi_aff_free(iterator_map
);
124 id
= isl_id_alloc(ctx
, NULL
, ref2expr
);
125 id
= isl_id_set_free_user(id
, &free_isl_id_to_ast_expr
);
127 return isl_ast_node_set_annotation(node
, id
);
130 /* Print the statement corresponding to "node" to "p".
131 * We look for the statement in the pet_scop passed through "user".
132 * The AST expressions for all references in the statement
133 * have been attached to the node by at_each_domain().
135 static __isl_give isl_printer
*print_user(__isl_take isl_printer
*p
,
136 __isl_take isl_ast_print_options
*print_options
,
137 __isl_keep isl_ast_node
*node
, void *user
)
139 isl_id_to_ast_expr
*ref2expr
;
141 struct pet_stmt
*stmt
;
142 struct pet_scop
*scop
= (struct pet_scop
*) user
;
144 stmt
= extract_pet_stmt(node
, scop
);
146 id
= isl_ast_node_get_annotation(node
);
147 ref2expr
= (isl_id_to_ast_expr
*) isl_id_get_user(id
);
150 p
= pet_stmt_print_body(stmt
, p
, ref2expr
);
152 isl_ast_print_options_free(print_options
);
157 /* Transform "scop" based on the schedule stored in "pdg" and
158 * print the result to "p".
160 static __isl_give isl_printer
*transform(__isl_take isl_printer
*p
,
161 struct pet_scop
*scop
, void *user
)
163 PDG
*pdg
= (PDG
*) user
;
165 isl_ast_build
*build
;
167 isl_ast_print_options
*print_options
;
168 isl_union_map
*sched
;
170 ctx
= isl_printer_get_ctx(p
);
171 build
= isl_ast_build_from_context(pdg
->get_context_isl_set());
172 build
= isl_ast_build_set_at_each_domain(build
, &at_each_domain
, scop
);
173 sched
= isl_union_map_empty(isl_space_params_alloc(ctx
, 0));
175 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
181 if (!pdg
->nodes
[i
]->schedule
)
182 isl_die(ctx
, isl_error_internal
, "Missing schedule",
183 isl_union_map_free(sched
); sched
= NULL
);
184 if (!pdg
->nodes
[i
]->name
)
185 isl_die(ctx
, isl_error_internal
, "Missing node name",
186 isl_union_map_free(sched
); sched
= NULL
);
190 name
= pdg
->nodes
[i
]->name
->s
.c_str();
192 source
= pdg
->nodes
[i
]->source
->get_isl_set(ctx
);
194 map
= pdg
->nodes
[i
]->schedule
->get_isl_map(ctx
);
195 map
= isl_map_intersect_domain(map
, source
);
196 id
= isl_id_alloc(ctx
, name
, NULL
);
197 map
= isl_map_set_tuple_id(map
, isl_dim_in
, id
);
199 sched
= isl_union_map_add_map(sched
, map
);
202 tree
= isl_ast_build_ast_from_schedule(build
, sched
);
203 isl_ast_build_free(build
);
205 p
= isl_ast_node_print_macros(tree
, p
);
207 print_options
= isl_ast_print_options_alloc(ctx
);
208 print_options
= isl_ast_print_options_set_print_user(print_options
,
210 p
= isl_ast_node_print(tree
, p
, print_options
);
212 isl_ast_node_free(tree
);
218 /* Given a C source code file and a PDG that is assumed to correspond
219 * to the first and only scop in this source code, print out the transformed
220 * C code based on the schedule of the PDG.
221 * The original PDG is assumed to have been extracted using c2pdg from
222 * the same source file.
224 int main(int argc
, char **argv
)
229 FILE *output
= stdout
;
230 struct options
*options
= options_new_with_defaults();
232 ctx
= isl_ctx_alloc_with_options(&options_args
, options
);
234 fprintf(stderr
, "Unable to allocate ctx\n");
238 pet_options_set_autodetect(ctx
, 1);
239 argc
= options_parse(options
, argc
, argv
, ISL_ARG_ALL
);
241 if (options
->input_pdg
&& strcmp(options
->input_pdg
, "-")) {
242 input
= fopen(options
->input_pdg
, "r");
245 if (options
->output
&& strcmp(options
->output
, "-")) {
246 output
= fopen(options
->output
, "w");
249 pdg
= PDG::Load(input
, ctx
);
252 if (pet_transform_C_source(ctx
, options
->input_C
, output
,
253 &transform
, pdg
) < 0)
259 if (output
!= stdout
)