gpu: generate host code from schedule tree
[ppcg.git] / schedule.c
blob37c4400f27b1dd82a0fa420d3e204c2835318eb1
1 /*
2 * Copyright 2010-2011 INRIA Saclay
4 * Use of this software is governed by the MIT license
6 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
7 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
8 * 91893 Orsay, France
9 */
11 #include <assert.h>
12 #include <ctype.h>
13 #include <string.h>
15 #include <isl/set.h>
16 #include <isl/map.h>
17 #include <isl/constraint.h>
19 #include "schedule.h"
21 /* Construct a map from a len-dimensional domain to
22 * a (len-n)-dimensional domain that projects out the n coordinates
23 * starting at first.
24 * "dim" prescribes the parameters.
26 __isl_give isl_map *project_out(__isl_take isl_space *dim,
27 int len, int first, int n)
29 int i, j;
30 isl_basic_map *bmap;
32 dim = isl_space_add_dims(dim, isl_dim_in, len);
33 dim = isl_space_add_dims(dim, isl_dim_out, len - n);
34 bmap = isl_basic_map_universe(dim);
36 for (i = 0, j = 0; i < len; ++i) {
37 if (i >= first && i < first + n)
38 continue;
39 bmap = isl_basic_map_equate(bmap, isl_dim_in, i, isl_dim_out, j);
40 ++j;
43 return isl_map_from_basic_map(bmap);
46 /* Construct a projection that maps a src_len dimensional domain
47 * to its first dst_len coordinates.
48 * "dim" prescribes the parameters.
50 __isl_give isl_map *projection(__isl_take isl_space *dim,
51 int src_len, int dst_len)
53 return project_out(dim, src_len, dst_len, src_len - dst_len);
56 /* Add parameters with identifiers "ids" to "set".
58 static __isl_give isl_set *add_params(__isl_take isl_set *set,
59 __isl_keep isl_id_list *ids)
61 int i, n;
62 unsigned nparam;
64 n = isl_id_list_n_id(ids);
66 nparam = isl_set_dim(set, isl_dim_param);
67 set = isl_set_add_dims(set, isl_dim_param, n);
69 for (i = 0; i < n; ++i) {
70 isl_id *id;
72 id = isl_id_list_get_id(ids, i);
73 set = isl_set_set_dim_id(set, isl_dim_param, nparam + i, id);
76 return set;
79 /* Equate the dimensions of "set" starting at "first" to
80 * freshly created parameters with identifiers "ids".
81 * The number of equated dimensions is equal to the number of elements in "ids".
83 static __isl_give isl_set *parametrize(__isl_take isl_set *set,
84 int first, __isl_keep isl_id_list *ids)
86 int i, n;
87 unsigned nparam;
89 nparam = isl_set_dim(set, isl_dim_param);
91 set = add_params(set, ids);
93 n = isl_id_list_n_id(ids);
94 for (i = 0; i < n; ++i)
95 set = isl_set_equate(set, isl_dim_param, nparam + i,
96 isl_dim_set, first + i);
98 return set;
101 /* Given a parameter space "space", create a set of dimension "len"
102 * of which the dimensions starting at "first" are equated to
103 * freshly created parameters with identifiers "ids".
105 __isl_give isl_set *parametrization(__isl_take isl_space *space,
106 int len, int first, __isl_keep isl_id_list *ids)
108 isl_set *set;
110 space = isl_space_set_from_params(space);
111 space = isl_space_add_dims(space, isl_dim_set, len);
112 set = isl_set_universe(space);
114 return parametrize(set, first, ids);
117 /* Extend "set" with unconstrained coordinates to a total length of "dst_len".
119 __isl_give isl_set *extend(__isl_take isl_set *set, int dst_len)
121 int n_set;
122 isl_space *dim;
123 isl_map *map;
125 dim = isl_set_get_space(set);
126 n_set = isl_space_dim(dim, isl_dim_set);
127 dim = isl_space_drop_dims(dim, isl_dim_set, 0, n_set);
128 map = projection(dim, dst_len, n_set);
129 map = isl_map_reverse(map);
131 return isl_set_apply(set, map);
134 /* Set max_out to the maximal number of output dimensions over
135 * all maps.
137 static int update_max_out(__isl_take isl_map *map, void *user)
139 int *max_out = user;
140 int n_out = isl_map_dim(map, isl_dim_out);
142 if (n_out > *max_out)
143 *max_out = n_out;
145 isl_map_free(map);
146 return 0;
149 struct align_range_data {
150 int max_out;
151 isl_union_map *res;
154 /* Extend the dimension of the range of the given map to data->max_out and
155 * then add the result to data->res.
157 static int map_align_range(__isl_take isl_map *map, void *user)
159 struct align_range_data *data = user;
160 int i;
161 isl_space *dim;
162 isl_map *proj;
163 int n_out = isl_map_dim(map, isl_dim_out);
165 dim = isl_union_map_get_space(data->res);
166 proj = isl_map_reverse(projection(dim, data->max_out, n_out));
167 for (i = n_out; i < data->max_out; ++i)
168 proj = isl_map_fix_si(proj, isl_dim_out, i, 0);
170 map = isl_map_apply_range(map, proj);
172 data->res = isl_union_map_add_map(data->res, map);
174 return 0;
177 /* Extend the ranges of the maps in the union map such they all have
178 * the same dimension.
180 __isl_give isl_union_map *align_range(__isl_take isl_union_map *umap)
182 struct align_range_data data;
184 data.max_out = 0;
185 isl_union_map_foreach_map(umap, &update_max_out, &data.max_out);
187 data.res = isl_union_map_empty(isl_union_map_get_space(umap));
188 isl_union_map_foreach_map(umap, &map_align_range, &data);
190 isl_union_map_free(umap);
191 return data.res;
194 /* Does "map" have an obviously fixed value at variable "pos" of "type"?
196 int map_plain_is_fixed(isl_map *map, enum isl_dim_type type, unsigned pos)
198 isl_val *v;
199 int fixed;
201 v = isl_map_plain_get_val_if_fixed(map, type, pos);
202 if (!v)
203 return -1;
204 fixed = isl_val_is_int(v);
205 isl_val_free(v);
207 return fixed;