PetScan: drop allow_nested attribute
[pet.git] / context.c
blobafa8c1deb9dd1790224f51f158392dab96a441b3
1 /*
2 * Copyright 2011 Leiden University. All rights reserved.
3 * Copyright 2014 Ecole Normale Superieure. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials provided
15 * with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY LEIDEN UNIVERSITY ''AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LEIDEN UNIVERSITY OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * The views and conclusions contained in the software and documentation
30 * are those of the authors and should not be interpreted as
31 * representing official policies, either expressed or implied, of
32 * Leiden University.
35 #include <isl/aff.h>
37 #include "context.h"
39 /* A pet_context represents the context in which a pet_expr
40 * in converted to an affine expression.
42 * "domain" prescribes the domain space of the affine expressions.
44 * "assignments" maps variable names to their currently known values.
45 * The domains of the values are equal to "domain".
46 * If a variable has been assigned an unknown value (possibly because
47 * it may be assigned a different expression in each iteration) or a value
48 * that is not an affine expression, then the corresponding isl_pw_aff
49 * is set to NaN.
51 * If "allow_nested" is set, then the affine expression created
52 * in this context may involve new parameters that encode a pet_expr.
54 struct pet_context {
55 int ref;
57 isl_space *domain;
58 isl_id_to_pw_aff *assignments;
59 int allow_nested;
62 /* Create a pet_context with the given domain, assignments,
63 * and value for allow_nested.
65 static __isl_give pet_context *context_alloc(__isl_take isl_space *domain,
66 __isl_take isl_id_to_pw_aff *assignments, int allow_nested)
68 pet_context *pc;
70 if (!domain || !assignments)
71 goto error;
73 pc = isl_calloc_type(isl_space_get_ctx(domain), struct pet_context);
74 if (!pc)
75 goto error;
77 pc->ref = 1;
78 pc->domain = domain;
79 pc->assignments = assignments;
80 pc->allow_nested = allow_nested;
82 return pc;
83 error:
84 isl_space_free(domain);
85 isl_id_to_pw_aff_free(assignments);
86 return NULL;
89 /* Create a pet_context with the given domain.
91 * Initially, there are no assigned values and parameters that
92 * encode a pet_expr are not allowed.
94 __isl_give pet_context *pet_context_alloc(__isl_take isl_space *domain)
96 isl_id_to_pw_aff *assignments;
98 if (!domain)
99 return NULL;
101 assignments = isl_id_to_pw_aff_alloc(isl_space_get_ctx(domain), 0);;
102 return context_alloc(domain, assignments, 0);
105 /* Return an independent duplicate of "pc".
107 static __isl_give pet_context *pet_context_dup(__isl_keep pet_context *pc)
109 pet_context *dup;
111 if (!pc)
112 return NULL;
114 dup = context_alloc(isl_space_copy(pc->domain),
115 isl_id_to_pw_aff_copy(pc->assignments),
116 pc->allow_nested);
118 return dup;
121 /* Return a pet_context that is equal to "pc" and that has only one reference.
123 static __isl_give pet_context *pet_context_cow(__isl_take pet_context *pc)
125 if (!pc)
126 return NULL;
128 if (pc->ref == 1)
129 return pc;
130 pc->ref--;
131 return pet_context_dup(pc);
134 /* Return an extra reference to "pc".
136 __isl_give pet_context *pet_context_copy(__isl_keep pet_context *pc)
138 if (!pc)
139 return NULL;
141 pc->ref++;
142 return pc;
145 /* Free a reference to "pc" and return NULL.
147 __isl_null pet_context *pet_context_free(__isl_take pet_context *pc)
149 if (!pc)
150 return NULL;
151 if (--pc->ref > 0)
152 return NULL;
154 isl_space_free(pc->domain);
155 isl_id_to_pw_aff_free(pc->assignments);
156 free(pc);
157 return NULL;
160 /* Return the isl_ctx in which "pc" was created.
162 isl_ctx *pet_context_get_ctx(__isl_keep pet_context *pc)
164 return pc ? isl_space_get_ctx(pc->domain) : NULL;
167 /* Return the domain space of "pc".
169 __isl_give isl_space *pet_context_get_space(__isl_keep pet_context *pc)
171 if (!pc)
172 return NULL;
173 return isl_space_copy(pc->domain);
176 /* Return the dimension of the domain space of "pc".
178 unsigned pet_context_dim(__isl_keep pet_context *pc)
180 if (!pc)
181 return 0;
182 return isl_space_dim(pc->domain, isl_dim_set);
185 /* Return the assignments of "pc".
187 __isl_give isl_id_to_pw_aff *pet_context_get_assignments(
188 __isl_keep pet_context *pc)
190 if (!pc)
191 return NULL;
192 return isl_id_to_pw_aff_copy(pc->assignments);
195 /* Is "id" assigned any value in "pc"?
197 int pet_context_is_assigned(__isl_keep pet_context *pc, __isl_keep isl_id *id)
199 if (!pc || !id)
200 return -1;
201 return isl_id_to_pw_aff_has(pc->assignments, id);
204 /* Return the value assigned to "id" in "pc".
206 __isl_give isl_pw_aff *pet_context_get_value(__isl_keep pet_context *pc,
207 __isl_take isl_id *id)
209 if (!pc || !id)
210 goto error;
212 return isl_id_to_pw_aff_get(pc->assignments, id);
213 error:
214 isl_id_free(id);
215 return NULL;
218 /* Assign the value "value" to "id" in "pc", replacing the previously
219 * assigned value, if any.
221 __isl_give pet_context *pet_context_set_value(__isl_take pet_context *pc,
222 __isl_take isl_id *id, isl_pw_aff *value)
224 pc = pet_context_cow(pc);
225 if (!pc)
226 goto error;
227 pc->assignments = isl_id_to_pw_aff_set(pc->assignments, id, value);
228 if (!pc->assignments)
229 return pet_context_free(pc);
230 return pc;
231 error:
232 isl_id_free(id);
233 isl_pw_aff_free(value);
234 return NULL;
237 /* Remove any assignment to "id" in "pc".
239 __isl_give pet_context *pet_context_clear_value(__isl_keep pet_context *pc,
240 __isl_take isl_id *id)
242 pc = pet_context_cow(pc);
243 if (!pc)
244 goto error;
245 pc->assignments = isl_id_to_pw_aff_drop(pc->assignments, id);
246 if (!pc->assignments)
247 return pet_context_free(pc);
248 return pc;
249 error:
250 isl_id_free(id);
251 return NULL;
254 /* Return a piecewise affine expression defined on the specified domain
255 * that represents NaN.
257 static __isl_give isl_pw_aff *nan_on_domain(__isl_take isl_space *space)
259 return isl_pw_aff_nan_on_domain(isl_local_space_from_space(space));
262 /* Assign the value NaN to "id" in "pc", marked it as having an unknown
263 * value.
265 __isl_give pet_context *pet_context_mark_unknown(__isl_take pet_context *pc,
266 __isl_take isl_id *id)
268 isl_pw_aff *pa;
270 pa = nan_on_domain(pet_context_get_space(pc));
271 pc = pet_context_set_value(pc, id, pa);
273 return pc;
276 /* Internal data structure used inside clear_assigned_parameter.
278 * "pc" is the context that is updated by clear_assigned_parameter.
279 * "id" is the identifier that was assigned an unknown value.
281 struct pet_context_mark_assigned_parameter_data {
282 pet_context *pc;
283 isl_id *id;
286 /* This function is called for each assignment in a pet_context
287 * when data->id is assigned an unknown value where it was not
288 * assigned any value before.
289 * Since it was not assigned any value before, it may have been
290 * treated as a parameter.
292 * If the value "value" does indeed refer to data->id as a parameter,
293 * then it is marked as unknown in data->pc since data->id can no
294 * longer be treated as a parameter and the current value has
295 * therefore been invalidated.
297 static int mark_assigned_parameter(__isl_take isl_id *id,
298 __isl_take isl_pw_aff *value, void *user)
300 struct pet_context_mark_assigned_parameter_data *data;
301 isl_space *space;
303 data = (struct pet_context_mark_assigned_parameter_data *) user;
305 space = isl_pw_aff_get_space(value);
306 if (isl_space_find_dim_by_id(space, isl_dim_param, data->id) >= 0)
307 data->pc = pet_context_mark_unknown(data->pc, id);
308 else
309 isl_id_free(id);
311 isl_space_free(space);
312 isl_pw_aff_free(value);
314 return 0;
317 /* This function is called when "id" may have been assigned some value.
319 * Mark "id" as having an unknown value in "pc".
321 * Furthermore, if no (known or unknown) value was assigned to "id" before,
322 * then it may have been treated as a parameter before and may
323 * therefore appear in a value assigned to another variable.
324 * If so, this assignment needs to be turned into an unknown value too.
326 __isl_give pet_context *pet_context_mark_assigned(__isl_take pet_context *pc,
327 __isl_take isl_id *id)
329 int was_assigned;
330 isl_id_to_pw_aff *assignments;
331 struct pet_context_mark_assigned_parameter_data data;
333 was_assigned = pet_context_is_assigned(pc, id);
335 pc = pet_context_mark_unknown(pc, isl_id_copy(id));
337 if (was_assigned) {
338 isl_id_free(id);
339 return pc;
342 assignments = pet_context_get_assignments(pc);
343 data.pc = pc;
344 data.id = id;
345 if (isl_id_to_pw_aff_foreach(assignments,
346 &mark_assigned_parameter, &data) < 0)
347 data.pc = pet_context_free(data.pc);
348 isl_id_to_pw_aff_free(assignments);
350 isl_id_free(id);
351 return data.pc;
354 /* Are affine expressions created in this context allowed to involve
355 * parameters that encode a pet_expr?
357 int pet_context_allow_nesting(__isl_keep pet_context *pc)
359 if (!pc)
360 return -1;
361 return pc->allow_nested;
364 /* Allow affine expressions created in this context to involve
365 * parameters that encode a pet_expr based on the value of "allow_nested".
367 __isl_give pet_context *pet_context_set_allow_nested(__isl_take pet_context *pc,
368 int allow_nested)
370 if (!pc)
371 return NULL;
372 if (pc->allow_nested == allow_nested)
373 return pc;
374 pc = pet_context_cow(pc);
375 if (!pc)
376 return NULL;
377 pc->allow_nested = allow_nested;
378 return pc;
381 void pet_context_dump(__isl_keep pet_context *pc)
383 if (!pc)
384 return;
385 fprintf(stderr, "domain: ");
386 isl_space_dump(pc->domain);
387 fprintf(stderr, "assignments: ");
388 isl_id_to_pw_aff_dump(pc->assignments);
389 fprintf(stderr, "nesting allowed: %d\n", pc->allow_nested);