1 #include <stdlib.h>
2 #include <string.h>
3 #include <assert.h>
4 #include "../include/cloog/cloog.h"
5 
6 #define ALLOC(type) (type*)malloc(sizeof(type))
7 #define ALLOCN(type,n) (type*)malloc((n)*sizeof(type))
8 
9 /**
10  * CloogInfos structure:
11  * this structure contains all the informations necessary for pretty printing,
12  * they come from the original CloogProgram structure (language, names), from
13  * genereral options (options) or are built only for pretty printing (stride).
14  * This structure is mainly there to reduce the number of function parameters,
15  * since most pprint.c functions need most of its field.
16  */
17 struct clooginfos {
18   CloogState *state;         /**< State. */
19   CloogStride **stride;
20   int stride_level;          /**< Number of valid entries in stride array. */
21   int  nb_scattdims ;        /**< Scattering dimension number. */
22   int * scaldims ;           /**< Boolean array saying whether a given
23                               *   scattering dimension is scalar or not.
24                               */
25   CloogNames * names ;       /**< Names of iterators and parameters. */
26   CloogOptions * options ;   /**< Options on CLooG's behaviour. */
27   CloogEqualities *equal;    /**< Matrix of equalities. */
28 } ;
29 
30 typedef struct clooginfos CloogInfos ;
31 
32 static int clast_expr_cmp(struct clast_expr *e1, struct clast_expr *e2);
33 static int clast_term_cmp(struct clast_term *t1, struct clast_term *t2);
34 static int clast_binary_cmp(struct clast_binary *b1, struct clast_binary *b2);
35 static int clast_reduction_cmp(struct clast_reduction *r1,
36 				 struct clast_reduction *r2);
37 
38 static struct clast_expr *clast_expr_copy(struct clast_expr *e);
39 
40 static int clast_equal_add(CloogEqualities *equal,
41 				CloogConstraintSet *constraints,
42 				int level, CloogConstraint *constraint,
43 				CloogInfos *infos);
44 
45 static struct clast_stmt *clast_equal(int level, CloogInfos *infos);
46 static struct clast_expr *clast_minmax(CloogConstraintSet *constraints,
47 					int level, int max, int guard,
48 					int lower_bound, int no_earlier,
49 					CloogInfos *infos);
50 static void insert_guard(CloogConstraintSet *constraints, int level,
51 			  struct clast_stmt ***next, CloogInfos *infos);
52 static int insert_modulo_guard(CloogConstraint *upper,
53 				CloogConstraint *lower, int level,
54 			        struct clast_stmt ***next, CloogInfos *infos);
55 static int insert_equation(CloogDomain *domain, CloogConstraint *upper,
56                            CloogConstraint *lower, int level,
57                            struct clast_stmt ***next, CloogInfos *infos);
58 static int insert_for(CloogDomain *domain, CloogConstraintSet *constraints,
59                       int level, int otl, struct clast_stmt ***next,
60                       CloogInfos *infos);
61 static void insert_block(CloogDomain *domain, CloogBlock *block, int level,
62 			 struct clast_stmt ***next, CloogInfos *infos);
63 static void insert_loop(CloogLoop * loop, int level,
64 			struct clast_stmt ***next, CloogInfos *infos);
65 
66 
new_clast_name(const char * name)67 struct clast_name *new_clast_name(const char *name)
68 {
69     struct clast_name *n = malloc(sizeof(struct clast_name));
70     n->expr.type = clast_expr_name;
71     n->name = name;
72     return n;
73 }
74 
new_clast_term(cloog_int_t c,struct clast_expr * v)75 struct clast_term *new_clast_term(cloog_int_t c, struct clast_expr *v)
76 {
77     struct clast_term *t = malloc(sizeof(struct clast_term));
78     t->expr.type = clast_expr_term;
79     cloog_int_init(t->val);
80     cloog_int_set(t->val, c);
81     t->var = v;
82     return t;
83 }
84 
new_clast_binary(enum clast_bin_type t,struct clast_expr * lhs,cloog_int_t rhs)85 struct clast_binary *new_clast_binary(enum clast_bin_type t,
86 				      struct clast_expr *lhs, cloog_int_t rhs)
87 {
88     struct clast_binary *b = malloc(sizeof(struct clast_binary));
89     b->expr.type = clast_expr_bin;
90     b->type = t;
91     b->LHS = lhs;
92     cloog_int_init(b->RHS);
93     cloog_int_set(b->RHS, rhs);
94     return b;
95 }
96 
new_clast_reduction(enum clast_red_type t,int n)97 struct clast_reduction *new_clast_reduction(enum clast_red_type t, int n)
98 {
99     int i;
100     struct clast_reduction *r;
101     r = malloc(sizeof(struct clast_reduction)+(n-1)*sizeof(struct clast_expr *));
102     r->expr.type = clast_expr_red;
103     r->type = t;
104     r->n = n;
105     for (i = 0; i < n; ++i)
106 	r->elts[i] = NULL;
107     return r;
108 }
109 
110 static void free_clast_root(struct clast_stmt *s);
111 
112 const struct clast_stmt_op stmt_root = { free_clast_root };
113 
free_clast_root(struct clast_stmt * s)114 static void free_clast_root(struct clast_stmt *s)
115 {
116     struct clast_root *r = (struct clast_root *)s;
117     assert(CLAST_STMT_IS_A(s, stmt_root));
118     cloog_names_free(r->names);
119     free(r);
120 }
121 
new_clast_root(CloogNames * names)122 struct clast_root *new_clast_root(CloogNames *names)
123 {
124     struct clast_root *r = malloc(sizeof(struct clast_root));
125     r->stmt.op = &stmt_root;
126     r->stmt.next = NULL;
127     r->names = cloog_names_copy(names);
128     return r;
129 }
130 
131 static void free_clast_assignment(struct clast_stmt *s);
132 
133 const struct clast_stmt_op stmt_ass = { free_clast_assignment };
134 
free_clast_assignment(struct clast_stmt * s)135 static void free_clast_assignment(struct clast_stmt *s)
136 {
137     struct clast_assignment *a = (struct clast_assignment *)s;
138     assert(CLAST_STMT_IS_A(s, stmt_ass));
139     free_clast_expr(a->RHS);
140     free(a);
141 }
142 
new_clast_assignment(const char * lhs,struct clast_expr * rhs)143 struct clast_assignment *new_clast_assignment(const char *lhs,
144 					      struct clast_expr *rhs)
145 {
146     struct clast_assignment *a = malloc(sizeof(struct clast_assignment));
147     a->stmt.op = &stmt_ass;
148     a->stmt.next = NULL;
149     a->LHS = lhs;
150     a->RHS = rhs;
151     return a;
152 }
153 
154 static void free_clast_user_stmt(struct clast_stmt *s);
155 
156 const struct clast_stmt_op stmt_user = { free_clast_user_stmt };
157 
free_clast_user_stmt(struct clast_stmt * s)158 static void free_clast_user_stmt(struct clast_stmt *s)
159 {
160     struct clast_user_stmt *u = (struct clast_user_stmt *)s;
161     assert(CLAST_STMT_IS_A(s, stmt_user));
162     cloog_domain_free(u->domain);
163     cloog_statement_free(u->statement);
164     cloog_clast_free(u->substitutions);
165     free(u);
166 }
167 
new_clast_user_stmt(CloogDomain * domain,CloogStatement * stmt,struct clast_stmt * subs)168 struct clast_user_stmt *new_clast_user_stmt(CloogDomain *domain,
169     CloogStatement *stmt, struct clast_stmt *subs)
170 {
171     struct clast_user_stmt *u = malloc(sizeof(struct clast_user_stmt));
172     u->stmt.op = &stmt_user;
173     u->stmt.next = NULL;
174     u->domain = cloog_domain_copy(domain);
175     u->statement = cloog_statement_copy(stmt);
176     u->substitutions = subs;
177     return u;
178 }
179 
180 static void free_clast_block(struct clast_stmt *b);
181 
182 const struct clast_stmt_op stmt_block = { free_clast_block };
183 
free_clast_block(struct clast_stmt * s)184 static void free_clast_block(struct clast_stmt *s)
185 {
186     struct clast_block *b = (struct clast_block *)s;
187     assert(CLAST_STMT_IS_A(s, stmt_block));
188     cloog_clast_free(b->body);
189     free(b);
190 }
191 
new_clast_block()192 struct clast_block *new_clast_block()
193 {
194     struct clast_block *b = malloc(sizeof(struct clast_block));
195     b->stmt.op = &stmt_block;
196     b->stmt.next = NULL;
197     b->body = NULL;
198     return b;
199 }
200 
201 static void free_clast_for(struct clast_stmt *s);
202 
203 const struct clast_stmt_op stmt_for = { free_clast_for };
204 
free_clast_for(struct clast_stmt * s)205 static void free_clast_for(struct clast_stmt *s)
206 {
207     struct clast_for *f = (struct clast_for *)s;
208     assert(CLAST_STMT_IS_A(s, stmt_for));
209     cloog_domain_free(f->domain);
210     free_clast_expr(f->LB);
211     free_clast_expr(f->UB);
212     cloog_int_clear(f->stride);
213     cloog_clast_free(f->body);
214     if (f->private_vars) free(f->private_vars);
215     if (f->reduction_vars) free(f->reduction_vars);
216     if (f->time_var_name) free(f->time_var_name);
217     if (f->user_directive) free(f->user_directive);
218     free(f);
219 }
220 
new_clast_for(CloogDomain * domain,const char * it,struct clast_expr * LB,struct clast_expr * UB,CloogStride * stride)221 struct clast_for *new_clast_for(CloogDomain *domain, const char *it,
222                                 struct clast_expr *LB, struct clast_expr *UB,
223                                 CloogStride *stride)
224 {
225     struct clast_for *f = malloc(sizeof(struct clast_for));
226     f->stmt.op = &stmt_for;
227     f->stmt.next = NULL;
228     f->domain = cloog_domain_copy(domain);
229     f->iterator = it;
230     f->LB = LB;
231     f->UB = UB;
232     f->body = NULL;
233     f->parallel = CLAST_PARALLEL_NOT;
234     f->private_vars = NULL;
235     f->reduction_vars = NULL;
236     f->time_var_name = NULL;
237     f->user_directive = NULL;
238     cloog_int_init(f->stride);
239     if (stride)
240 	cloog_int_set(f->stride, stride->stride);
241     else
242 	cloog_int_set_si(f->stride, 1);
243     return f;
244 }
245 
246 static void free_clast_guard(struct clast_stmt *s);
247 
248 const struct clast_stmt_op stmt_guard = { free_clast_guard };
249 
free_clast_guard(struct clast_stmt * s)250 static void free_clast_guard(struct clast_stmt *s)
251 {
252     int i;
253     struct clast_guard *g = (struct clast_guard *)s;
254     assert(CLAST_STMT_IS_A(s, stmt_guard));
255     cloog_clast_free(g->then);
256     for (i = 0; i < g->n; ++i) {
257 	free_clast_expr(g->eq[i].LHS);
258 	free_clast_expr(g->eq[i].RHS);
259     }
260     free(g);
261 }
262 
new_clast_guard(int n)263 struct clast_guard *new_clast_guard(int n)
264 {
265     int i;
266     struct clast_guard *g = malloc(sizeof(struct clast_guard) +
267 				   (n-1) * sizeof(struct clast_equation));
268     g->stmt.op = &stmt_guard;
269     g->stmt.next = NULL;
270     g->then = NULL;
271     g->n = n;
272     for (i = 0; i < n; ++i) {
273 	g->eq[i].LHS = NULL;
274 	g->eq[i].RHS = NULL;
275     }
276     return g;
277 }
278 
free_clast_name(struct clast_name * n)279 void free_clast_name(struct clast_name *n)
280 {
281     free(n);
282 }
283 
free_clast_term(struct clast_term * t)284 void free_clast_term(struct clast_term *t)
285 {
286     cloog_int_clear(t->val);
287     free_clast_expr(t->var);
288     free(t);
289 }
290 
free_clast_binary(struct clast_binary * b)291 void free_clast_binary(struct clast_binary *b)
292 {
293     cloog_int_clear(b->RHS);
294     free_clast_expr(b->LHS);
295     free(b);
296 }
297 
free_clast_reduction(struct clast_reduction * r)298 void free_clast_reduction(struct clast_reduction *r)
299 {
300     int i;
301     for (i = 0; i < r->n; ++i)
302 	free_clast_expr(r->elts[i]);
303     free(r);
304 }
305 
free_clast_expr(struct clast_expr * e)306 void free_clast_expr(struct clast_expr *e)
307 {
308     if (!e)
309 	return;
310     switch (e->type) {
311     case clast_expr_name:
312 	free_clast_name((struct clast_name*) e);
313 	break;
314     case clast_expr_term:
315 	free_clast_term((struct clast_term*) e);
316 	break;
317     case clast_expr_red:
318 	free_clast_reduction((struct clast_reduction*) e);
319 	break;
320     case clast_expr_bin:
321 	free_clast_binary((struct clast_binary*) e);
322 	break;
323     default:
324 	assert(0);
325     }
326 }
327 
free_clast_stmt(struct clast_stmt * s)328 void free_clast_stmt(struct clast_stmt *s)
329 {
330     assert(s->op);
331     assert(s->op->free);
332     s->op->free(s);
333 }
334 
cloog_clast_free(struct clast_stmt * s)335 void cloog_clast_free(struct clast_stmt *s)
336 {
337     struct clast_stmt *next;
338     while (s) {
339 	next = s->next;
340 	free_clast_stmt(s);
341 	s = next;
342     }
343 }
344 
clast_name_cmp(struct clast_name * n1,struct clast_name * n2)345 static int clast_name_cmp(struct clast_name *n1, struct clast_name *n2)
346 {
347     return n1->name == n2->name ? 0 : strcmp(n1->name, n2->name);
348 }
349 
clast_term_cmp(struct clast_term * t1,struct clast_term * t2)350 static int clast_term_cmp(struct clast_term *t1, struct clast_term *t2)
351 {
352     int c;
353     if (!t1->var && t2->var)
354 	return -1;
355     if (t1->var && !t2->var)
356 	return 1;
357     c = clast_expr_cmp(t1->var, t2->var);
358     if (c)
359 	return c;
360     return cloog_int_cmp(t1->val, t2->val);
361 }
362 
clast_binary_cmp(struct clast_binary * b1,struct clast_binary * b2)363 static int clast_binary_cmp(struct clast_binary *b1, struct clast_binary *b2)
364 {
365     int c;
366 
367     if (b1->type != b2->type)
368 	return b1->type - b2->type;
369     if ((c = cloog_int_cmp(b1->RHS, b2->RHS)))
370 	return c;
371     return clast_expr_cmp(b1->LHS, b2->LHS);
372 }
373 
clast_reduction_cmp(struct clast_reduction * r1,struct clast_reduction * r2)374 static int clast_reduction_cmp(struct clast_reduction *r1, struct clast_reduction *r2)
375 {
376     int i;
377     int c;
378 
379     if (r1->n == 1 && r2->n == 1)
380 	return clast_expr_cmp(r1->elts[0], r2->elts[0]);
381     if (r1->type != r2->type)
382 	return r1->type - r2->type;
383     if (r1->n != r2->n)
384 	return r1->n - r2->n;
385     for (i = 0; i < r1->n; ++i)
386 	if ((c = clast_expr_cmp(r1->elts[i], r2->elts[i])))
387 	    return c;
388     return 0;
389 }
390 
clast_expr_cmp(struct clast_expr * e1,struct clast_expr * e2)391 static int clast_expr_cmp(struct clast_expr *e1, struct clast_expr *e2)
392 {
393     if (!e1 && !e2)
394 	return 0;
395     if (!e1)
396 	return -1;
397     if (!e2)
398 	return 1;
399     if (e1->type != e2->type)
400 	return e1->type - e2->type;
401     switch (e1->type) {
402     case clast_expr_name:
403 	return clast_name_cmp((struct clast_name*) e1,
404 				(struct clast_name*) e2);
405     case clast_expr_term:
406 	return clast_term_cmp((struct clast_term*) e1,
407 				(struct clast_term*) e2);
408     case clast_expr_bin:
409 	return clast_binary_cmp((struct clast_binary*) e1,
410 				(struct clast_binary*) e2);
411     case clast_expr_red:
412 	return clast_reduction_cmp((struct clast_reduction*) e1,
413 				   (struct clast_reduction*) e2);
414     default:
415 	assert(0);
416     }
417 }
418 
clast_expr_equal(struct clast_expr * e1,struct clast_expr * e2)419 int clast_expr_equal(struct clast_expr *e1, struct clast_expr *e2)
420 {
421     return clast_expr_cmp(e1, e2) == 0;
422 }
423 
424 /**
425  * Return 1 is both expressions are constant terms and e1 is bigger than e2.
426  */
clast_expr_is_bigger_constant(struct clast_expr * e1,struct clast_expr * e2)427 int clast_expr_is_bigger_constant(struct clast_expr *e1, struct clast_expr *e2)
428 {
429     struct clast_term *t1, *t2;
430     struct clast_reduction *r;
431 
432     if (!e1 || !e2)
433 	return 0;
434     if (e1->type == clast_expr_red) {
435 	r = (struct clast_reduction *)e1;
436 	return r->n == 1 && clast_expr_is_bigger_constant(r->elts[0], e2);
437     }
438     if (e2->type == clast_expr_red) {
439 	r = (struct clast_reduction *)e2;
440 	return r->n == 1 && clast_expr_is_bigger_constant(e1, r->elts[0]);
441     }
442     if (e1->type != clast_expr_term || e2->type != clast_expr_term)
443 	return 0;
444     t1 = (struct clast_term *)e1;
445     t2 = (struct clast_term *)e2;
446     if (t1->var || t2->var)
447 	return 0;
448     return cloog_int_gt(t1->val, t2->val);
449 }
450 
qsort_expr_cmp(const void * p1,const void * p2)451 static int qsort_expr_cmp(const void *p1, const void *p2)
452 {
453     return clast_expr_cmp(*(struct clast_expr **)p1, *(struct clast_expr **)p2);
454 }
455 
clast_reduction_sort(struct clast_reduction * r)456 static void clast_reduction_sort(struct clast_reduction *r)
457 {
458     qsort(&r->elts[0], r->n, sizeof(struct clast_expr *), qsort_expr_cmp);
459 }
460 
qsort_eq_cmp(const void * p1,const void * p2)461 static int qsort_eq_cmp(const void *p1, const void *p2)
462 {
463     struct clast_equation *eq1 = (struct clast_equation *)p1;
464     struct clast_equation *eq2 = (struct clast_equation *)p2;
465     int cmp;
466 
467     cmp = clast_expr_cmp(eq1->LHS, eq2->LHS);
468     if (cmp)
469 	return cmp;
470 
471     cmp = clast_expr_cmp(eq1->RHS, eq2->RHS);
472     if (cmp)
473 	return cmp;
474 
475     return eq1->sign - eq2->sign;
476 }
477 
478 /**
479  * Sort equations in a clast_guard.
480  */
clast_guard_sort(struct clast_guard * g)481 static void clast_guard_sort(struct clast_guard *g)
482 {
483     qsort(&g->eq[0], g->n, sizeof(struct clast_equation), qsort_eq_cmp);
484 }
485 
486 
487 /**
488  * Construct a (deep) copy of an expression clast.
489  */
clast_expr_copy(struct clast_expr * e)490 static struct clast_expr *clast_expr_copy(struct clast_expr *e)
491 {
492     if (!e)
493 	return NULL;
494     switch (e->type) {
495     case clast_expr_name: {
496 	struct clast_name* n = (struct clast_name*) e;
497 	return &new_clast_name(n->name)->expr;
498     }
499     case clast_expr_term: {
500 	struct clast_term* t = (struct clast_term*) e;
501 	return &new_clast_term(t->val, clast_expr_copy(t->var))->expr;
502     }
503     case clast_expr_red: {
504 	int i;
505 	struct clast_reduction *r = (struct clast_reduction*) e;
506 	struct clast_reduction *r2 = new_clast_reduction(r->type, r->n);
507 	for (i = 0; i < r->n; ++i)
508 	    r2->elts[i] = clast_expr_copy(r->elts[i]);
509 	return &r2->expr;
510     }
511     case clast_expr_bin: {
512 	struct clast_binary *b = (struct clast_binary*) e;
513 	return &new_clast_binary(b->type, clast_expr_copy(b->LHS), b->RHS)->expr;
514     }
515     default:
516 	assert(0);
517     }
518 }
519 
520 
521 /******************************************************************************
522  *                        Equalities spreading functions                      *
523  ******************************************************************************/
524 
525 
526 /**
527  * clast_equal_allow function:
528  * This function checks whether the options allow us to spread the equality or
529  * not. It returns 1 if so, 0 otherwise.
530  * - equal is the matrix of equalities,
531  * - level is the column number in equal of the element which is 'equal to',
532  * - line is the line number in equal of the constraint we want to study,
533  * - the infos structure gives the user all options on code printing and more.
534  **
535  * - October 27th 2005: first version (extracted from old pprint_equal_add).
536  */
clast_equal_allow(CloogEqualities * equal,int level,int line,CloogInfos * infos)537 static int clast_equal_allow(CloogEqualities *equal, int level, int line,
538 				CloogInfos *infos)
539 {
540   if (level < infos->options->fsp)
541   return 0 ;
542 
543   if ((cloog_equal_type(equal, level) == EQTYPE_EXAFFINE) &&
544       !infos->options->esp)
545   return 0 ;
546 
547   return 1 ;
548 }
549 
550 
551 /**
552  * clast_equal_add function:
553  * This function updates the row (level-1) of the equality matrix (equal) with
554  * the row that corresponds to the row (line) of the matrix (matrix). It returns
555  * 1 if the row can be updated, 0 otherwise.
556  * - equal is the matrix of equalities,
557  * - matrix is the matrix of constraints,
558  * - level is the column number in matrix of the element which is 'equal to',
559  * - line is the line number in matrix of the constraint we want to study,
560  * - the infos structure gives the user all options on code printing and more.
561  */
clast_equal_add(CloogEqualities * equal,CloogConstraintSet * constraints,int level,CloogConstraint * constraint,CloogInfos * infos)562 static int clast_equal_add(CloogEqualities *equal,
563 				CloogConstraintSet *constraints,
564 				int level, CloogConstraint *constraint,
565 				CloogInfos *infos)
566 {
567     cloog_equal_add(equal, constraints, level, constraint,
568 		    infos->names->nb_parameters);
569 
570     return clast_equal_allow(equal, level, level-1, infos);
571 }
572 
573 
574 
575 /**
576  * clast_equal function:
577  * This function prints the substitution data of a statement into a clast_stmt.
578  * Using this function instead of pprint_equal is useful for generating
579  * a compilable pseudo-code by using preprocessor macro for each statement.
580  * By opposition to pprint_equal, the result is less human-readable. For
581  * instance this function will print (i,i+3,k,3) where pprint_equal would
582  * return (j=i+3,l=3).
583  * - level is the number of loops enclosing the statement,
584  * - the infos structure gives the user all options on code printing and more.
585  **
586  * - March    12th 2004: first version.
587  * - November 21th 2005: (debug) now works well with GMP version.
588  */
clast_equal(int level,CloogInfos * infos)589 static struct clast_stmt *clast_equal(int level, CloogInfos *infos)
590 {
591   int i ;
592   struct clast_expr *e;
593   struct clast_stmt *a = NULL;
594   struct clast_stmt **next = &a;
595   CloogEqualities *equal = infos->equal;
596   CloogConstraint *equal_constraint;
597 
598   for (i=infos->names->nb_scattering;i<level-1;i++)
599   { if (cloog_equal_type(equal, i+1)) {
600       equal_constraint = cloog_equal_constraint(equal, i);
601       e = clast_bound_from_constraint(equal_constraint, i+1, infos->names);
602       cloog_constraint_release(equal_constraint);
603     } else {
604       e = &new_clast_term(infos->state->one, &new_clast_name(
605 		 cloog_names_name_at_level(infos->names, i+1))->expr)->expr;
606     }
607     *next = &new_clast_assignment(NULL, e)->stmt;
608     next = &(*next)->next;
609   }
610 
611   return a;
612 }
613 
614 
615 /**
616  * clast_bound_from_constraint function:
617  * This function returns a clast_expr containing the printing of the
618  * 'right part' of a constraint according to an element.
619  * For instance, for the constraint -3*i + 2*j - M >=0 and the element j,
620  * we have j >= (3*i + M)/2. As we are looking for integral solutions, this
621  * function should return 'ceild(3*i+M,2)'.
622  * - matrix is the polyhedron containing all the constraints,
623  * - line_num is the line number in domain of the constraint we want to print,
624  * - level is the column number in domain of the element we want to use,
625  * - names structure gives the user some options about code printing,
626  *   the number of parameters in domain (nb_par), and the arrays of iterator
627  *   names and parameters (iters and params).
628  **
629  * - November 2nd 2001: first version.
630  * - June    27th 2003: 64 bits version ready.
631  */
clast_bound_from_constraint(CloogConstraint * constraint,int level,CloogNames * names)632 struct clast_expr *clast_bound_from_constraint(CloogConstraint *constraint,
633 					       int level, CloogNames *names)
634 {
635   int i, sign, nb_elts=0, len;
636   cloog_int_t *line, numerator, denominator, temp, division;
637   struct clast_expr *e = NULL;
638   struct cloog_vec *line_vector;
639 
640   len = cloog_constraint_total_dimension(constraint) + 2;
641   line_vector = cloog_vec_alloc(len);
642   line = line_vector->p;
643   cloog_constraint_copy_coefficients(constraint, line+1);
644   cloog_int_init(temp);
645   cloog_int_init(numerator);
646   cloog_int_init(denominator);
647 
648   if (!cloog_int_is_zero(line[level])) {
649     struct clast_reduction *r;
650     /* Maybe we need to invert signs in such a way that the element sign is>0.*/
651     sign = -cloog_int_sgn(line[level]);
652 
653     for (i = 1, nb_elts = 0; i <= len - 1; ++i)
654 	if (i != level && !cloog_int_is_zero(line[i]))
655 	    nb_elts++;
656     r = new_clast_reduction(clast_red_sum, nb_elts);
657     nb_elts = 0;
658 
659     /* First, we have to print the iterators and the parameters. */
660     for (i = 1; i <= len - 2; i++) {
661       struct clast_expr *v;
662 
663       if (i == level || cloog_int_is_zero(line[i]))
664 	continue;
665 
666       v = cloog_constraint_variable_expr(constraint, i, names);
667 
668       if (sign == -1)
669 	cloog_int_neg(temp,line[i]);
670       else
671 	cloog_int_set(temp,line[i]);
672 
673       r->elts[nb_elts++] = &new_clast_term(temp, v)->expr;
674     }
675 
676     if (sign == -1) {
677       cloog_int_neg(numerator, line[len - 1]);
678       cloog_int_set(denominator, line[level]);
679     }
680     else {
681       cloog_int_set(numerator, line[len - 1]);
682       cloog_int_neg(denominator, line[level]);
683     }
684 
685     /* Finally, the constant, and the final printing. */
686     if (nb_elts) {
687       if (!cloog_int_is_zero(numerator))
688 	  r->elts[nb_elts++] = &new_clast_term(numerator, NULL)->expr;
689 
690       if (!cloog_int_is_one(line[level]) && !cloog_int_is_neg_one(line[level]))
691       { if (!cloog_constraint_is_equality(constraint))
692         { if (cloog_int_is_pos(line[level]))
693 	    e = &new_clast_binary(clast_bin_cdiv, &r->expr, denominator)->expr;
694           else
695 	    e = &new_clast_binary(clast_bin_fdiv, &r->expr, denominator)->expr;
696         } else
697 	    e = &new_clast_binary(clast_bin_div, &r->expr, denominator)->expr;
698       }
699       else
700 	e = &r->expr;
701     } else {
702       free_clast_reduction(r);
703       if (cloog_int_is_zero(numerator))
704 	e = &new_clast_term(numerator, NULL)->expr;
705       else
706       { if (!cloog_int_is_one(denominator))
707         { if (!cloog_constraint_is_equality(constraint)) { /* useful? */
708             if (cloog_int_is_divisible_by(numerator, denominator)) {
709               cloog_int_divexact(temp, numerator, denominator);
710 	      e = &new_clast_term(temp, NULL)->expr;
711             }
712             else {
713               cloog_int_init(division);
714 	      cloog_int_tdiv_q(division, numerator, denominator);
715 	      if (cloog_int_is_neg(numerator)) {
716                 if (cloog_int_is_pos(line[level])) {
717 		    /* nb<0 need max */
718 		    e = &new_clast_term(division, NULL)->expr;
719 		} else {
720                   /* nb<0 need min */
721                   cloog_int_sub_ui(temp, division, 1);
722 		  e = &new_clast_term(temp, NULL)->expr;
723                 }
724 	      }
725               else
726               { if (cloog_int_is_pos(line[level]))
727 	        { /* nb>0 need max */
728                   cloog_int_add_ui(temp, division, 1);
729 		  e = &new_clast_term(temp, NULL)->expr;
730                 }
731 		else
732 		    /* nb>0 need min */
733 		    e = &new_clast_term(division, NULL)->expr;
734               }
735 	      cloog_int_clear(division);
736             }
737           }
738           else
739 	    e = &new_clast_binary(clast_bin_div,
740 				  &new_clast_term(numerator, NULL)->expr,
741 				  denominator)->expr;
742         }
743         else
744 	    e = &new_clast_term(numerator, NULL)->expr;
745       }
746     }
747   }
748 
749   cloog_vec_free(line_vector);
750 
751   cloog_int_clear(temp);
752   cloog_int_clear(numerator);
753   cloog_int_clear(denominator);
754 
755   return e;
756 }
757 
758 
759 /* Temporary structure for communication between clast_minmax and
760  * its cloog_constraint_set_foreach_constraint callback functions.
761  */
762 struct clast_minmax_data {
763     int level;
764     int max;
765     int guard;
766     int lower_bound;
767     int no_earlier;
768     CloogInfos *infos;
769     int n;
770     struct clast_reduction *r;
771 };
772 
773 
774 /* Should constraint "c" be considered by clast_minmax?
775  *
776  * If d->no_earlier is set, then the constraint may not involve
777  * any earlier variables.
778  */
valid_bound(CloogConstraint * c,struct clast_minmax_data * d)779 static int valid_bound(CloogConstraint *c, struct clast_minmax_data *d)
780 {
781     int i;
782 
783     if (d->max && !cloog_constraint_is_lower_bound(c, d->level - 1))
784 	return 0;
785     if (!d->max && !cloog_constraint_is_upper_bound(c, d->level - 1))
786 	return 0;
787     if (cloog_constraint_is_equality(c))
788 	return 0;
789     if (d->guard && cloog_constraint_involves(c, d->guard - 1))
790 	return 0;
791 
792     if (d->no_earlier)
793 	for (i = 0; i < d->level - 1; ++i)
794 	    if (cloog_constraint_involves(c, i))
795 		return 0;
796 
797     return 1;
798 }
799 
800 
801 /* Increment n for each bound that should be considered by clast_minmax.
802  */
count_bounds(CloogConstraint * c,void * user)803 static int count_bounds(CloogConstraint *c, void *user)
804 {
805     struct clast_minmax_data *d = (struct clast_minmax_data *) user;
806 
807     if (!valid_bound(c, d))
808 	return 0;
809 
810     d->n++;
811 
812     return 0;
813 }
814 
815 
816 /* Update the given lower bound based on stride information,
817  * for those cases where the stride offset is represented by
818  * a constraint.
819  * Note that cloog_loop_stride may have already performed a
820  * similar update of the lower bounds, but the updated lower
821  * bounds may have been eliminated because they are redundant
822  * by definition.  On the other hand, performing the update
823  * on an already updated constraint is an identity operation
824  * and is therefore harmless.
825  */
update_lower_bound_c(CloogConstraint * c,int level,CloogStride * stride)826 static CloogConstraint *update_lower_bound_c(CloogConstraint *c, int level,
827 	CloogStride *stride)
828 {
829     if (!stride->constraint)
830 	return c;
831     return cloog_constraint_stride_lower_bound(c, level, stride);
832 }
833 
834 
835 /* Update the given lower bound based on stride information.
836  * If the stride offset is represented by a constraint,
837  * then we have already performed the update in update_lower_bound_c.
838  * Otherwise, the original lower bound is known to be a constant.
839  * If the bound has already been updated and it just happens
840  * to be a constant, then this function performs an identity
841  * operation on the constant.
842  */
update_lower_bound(struct clast_expr * expr,int level,CloogStride * stride)843 static void update_lower_bound(struct clast_expr *expr, int level,
844 	CloogStride *stride)
845 {
846     struct clast_term *t;
847     if (stride->constraint)
848 	return;
849     if (expr->type != clast_expr_term)
850 	return;
851     t = (struct clast_term *)expr;
852     if (t->var)
853 	return;
854     cloog_int_sub(t->val, t->val, stride->offset);
855     cloog_int_cdiv_q(t->val, t->val, stride->stride);
856     cloog_int_mul(t->val, t->val, stride->stride);
857     cloog_int_add(t->val, t->val, stride->offset);
858 }
859 
860 
861 /* Add all relevant bounds to r->elts and update lower bounds
862  * based on stride information.
863  */
collect_bounds(CloogConstraint * c,void * user)864 static int collect_bounds(CloogConstraint *c, void *user)
865 {
866     struct clast_minmax_data *d = (struct clast_minmax_data *) user;
867 
868     if (!valid_bound(c, d))
869 	return 0;
870 
871     c = cloog_constraint_copy(c);
872 
873     if (d->lower_bound && d->infos->stride[d->level - 1])
874 	c = update_lower_bound_c(c, d->level, d->infos->stride[d->level - 1]);
875 
876     d->r->elts[d->n] = clast_bound_from_constraint(c, d->level,
877 							    d->infos->names);
878     if (d->lower_bound && d->infos->stride[d->level - 1]) {
879 	update_lower_bound(d->r->elts[d->n], d->level,
880 			   d->infos->stride[d->level - 1]);
881     }
882 
883     cloog_constraint_release(c);
884 
885     d->n++;
886 
887     return 0;
888 }
889 
890 
891 /**
892  * clast_minmax function:
893  * This function returns a clast_expr containing the printing of a minimum or a
894  * maximum of the 'right parts' of all constraints according to an element.
895  * For instance consider the constraints:
896  * -3*i  +2*j   -M >= 0
897  *  2*i    +j      >= 0
898  *   -i    -j +2*M >= 0
899  * if we are looking for the minimum for the element j, the function should
900  * return 'max(ceild(3*i+M,2),-2*i)'.
901  * - constraints is the constraints,
902  * - level is the column number in domain of the element we want to use,
903  * - max is a boolean set to 1 if we are looking for a maximum, 0 for a minimum,
904  * - guard is set to 0 if there is no guard, and set to the level of the element
905  *   with a guard otherwise (then the function gives the max or the min only
906  *   for the constraint where the guarded coefficient is 0),
907  * - lower is set to 1 if the maximum is to be used a lower bound on a loop
908  * - no_earlier is set if no constraints should be used that involve
909  *   earlier dimensions,
910  * - the infos structure gives the user some options about code printing,
911  *   the number of parameters in domain (nb_par), and the arrays of iterator
912  *   names and parameters (iters and params).
913  **
914  * - November 2nd 2001: first version.
915  */
clast_minmax(CloogConstraintSet * constraints,int level,int max,int guard,int lower_bound,int no_earlier,CloogInfos * infos)916 static struct clast_expr *clast_minmax(CloogConstraintSet *constraints,
917 				       int level, int max, int guard,
918 				       int lower_bound, int no_earlier,
919 				       CloogInfos *infos)
920 {
921     struct clast_minmax_data data = { level, max, guard, lower_bound,
922 				      no_earlier, infos };
923 
924     data.n = 0;
925 
926     cloog_constraint_set_foreach_constraint(constraints, count_bounds, &data);
927 
928     if (!data.n)
929 	return NULL;
930     data.r = new_clast_reduction(max ? clast_red_max : clast_red_min, data.n);
931 
932     data.n = 0;
933     cloog_constraint_set_foreach_constraint(constraints, collect_bounds, &data);
934 
935     clast_reduction_sort(data.r);
936     return &data.r->expr;
937 }
938 
939 
940 /**
941  * Insert modulo guards defined by existentially quantified dimensions,
942  * not involving the given level.
943  *
944  * This function is called from within insert_guard.
945  * Any constraint used in constructing a modulo guard is removed
946  * from the constraint set to avoid insert_guard
947  * adding a duplicate (pair of) constraint(s).
948  *
949  * Return the updated CloogConstraintSet.
950  */
insert_extra_modulo_guards(CloogConstraintSet * constraints,int level,struct clast_stmt *** next,CloogInfos * infos)951 static CloogConstraintSet *insert_extra_modulo_guards(
952 	CloogConstraintSet *constraints, int level,
953 	struct clast_stmt ***next, CloogInfos *infos)
954 {
955     int i;
956     int nb_iter;
957     int total_dim;
958     CloogConstraint *upper, *lower;
959 
960     total_dim = cloog_constraint_set_total_dimension(constraints);
961     nb_iter = cloog_constraint_set_n_iterators(constraints,
962 						infos->names->nb_parameters);
963 
964     for (i = total_dim - infos->names->nb_parameters; i >= nb_iter + 1; i--) {
965 	if (cloog_constraint_is_valid(upper =
966 		cloog_constraint_set_defining_equality(constraints, i))) {
967 	    if (!level || (nb_iter < level) ||
968 		    !cloog_constraint_involves(upper, level-1)) {
969 		insert_modulo_guard(upper,
970 				cloog_constraint_invalid(), i, next, infos);
971 		constraints = cloog_constraint_set_drop_constraint(constraints,
972 									upper);
973 	    }
974 	    cloog_constraint_release(upper);
975 	} else if (cloog_constraint_is_valid(upper =
976 		    cloog_constraint_set_defining_inequalities(constraints,
977 			      i, &lower, infos->names->nb_parameters))) {
978 	    if (!level || (nb_iter < level) ||
979 		    !cloog_constraint_involves(upper, level-1)) {
980 		insert_modulo_guard(upper, lower, i, next, infos);
981 		constraints = cloog_constraint_set_drop_constraint(constraints,
982 									upper);
983 		constraints = cloog_constraint_set_drop_constraint(constraints,
984 									lower);
985 	    }
986 	    cloog_constraint_release(upper);
987 	    cloog_constraint_release(lower);
988 	}
989     }
990 
991     return constraints;
992 }
993 
994 
995 /* Temporary structure for communication between insert_guard and
996  * its cloog_constraint_set_foreach_constraint callback function.
997  */
998 struct clast_guard_data {
999     int level;
1000     CloogInfos *infos;
1001     int n;
1002     int i;
1003     int nb_iter;
1004     CloogConstraintSet *copy;
1005     struct clast_guard *g;
1006 
1007     int min;
1008     int max;
1009 };
1010 
1011 
guard_count_bounds(CloogConstraint * c,void * user)1012 static int guard_count_bounds(CloogConstraint *c, void *user)
1013 {
1014     struct clast_guard_data *d = (struct clast_guard_data *) user;
1015 
1016     d->n++;
1017 
1018     return 0;
1019 }
1020 
1021 
1022 /* Insert a guard, if necesessary, for constraint j.
1023  *
1024  * If the constraint involves any earlier dimensions, then we have
1025  * already considered it during a previous iteration over the constraints.
1026  *
1027  * If we have already generated a min [max] for the current level d->i
1028  * and if the current constraint is an upper [lower] bound, then we
1029  * can skip the constraint as it will already have been used
1030  * in that previously generated min [max].
1031  */
insert_guard_constraint(CloogConstraint * j,void * user)1032 static int insert_guard_constraint(CloogConstraint *j, void *user)
1033 {
1034     int i;
1035     struct clast_guard_data *d = (struct clast_guard_data *) user;
1036     int minmax = -1;
1037     int individual_constraint;
1038     struct clast_expr *v;
1039     struct clast_term *t;
1040 
1041     if (!cloog_constraint_involves(j, d->i - 1))
1042 	return 0;
1043 
1044     for (i = 0; i < d->i - 1; ++i)
1045 	if (cloog_constraint_involves(j, i))
1046 	    return 0;
1047 
1048     if (d->level && d->nb_iter >= d->level &&
1049 	    cloog_constraint_involves(j, d->level - 1))
1050 	return 0;
1051 
1052     individual_constraint = !d->level || cloog_constraint_is_equality(j);
1053     if (!individual_constraint) {
1054 	if (d->max && cloog_constraint_is_lower_bound(j, d->i - 1))
1055 	    return 0;
1056 	if (d->min && cloog_constraint_is_upper_bound(j, d->i - 1))
1057 	    return 0;
1058     }
1059 
1060     v = cloog_constraint_variable_expr(j, d->i, d->infos->names);
1061     d->g->eq[d->n].LHS = &(t = new_clast_term(d->infos->state->one, v))->expr;
1062     if (individual_constraint) {
1063 	/* put the "denominator" in the LHS */
1064 	cloog_constraint_coefficient_get(j, d->i - 1, &t->val);
1065 	cloog_constraint_coefficient_set(j, d->i - 1, d->infos->state->one);
1066 	if (cloog_int_is_neg(t->val)) {
1067 	    cloog_int_neg(t->val, t->val);
1068 	    cloog_constraint_coefficient_set(j, d->i - 1, d->infos->state->negone);
1069 	}
1070 	if (d->level || cloog_constraint_is_equality(j))
1071 	    d->g->eq[d->n].sign = 0;
1072 	else if (cloog_constraint_is_lower_bound(j, d->i - 1))
1073 	    d->g->eq[d->n].sign = 1;
1074 	else
1075 	    d->g->eq[d->n].sign = -1;
1076 	d->g->eq[d->n].RHS = clast_bound_from_constraint(j, d->i, d->infos->names);
1077     } else {
1078 	int guarded;
1079 
1080 	if (cloog_constraint_is_lower_bound(j, d->i - 1)) {
1081 	    minmax = 1;
1082 	    d->max = 1;
1083 	    d->g->eq[d->n].sign = 1;
1084 	} else {
1085 	    minmax = 0;
1086 	    d->min = 1;
1087 	    d->g->eq[d->n].sign = -1;
1088 	}
1089 
1090 	guarded = (d->nb_iter >= d->level) ? d->level : 0 ;
1091 	d->g->eq[d->n].RHS = clast_minmax(d->copy,  d->i, minmax, guarded, 0, 1,
1092 					  d->infos);
1093     }
1094     d->n++;
1095 
1096     return 0;
1097 }
1098 
1099 
1100 /**
1101  * insert_guard function:
1102  * This function inserts a guard in the clast.
1103  * A guard on an element (level) is :
1104  * -> the conjunction of all the existing constraints where the coefficient of
1105  *    this element is 0 if the element is an iterator,
1106  * -> the conjunction of all the existing constraints if the element isn't an
1107  *    iterator.
1108  * For instance, considering these constraints and the element j:
1109  * -3*i +2*j -M >= 0
1110  *  2*i      +M >= 0
1111  * this function should return 'if (2*i+M>=0) {'.
1112  * - matrix is the polyhedron containing all the constraints,
1113  * - level is the column number of the element in matrix we want to use,
1114  * - the infos structure gives the user some options about code printing,
1115  *   the number of parameters in matrix (nb_par), and the arrays of iterator
1116  *   names and parameters (iters and params).
1117  **
1118  * - November  3rd 2001: first version.
1119  * - November 14th 2001: a lot of 'purifications'.
1120  * - July     31th 2002: (debug) some guard parts are no more redundants.
1121  * - August   12th 2002: polyhedra union ('or' conditions) are now supported.
1122  * - October  27th 2005: polyhedra union ('or' conditions) are no more supported
1123  *                       (the need came from loop_simplify that may result in
1124  *                       domain unions, now it should be fixed directly in
1125  *                       cloog_loop_simplify).
1126  */
insert_guard(CloogConstraintSet * constraints,int level,struct clast_stmt *** next,CloogInfos * infos)1127 static void insert_guard(CloogConstraintSet *constraints, int level,
1128 			 struct clast_stmt ***next, CloogInfos *infos)
1129 {
1130     int total_dim;
1131     struct clast_guard_data data = { level, infos, 0 };
1132 
1133     if (!constraints)
1134 	return;
1135 
1136     data.copy = cloog_constraint_set_copy(constraints);
1137 
1138     data.copy = insert_extra_modulo_guards(data.copy, level, next, infos);
1139 
1140     cloog_constraint_set_foreach_constraint(constraints,
1141 						guard_count_bounds, &data);
1142 
1143     data.g = new_clast_guard(data.n);
1144     data.n = 0;
1145 
1146     /* Well, it looks complicated because I wanted to have a particular, more
1147      * readable, ordering, obviously this function may be far much simpler !
1148      */
1149     data.nb_iter = cloog_constraint_set_n_iterators(constraints,
1150 						infos->names->nb_parameters);
1151 
1152     /* We search for guard parts. */
1153     total_dim = cloog_constraint_set_total_dimension(constraints);
1154     for (data.i = 1; data.i <= total_dim; data.i++) {
1155 	data.min = 0;
1156 	data.max = 0;
1157 	cloog_constraint_set_foreach_constraint(data.copy,
1158 						insert_guard_constraint, &data);
1159     }
1160 
1161     cloog_constraint_set_free(data.copy);
1162 
1163     data.g->n = data.n;
1164     if (data.n) {
1165 	clast_guard_sort(data.g);
1166 	**next = &data.g->stmt;
1167 	*next = &data.g->then;
1168     } else
1169 	free_clast_stmt(&data.g->stmt);
1170 }
1171 
1172 /**
1173  * Check if the constant "cst" satisfies the modulo guard that
1174  * would be introduced by insert_computed_modulo_guard.
1175  * The constant is assumed to have been reduced prior to calling
1176  * this function.
1177  */
constant_modulo_guard_is_satisfied(CloogConstraint * lower,cloog_int_t bound,cloog_int_t cst)1178 static int constant_modulo_guard_is_satisfied(CloogConstraint *lower,
1179 	cloog_int_t bound, cloog_int_t cst)
1180 {
1181     if (cloog_constraint_is_valid(lower))
1182 	return cloog_int_le(cst, bound);
1183     else
1184 	return cloog_int_is_zero(cst);
1185 }
1186 
1187 /**
1188  * Insert a modulo guard "r % mod == 0" or "r % mod <= bound",
1189  * depending on whether lower represents a valid constraint.
1190  */
insert_computed_modulo_guard(struct clast_reduction * r,CloogConstraint * lower,cloog_int_t mod,cloog_int_t bound,struct clast_stmt *** next)1191 static void insert_computed_modulo_guard(struct clast_reduction *r,
1192 	CloogConstraint *lower, cloog_int_t mod, cloog_int_t bound,
1193 	struct clast_stmt ***next)
1194 {
1195     struct clast_expr *e;
1196     struct clast_guard *g;
1197 
1198     e = &new_clast_binary(clast_bin_mod, &r->expr, mod)->expr;
1199     g = new_clast_guard(1);
1200     if (!cloog_constraint_is_valid(lower)) {
1201 	g->eq[0].LHS = e;
1202 	cloog_int_set_si(bound, 0);
1203 	g->eq[0].RHS = &new_clast_term(bound, NULL)->expr;
1204 	g->eq[0].sign = 0;
1205     } else {
1206 	g->eq[0].LHS = e;
1207 	g->eq[0].RHS = &new_clast_term(bound, NULL)->expr;
1208 	g->eq[0].sign = -1;
1209     }
1210 
1211     **next = &g->stmt;
1212     *next = &g->then;
1213 }
1214 
1215 
1216 /* Try and eliminate coefficients from a modulo constraint based on
1217  * stride information of an earlier level.
1218  * The modulo of the constraint being constructed is "m".
1219  * The stride information at level "level" is given by "stride"
1220  * and indicated that the iterator i at level "level" is equal to
1221  * some expression modulo stride->stride.
1222  * If stride->stride is a multiple of "m' then i is also equal to
1223  * the expression modulo m and so we can eliminate the coefficient of i.
1224  *
1225  * If stride->constraint is NULL, then i has a constant value modulo m, stored
1226  * stride->offset.  We simply multiply this constant with the coefficient
1227  * of i and add the result to the constant term, reducing it modulo m.
1228  *
1229  * If stride->constraint is not NULL, then it is a constraint of the form
1230  *
1231  *	e + k i = s a
1232  *
1233  * with s equal to stride->stride, e an expression in terms of the
1234  * parameters and earlier iterators and a some arbitrary expression
1235  * in terms of existentially quantified variables.
1236  * stride->factor is a value f such that f * k = -1 mod s.
1237  * Adding stride->constraint f * c times to the current modulo constraint,
1238  * with c the coefficient of i eliminates i in favor of parameters and
1239  * earlier variables.
1240  */
eliminate_using_stride_constraint(cloog_int_t * line,int len,int nb_iter,CloogStride * stride,int level,cloog_int_t m)1241 static void eliminate_using_stride_constraint(cloog_int_t *line, int len,
1242 	int nb_iter, CloogStride *stride, int level, cloog_int_t m)
1243 {
1244 	if (!stride)
1245 		return;
1246 	if (!cloog_int_is_divisible_by(stride->stride, m))
1247 		return;
1248 
1249 	if (stride->constraint) {
1250 		int i, s_len;
1251 		cloog_int_t t, v;
1252 
1253 		cloog_int_init(t);
1254 		cloog_int_init(v);
1255 		cloog_int_mul(t, line[level], stride->factor);
1256 		for (i = 1; i < level; ++i) {
1257 			cloog_constraint_coefficient_get(stride->constraint,
1258 							i - 1, &v);
1259 			cloog_int_addmul(line[i], t, v);
1260 			cloog_int_fdiv_r(line[i], line[i], m);
1261 		}
1262 		s_len = cloog_constraint_total_dimension(stride->constraint)+2;
1263 		for (i = nb_iter + 1; i <= len - 2; ++i) {
1264 			cloog_constraint_coefficient_get(stride->constraint,
1265 						i - (len - s_len) - 1, &v);
1266 			cloog_int_addmul(line[i], t, v);
1267 			cloog_int_fdiv_r(line[i], line[i], m);
1268 		}
1269 		cloog_constraint_constant_get(stride->constraint, &v);
1270 		cloog_int_addmul(line[len - 1], t, v);
1271 		cloog_int_fdiv_r(line[len - 1], line[len - 1], m);
1272 		cloog_int_clear(v);
1273 		cloog_int_clear(t);
1274 	} else {
1275 		cloog_int_addmul(line[len - 1], line[level], stride->offset);
1276 		cloog_int_fdiv_r(line[len - 1], line[len - 1], m);
1277 	}
1278 
1279 	cloog_int_set_si(line[level], 0);
1280 }
1281 
1282 
1283 /* Temporary structure for communication between insert_modulo_guard and
1284  * its cloog_constraint_set_foreach_constraint callback function.
1285  */
1286 struct clast_modulo_guard_data {
1287     CloogConstraint *lower;
1288     int level;
1289     struct clast_stmt ***next;
1290     CloogInfos *infos;
1291     int empty;
1292     cloog_int_t val, bound;
1293 };
1294 
1295 
1296 /* Insert a modulo guard for constraint c.
1297  * The constraint may be either an equality or an inequality.
1298  * Since this function returns -1, it is only called on a single constraint.
1299  * In case of an inequality, the constraint is usually an upper bound
1300  * on d->level.  However, if this variable is an existentially
1301  * quantified variable, the upper bound constraint may get removed
1302  * as trivially holding and then this function is called with
1303  * a lower bound instead.  In this case, we need to adjust the constraint
1304  * based on the sum of the constant terms of the lower and upper bound
1305  * stored in d->bound.
1306  */
insert_modulo_guard_constraint(CloogConstraint * c,void * user)1307 static int insert_modulo_guard_constraint(CloogConstraint *c, void *user)
1308 {
1309     struct clast_modulo_guard_data *d = (struct clast_modulo_guard_data *) user;
1310     int level = d->level;
1311     CloogInfos *infos = d->infos;
1312     int i, nb_elts = 0, len, nb_iter, nb_par;
1313     int constant;
1314     struct cloog_vec *line_vector;
1315     cloog_int_t *line;
1316 
1317     len = cloog_constraint_total_dimension(c) + 2;
1318     nb_par = infos->names->nb_parameters;
1319     nb_iter = len - 2 - nb_par;
1320 
1321     line_vector = cloog_vec_alloc(len);
1322     line = line_vector->p;
1323     cloog_constraint_copy_coefficients(c, line + 1);
1324 
1325     if (cloog_int_is_pos(line[level])) {
1326 	cloog_seq_neg(line + 1, line + 1, len - 1);
1327 	if (!cloog_constraint_is_equality(c))
1328 	    cloog_int_add(line[len - 1], line[len - 1], d->bound);
1329     }
1330     cloog_int_neg(line[level], line[level]);
1331     assert(cloog_int_is_pos(line[level]));
1332 
1333     nb_elts = 0;
1334     for (i = 1; i <= len-1; ++i) {
1335 	if (i == level)
1336 	    continue;
1337 	cloog_int_fdiv_r(line[i], line[i], line[level]);
1338 	if (cloog_int_is_zero(line[i]))
1339 	    continue;
1340 	if (i == len-1)
1341 	    continue;
1342 
1343 	nb_elts++;
1344     }
1345 
1346     if (nb_elts || !cloog_int_is_zero(line[len-1])) {
1347 	struct clast_reduction *r;
1348 	const char *name;
1349 
1350 	r = new_clast_reduction(clast_red_sum, nb_elts + 1);
1351 	nb_elts = 0;
1352 
1353 	/* First, the modulo guard : the iterators... */
1354 	i = level - 1;
1355 	if (i > infos->stride_level)
1356 		i = infos->stride_level;
1357 	for (; i >= 1; --i)
1358 	    eliminate_using_stride_constraint(line, len, nb_iter,
1359 					infos->stride[i - 1], i, line[level]);
1360 	for (i=1;i<=nb_iter;i++) {
1361 	  if (i == level || cloog_int_is_zero(line[i]))
1362 	    continue;
1363 
1364 	  name = cloog_names_name_at_level(infos->names, i);
1365 
1366 	  r->elts[nb_elts++] = &new_clast_term(line[i],
1367 				    &new_clast_name(name)->expr)->expr;
1368 	}
1369 
1370 	/* ...the parameters... */
1371 	for (i=nb_iter+1;i<=len-2;i++) {
1372 	  if (cloog_int_is_zero(line[i]))
1373 	    continue;
1374 
1375 	  name = infos->names->parameters[i-nb_iter-1] ;
1376 	  r->elts[nb_elts++] = &new_clast_term(line[i],
1377 				    &new_clast_name(name)->expr)->expr;
1378 	}
1379 
1380 	constant = nb_elts == 0;
1381 	/* ...the constant. */
1382 	if (!cloog_int_is_zero(line[len-1]))
1383 	  r->elts[nb_elts++] = &new_clast_term(line[len-1], NULL)->expr;
1384 
1385 	/* our initial computation may have been an overestimate */
1386 	r->n = nb_elts;
1387 
1388 	if (constant) {
1389 	  d->empty = !constant_modulo_guard_is_satisfied(d->lower, d->bound,
1390 							 line[len - 1]);
1391 	  free_clast_reduction(r);
1392 	} else
1393 	  insert_computed_modulo_guard(r, d->lower, line[level], d->bound,
1394 					d->next);
1395     }
1396 
1397     cloog_vec_free(line_vector);
1398 
1399     return -1;
1400 }
1401 
1402 
1403 /**
1404  * insert_modulo_guard:
1405  * This function inserts a modulo guard corresponding to an equality
1406  * or a pair of inequalities.
1407  * Returns 0 if the modulo guard is discovered to be unsatisfiable.
1408  *
1409  * See insert_equation.
1410  * - matrix is the polyhedron containing all the constraints,
1411  * - upper and lower are the line numbers of the constraint in matrix
1412  *   we want to print; in particular, if we want to print an equality,
1413  *   then lower == -1 and upper is the row of the equality; if we want
1414  *   to print an inequality, then upper is the row of the upper bound
1415  *   and lower in the row of the lower bound
1416  * - level is the column number of the element in matrix we want to use,
1417  * - the infos structure gives the user some options about code printing,
1418  *   the number of parameters in matrix (nb_par), and the arrays of iterator
1419  *   names and parameters (iters and params).
1420  */
insert_modulo_guard(CloogConstraint * upper,CloogConstraint * lower,int level,struct clast_stmt *** next,CloogInfos * infos)1421 static int insert_modulo_guard(CloogConstraint *upper,
1422 				CloogConstraint *lower, int level,
1423 				struct clast_stmt ***next, CloogInfos *infos)
1424 {
1425   int nb_par;
1426   CloogConstraintSet *set;
1427   struct clast_modulo_guard_data data = { lower, level, next, infos, 0 };
1428 
1429   cloog_int_init(data.val);
1430   cloog_constraint_coefficient_get(upper, level-1, &data.val);
1431   if (cloog_int_is_one(data.val) || cloog_int_is_neg_one(data.val)) {
1432     cloog_int_clear(data.val);
1433     return 1;
1434   }
1435 
1436   nb_par = infos->names->nb_parameters;
1437 
1438   cloog_int_init(data.bound);
1439   /* Check if would be emitting the redundant constraint mod(e,m) <= m-1 */
1440   if (cloog_constraint_is_valid(lower)) {
1441     cloog_constraint_constant_get(upper, &data.val);
1442     cloog_constraint_constant_get(lower, &data.bound);
1443     cloog_int_add(data.bound, data.val, data.bound);
1444     cloog_constraint_coefficient_get(lower, level-1, &data.val);
1445     cloog_int_sub_ui(data.val, data.val, 1);
1446     if (cloog_int_eq(data.val, data.bound)) {
1447       cloog_int_clear(data.val);
1448       cloog_int_clear(data.bound);
1449       return 1;
1450     }
1451   }
1452 
1453   if (cloog_constraint_needs_reduction(upper, level)) {
1454     set = cloog_constraint_set_for_reduction(upper, lower);
1455     set = cloog_constraint_set_reduce(set, level, infos->equal,
1456 					nb_par, &data.bound);
1457     cloog_constraint_set_foreach_constraint(set,
1458 					insert_modulo_guard_constraint, &data);
1459     cloog_constraint_set_free(set);
1460   } else
1461     insert_modulo_guard_constraint(upper, &data);
1462 
1463   cloog_int_clear(data.val);
1464   cloog_int_clear(data.bound);
1465 
1466   return !data.empty;
1467 }
1468 
1469 
1470 /**
1471  * We found an equality or a pair of inequalities identifying
1472  * a loop with a single iteration, but the user wants us to generate
1473  * a loop anyway, so we do it here.
1474  */
insert_equation_as_loop(CloogDomain * domain,CloogConstraint * upper,CloogConstraint * lower,int level,struct clast_stmt *** next,CloogInfos * infos)1475 static int insert_equation_as_loop(CloogDomain *domain, CloogConstraint *upper,
1476 		CloogConstraint *lower, int level, struct clast_stmt ***next,
1477 		CloogInfos *infos)
1478 {
1479     const char *iterator = cloog_names_name_at_level(infos->names, level);
1480     struct clast_expr *e1, *e2;
1481     struct clast_for *f;
1482 
1483     e2 = clast_bound_from_constraint(upper, level, infos->names);
1484     if (!cloog_constraint_is_valid(lower))
1485 	e1 = clast_expr_copy(e2);
1486     else
1487 	e1 = clast_bound_from_constraint(lower, level, infos->names);
1488 
1489     f = new_clast_for(domain, iterator, e1, e2, infos->stride[level-1]);
1490     **next = &f->stmt;
1491     *next = &f->body;
1492 
1493     cloog_constraint_release(lower);
1494     cloog_constraint_release(upper);
1495     return 1;
1496 }
1497 
1498 
1499 /**
1500  * insert_equation function:
1501  * This function inserts an equality
1502  * constraint according to an element in the clast.
1503  * Returns 1 if the calling function should recurse into inner loops.
1504  *
1505  * An equality can be preceded by a 'modulo guard'.
1506  * For instance, consider the constraint i -2*j = 0 and the
1507  * element j: pprint_equality should return 'if(i%2==0) { j = i/2 ;'.
1508  * - matrix is the polyhedron containing all the constraints,
1509  * - num is the line number of the constraint in matrix we want to print,
1510  * - level is the column number of the element in matrix we want to use,
1511  * - the infos structure gives the user some options about code printing,
1512  *   the number of parameters in matrix (nb_par), and the arrays of iterator
1513  *   names and parameters (iters and params).
1514  **
1515  * - November 13th 2001: first version.
1516  * - June 26th 2003: simplification of the modulo guards (remove parts such as
1517  *                   modulo is 0, compare vivien or vivien2 with a previous
1518  *                   version for an idea).
1519  * - June 29th 2003: non-unit strides support.
1520  * - July 14th 2003: (debug) no more print the constant in the modulo guard when
1521  *                   it was previously included in a stride calculation.
1522  */
insert_equation(CloogDomain * domain,CloogConstraint * upper,CloogConstraint * lower,int level,struct clast_stmt *** next,CloogInfos * infos)1523 static int insert_equation(CloogDomain *domain, CloogConstraint *upper,
1524                            CloogConstraint *lower, int level, struct clast_stmt
1525                            ***next, CloogInfos *infos)
1526 {
1527   struct clast_expr *e;
1528   struct clast_assignment *ass;
1529 
1530   if (!infos->options->otl)
1531     return insert_equation_as_loop(domain, upper, lower, level, next, infos);
1532 
1533   if (!insert_modulo_guard(upper, lower, level, next, infos)) {
1534     cloog_constraint_release(lower);
1535     cloog_constraint_release(upper);
1536 
1537     return 0;
1538   }
1539 
1540   if (cloog_constraint_is_valid(lower) ||
1541       !clast_equal_add(infos->equal, NULL, level, upper, infos))
1542   { /* Finally, the equality. */
1543 
1544     /* If we have to make a block by dimension, we start the block. Function
1545      * pprint knows if there is an equality, if this is the case, it checks
1546      * for the same following condition to close the brace.
1547      */
1548     if (infos->options->block) {
1549       struct clast_block *b = new_clast_block();
1550       **next = &b->stmt;
1551       *next = &b->body;
1552     }
1553 
1554     e = clast_bound_from_constraint(upper, level, infos->names);
1555     ass = new_clast_assignment(cloog_names_name_at_level(infos->names, level), e);
1556 
1557     **next = &ass->stmt;
1558     *next = &(**next)->next;
1559   }
1560 
1561   cloog_constraint_release(lower);
1562   cloog_constraint_release(upper);
1563 
1564   return 1;
1565 }
1566 
1567 
1568 /**
1569  * Insert a loop that is executed exactly once as an assignment.
1570  * In particular, the loop
1571  *
1572  *	for (i = e; i <= e; ++i) {
1573  *		S;
1574  *	}
1575  *
1576  * is generated as
1577  *
1578  *	i = e;
1579  *	S;
1580  *
1581  */
insert_otl_for(CloogConstraintSet * constraints,int level,struct clast_expr * e,struct clast_stmt *** next,CloogInfos * infos)1582 static void insert_otl_for(CloogConstraintSet *constraints, int level,
1583 	struct clast_expr *e, struct clast_stmt ***next, CloogInfos *infos)
1584 {
1585     const char *iterator;
1586 
1587     iterator = cloog_names_name_at_level(infos->names, level);
1588 
1589     if (!clast_equal_add(infos->equal, constraints, level,
1590 				cloog_constraint_invalid(), infos)) {
1591 	struct clast_assignment *ass;
1592 	if (infos->options->block) {
1593 	    struct clast_block *b = new_clast_block();
1594 	    **next = &b->stmt;
1595 	    *next = &b->body;
1596 	}
1597 	ass = new_clast_assignment(iterator, e);
1598 	**next = &ass->stmt;
1599 	*next = &(**next)->next;
1600     } else {
1601 	free_clast_expr(e);
1602     }
1603 }
1604 
1605 
1606 /**
1607  * Insert a loop that is executed at most once as an assignment followed
1608  * by a guard.  In particular, the loop
1609  *
1610  *	for (i = e1; i <= e2; ++i) {
1611  *		S;
1612  *	}
1613  *
1614  * is generated as
1615  *
1616  *	i = e1;
1617  *	if (i <= e2) {
1618  *		S;
1619  *	}
1620  *
1621  */
insert_guarded_otl_for(CloogConstraintSet * constraints,int level,struct clast_expr * e1,struct clast_expr * e2,struct clast_stmt *** next,CloogInfos * infos)1622 static void insert_guarded_otl_for(CloogConstraintSet *constraints, int level,
1623 	struct clast_expr *e1, struct clast_expr *e2,
1624 	struct clast_stmt ***next, CloogInfos *infos)
1625 {
1626     const char *iterator;
1627     struct clast_assignment *ass;
1628     struct clast_guard *guard;
1629 
1630     iterator = cloog_names_name_at_level(infos->names, level);
1631 
1632     if (infos->options->block) {
1633 	struct clast_block *b = new_clast_block();
1634 	**next = &b->stmt;
1635 	*next = &b->body;
1636     }
1637     ass = new_clast_assignment(iterator, e1);
1638     **next = &ass->stmt;
1639     *next = &(**next)->next;
1640 
1641     guard = new_clast_guard(1);
1642     guard->eq[0].sign = -1;
1643     guard->eq[0].LHS = &new_clast_term(infos->state->one,
1644 				       &new_clast_name(iterator)->expr)->expr;
1645     guard->eq[0].RHS = e2;
1646 
1647     **next = &guard->stmt;
1648     *next = &guard->then;
1649 }
1650 
1651 
1652 /**
1653  * insert_for function:
1654  * This function inserts a for loop in the clast.
1655  * Returns 1 if the calling function should recurse into inner loops.
1656  *
1657  * A loop header according to an element is the conjunction of a minimum and a
1658  * maximum on a given element (they give the loop bounds).
1659  * For instance, considering these constraints and the element j:
1660  * i + j -9*M >= 0
1661  *    -j +5*M >= 0
1662  *     j -4*M >= 0
1663  * this function should return 'for (j=max(-i+9*M,4*M),j<=5*M;j++) {'.
1664  * - constraints contains all constraints,
1665  * - level is the column number of the element in matrix we want to use,
1666  * - otl is set if the loop is executed at most once,
1667  * - the infos structure gives the user some options about code printing,
1668  *   the number of parameters in matrix (nb_par), and the arrays of iterator
1669  *   names and parameters (iters and params).
1670  */
insert_for(CloogDomain * domain,CloogConstraintSet * constraints,int level,int otl,struct clast_stmt *** next,CloogInfos * infos)1671 static int insert_for(CloogDomain *domain, CloogConstraintSet *constraints,
1672                       int level, int otl, struct clast_stmt ***next,
1673                       CloogInfos *infos)
1674 {
1675   const char *iterator;
1676   struct clast_expr *e1;
1677   struct clast_expr *e2;
1678 
1679   e1 = clast_minmax(constraints, level, 1, 0, 1, 0, infos);
1680   e2 = clast_minmax(constraints, level, 0, 0, 0, 0, infos);
1681 
1682   if (clast_expr_is_bigger_constant(e1, e2)) {
1683     free_clast_expr(e1);
1684     free_clast_expr(e2);
1685     return 0;
1686   }
1687 
1688   /* If min and max are not equal there is a 'for' else, there is a '='.
1689    * In the special case e1 = e2 = NULL, this is an infinite loop
1690    * so this is not a '='.
1691    */
1692   if (e1 && e2 && infos->options->otl && clast_expr_equal(e1, e2)) {
1693     free_clast_expr(e2);
1694     insert_otl_for(constraints, level, e1, next, infos);
1695   } else if (otl) {
1696     insert_guarded_otl_for(constraints, level, e1, e2, next, infos);
1697   } else {
1698     struct clast_for *f;
1699     iterator = cloog_names_name_at_level(infos->names, level);
1700 
1701     f = new_clast_for(domain, iterator, e1, e2, infos->stride[level-1]);
1702     **next = &f->stmt;
1703     *next = &f->body;
1704   }
1705 
1706   return 1;
1707 }
1708 
1709 
1710 /**
1711  * insert_block function:
1712  * This function inserts a statement block.
1713  * - block is the statement block,
1714  * - level is the number of loops enclosing the statement,
1715  * - the infos structure gives the user some options about code printing,
1716  *   the number of parameters in domain (nb_par), and the arrays of iterator
1717  *   names and parameters (iters and params).
1718  **
1719  * - September 21th 2003: first version (pick from pprint function).
1720  */
insert_block(CloogDomain * domain,CloogBlock * block,int level,struct clast_stmt *** next,CloogInfos * infos)1721 static void insert_block(CloogDomain *domain, CloogBlock *block, int level,
1722 			 struct clast_stmt ***next, CloogInfos *infos)
1723 {
1724     CloogStatement * statement ;
1725     struct clast_stmt *subs;
1726 
1727     if (!block)
1728 	return;
1729 
1730     for (statement = block->statement; statement; statement = statement->next) {
1731 	CloogStatement *s_next = statement->next;
1732 
1733 	subs = clast_equal(level,infos);
1734 
1735 	statement->next = NULL;
1736 	**next = &new_clast_user_stmt(domain, statement, subs)->stmt;
1737 	statement->next = s_next;
1738 	*next = &(**next)->next;
1739     }
1740 }
1741 
1742 
1743 /**
1744  * insert_loop function:
1745  * This function converts the content of a CloogLoop structure (loop) into a
1746  * clast_stmt (inserted at **next).
1747  * The iterator (level) of
1748  * the current loop is given by 'level': this is the column number of the
1749  * domain corresponding to the current loop iterator. The data of a loop are
1750  * written in this order:
1751  * 1. The guard of the loop, i.e. each constraint in the domain that does not
1752  *    depend on the iterator (when the entry in the column 'level' is 0).
1753  * 2. The iteration domain of the iterator, given by the constraints in the
1754  *    domain depending on the iterator, i.e.:
1755  *    * an equality if the iterator has only one value (possibly preceded by
1756  *      a guard verifying if this value is integral), *OR*
1757  *    * a loop from the minimum possible value of the iterator to the maximum
1758  *      possible value.
1759  * 3. The included statement block.
1760  * 4. The inner loops (recursive call).
1761  * 5. The following loops (recursive call).
1762  * - level is the recursion level or the iteration level that we are printing,
1763  * - the infos structure gives the user some options about code printing,
1764  *   the number of parameters in domain (nb_par), and the arrays of iterator
1765  *   names and parameters (iters and params).
1766  **
1767  * - November   2nd 2001: first version.
1768  * - March      6th 2003: infinite domain support.
1769  * - April     19th 2003: (debug) NULL loop support.
1770  * - June      29th 2003: non-unit strides support.
1771  * - April     28th 2005: (debug) level is level+equality when print statement!
1772  * - June      16th 2005: (debug) the N. Vasilache normalization step has been
1773  *                        added to avoid iteration duplication (see DaeGon Kim
1774  *                        bug in cloog_program_generate). Try vasilache.cloog
1775  *                        with and without the call to cloog_polylib_matrix_normalize,
1776  *                        using -f 8 -l 9 options for an idea.
1777  * - September 15th 2005: (debug) don't close equality braces when unnecessary.
1778  * - October   16th 2005: (debug) scalar value is saved for next loops.
1779  */
insert_loop(CloogLoop * loop,int level,struct clast_stmt *** next,CloogInfos * infos)1780 static void insert_loop(CloogLoop * loop, int level,
1781 			struct clast_stmt ***next, CloogInfos *infos)
1782 {
1783     int equality = 0;
1784     CloogConstraintSet *constraints, *temp;
1785     struct clast_stmt **top = *next;
1786     CloogConstraint *i, *j;
1787     int empty_loop = 0;
1788 
1789     /* It can happen that loop be NULL when an input polyhedron is empty. */
1790     if (loop == NULL)
1791 	return;
1792 
1793     /* The constraints do not always have a shape that allows us to generate code from it,
1794     * thus we normalize it, we also simplify it with the equalities.
1795     */
1796     temp = cloog_domain_constraints(loop->domain);
1797     cloog_constraint_set_normalize(temp,level);
1798     constraints = cloog_constraint_set_simplify(temp,infos->equal,level,
1799 				   infos->names->nb_parameters);
1800     cloog_constraint_set_free(temp);
1801     if (level) {
1802 	infos->stride[level - 1] = loop->stride;
1803 	infos->stride_level++;
1804     }
1805 
1806     /* First of all we have to print the guard. */
1807     insert_guard(constraints,level, next, infos);
1808 
1809     if (level && cloog_constraint_set_contains_level(constraints, level,
1810 					infos->names->nb_parameters)) {
1811 	/* We scan all the constraints to know in which case we are :
1812 	 * [[if] equation] or [for].
1813 	 */
1814 	if (cloog_constraint_is_valid(i =
1815 		cloog_constraint_set_defining_equality(constraints, level))) {
1816           empty_loop = !insert_equation(loop->unsimplified, i,
1817                                         cloog_constraint_invalid(), level, next,
1818                                         infos);
1819 	  equality = 1 ;
1820 	} else if (cloog_constraint_is_valid(i =
1821 		    cloog_constraint_set_defining_inequalities(constraints,
1822 			      level, &j, infos->names->nb_parameters))) {
1823             empty_loop = !insert_equation(loop->unsimplified, i, j, level, next,
1824                                           infos);
1825 	} else
1826 	    empty_loop = !insert_for(loop->unsimplified, constraints, level,
1827                                      loop->otl, next, infos);
1828     }
1829 
1830     if (!empty_loop) {
1831 	/* Finally, if there is an included statement block, print it. */
1832 	insert_block(loop->unsimplified, loop->block, level+equality, next, infos);
1833 
1834 	/* Go to the next level. */
1835 	if (loop->inner != NULL)
1836 	    insert_loop(loop->inner, level+1, next, infos);
1837     }
1838 
1839     if (level) {
1840       cloog_equal_del(infos->equal,level);
1841       infos->stride_level--;
1842     }
1843     cloog_constraint_set_free(constraints);
1844 
1845     /* Go to the next loop on the same level. */
1846     while (*top)
1847 	top = &(*top)->next;
1848     if (loop->next != NULL)
1849 	insert_loop(loop->next, level, &top,infos);
1850 }
1851 
1852 
cloog_clast_create(CloogProgram * program,CloogOptions * options)1853 struct clast_stmt *cloog_clast_create(CloogProgram *program,
1854 				      CloogOptions *options)
1855 {
1856     CloogInfos *infos = ALLOC(CloogInfos);
1857     int nb_levels;
1858     struct clast_stmt *root = &new_clast_root(program->names)->stmt;
1859     struct clast_stmt **next = &root->next;
1860 
1861     infos->state      = options->state;
1862     infos->names    = program->names;
1863     infos->options  = options;
1864     infos->scaldims = program->scaldims;
1865     infos->nb_scattdims = program->nb_scattdims;
1866 
1867     /* Allocation for the array of strides, there is a +1 since the statement can
1868     * be included inside an external loop without iteration domain.
1869     */
1870     nb_levels = program->names->nb_scattering+program->names->nb_iterators+1;
1871     infos->stride = ALLOCN(CloogStride *, nb_levels);
1872     infos->stride_level = 0;
1873 
1874     infos->equal = cloog_equal_alloc(nb_levels,
1875 			       nb_levels, program->names->nb_parameters);
1876 
1877     insert_loop(program->loop, 0, &next, infos);
1878 
1879     cloog_equal_free(infos->equal);
1880 
1881     free(infos->stride);
1882     free(infos);
1883 
1884     return root;
1885 }
1886 
1887 
cloog_clast_create_from_input(CloogInput * input,CloogOptions * options)1888 struct clast_stmt *cloog_clast_create_from_input(CloogInput *input,
1889 						 CloogOptions *options)
1890 {
1891     CloogProgram *program;
1892     struct clast_stmt *root;
1893 
1894     program = cloog_program_alloc(input->context, input->ud, options);
1895     free(input);
1896 
1897     program = cloog_program_generate(program, options);
1898 
1899     root = cloog_clast_create(program, options);
1900     cloog_program_free(program);
1901 
1902     return root;
1903 }
1904 
1905 /* Adds to the list if not already in it */
add_if_new(void ** list,int num,void * new,int size)1906 static int add_if_new(void **list, int num, void *new, int size)
1907 {
1908     int i;
1909 
1910     for (i=0; i<num; i++) {
1911         if (!memcmp((*list) + i*size, new, size)) break;
1912     }
1913 
1914     if (i==num) {
1915         *list = realloc(*list, (num+1)*size);
1916         memcpy(*list + num*size, new, size);
1917         return 1;
1918     }
1919 
1920     return 0;
1921 }
1922 
1923 
1924 /* Concatenates all elements of list2 that are not in list1;
1925  * Returns the new size of the list */
concat_if_new(void ** list1,int num1,void * list2,int num2,int size)1926 int concat_if_new(void **list1, int num1, void *list2, int num2, int size)
1927 {
1928     int i, ret;
1929 
1930     for (i=0; i<num2; i++) {
1931         ret = add_if_new(list1, num1, (char *)list2 + i*size, size);
1932         if (ret) num1++;
1933     }
1934 
1935     return num1;
1936 }
1937 
1938 /* Compares list1 to list2
1939  * Returns 0 if both have the same elements; returns -1 if all elements of
1940  * list1 are strictly contained in list2; 1 otherwise
1941  */
list_compare(const int * list1,int num1,const int * list2,int num2)1942 int list_compare(const int *list1, int num1, const int *list2, int num2)
1943 {
1944     int i, j;
1945 
1946     for (i=0; i<num1; i++) {
1947         for (j=0; j<num2; j++) {
1948             if (list1[i] == list2[j]) break;
1949         }
1950         if (j==num2) break;
1951     }
1952     if (i==num1) {
1953        if (num1 == num2) {
1954         return 0;
1955        }
1956        return -1;
1957     }
1958 
1959     return 1;
1960 }
1961 
1962 
1963 
1964 /*
1965  * A multi-purpose function to traverse and get information on Clast
1966  * loops
1967  *
1968  * node: clast node where processing should start
1969  *
1970  * Returns:
1971  * A list of loops under clast_stmt 'node' filtered in two ways: (1) it contains
1972  * statements appearing in 'stmts_filter', (2) loop iterator's name is 'iter'
1973  * If iter' is set to NULL, no filtering based on iterator name is done
1974  *
1975  * iter: loop iterator name
1976  * stmts_filter: list of statement numbers for filtering (1-indexed)
1977  * nstmts_filter: number of statements in stmts_filter
1978  *
1979  * FilterType: match exact (i.e., loops containing only and all those statements
1980  * in stmts_filter) or subset, i.e., loops which have only those statements
1981  * that appear in stmts_filter
1982  *
1983  * To disable all filtering, set 'iter' to NULL, provide all statement
1984  * numbers in 'stmts_filter' and set FilterType to subset
1985  *
1986  * Return fields
1987  *
1988  * stmts: an array of statement numbers under node
1989  * nstmts: number of stmt numbers pointed to by stmts
1990  * loops: list of clast loops
1991  * nloops: number of clast loops in loops
1992  *
1993  */
clast_filter(struct clast_stmt * node,ClastFilter filter,struct clast_for *** loops,int * nloops,int ** stmts,int * nstmts)1994 void clast_filter(struct clast_stmt *node,
1995         ClastFilter filter,
1996         struct clast_for ***loops, int *nloops,
1997         int **stmts, int *nstmts)
1998 {
1999     int num_next_stmts, num_next_loops, ret, *stmts_next;
2000     struct clast_for **loops_next;
2001 
2002     *loops = NULL;
2003     *nloops = 0;
2004     *nstmts = 0;
2005     *stmts = NULL;
2006 
2007     if (node == NULL) {
2008         return;
2009     }
2010 
2011     ClastFilterType filter_type = filter.filter_type;
2012     const char *iter = filter.iter;
2013     int nstmts_filter = filter.nstmts_filter;
2014     const int *stmts_filter = filter.stmts_filter;
2015 
2016     if (CLAST_STMT_IS_A(node, stmt_root)) {
2017         // printf("root stmt\n");
2018         struct clast_root *root = (struct clast_root *) node;
2019         clast_filter((root->stmt).next, filter, &loops_next,
2020                 &num_next_loops, &stmts_next, &num_next_stmts);
2021         *nstmts = concat_if_new((void **)stmts, *nstmts, stmts_next, num_next_stmts, sizeof(int));
2022         *nloops = concat_if_new((void **)loops, *nloops, loops_next, num_next_loops,
2023                 sizeof(struct clast_stmt *));
2024         free(loops_next);
2025         free(stmts_next);
2026     }
2027 
2028     if (CLAST_STMT_IS_A(node, stmt_guard)) {
2029         // printf("guard stmt\n");
2030         struct clast_guard *guard = (struct clast_guard *) node;
2031         clast_filter(guard->then, filter, &loops_next,
2032                 &num_next_loops, &stmts_next, &num_next_stmts);
2033         *nstmts = concat_if_new((void **)stmts, *nstmts, stmts_next, num_next_stmts, sizeof(int));
2034         *nloops = concat_if_new((void **)loops, *nloops, loops_next, num_next_loops,
2035                 sizeof(struct clast_stmt *));
2036         free(loops_next);
2037         free(stmts_next);
2038         clast_filter((guard->stmt).next, filter, &loops_next,
2039                 &num_next_loops, &stmts_next, &num_next_stmts);
2040         *nstmts = concat_if_new((void **)stmts, *nstmts, stmts_next, num_next_stmts, sizeof(int));
2041         *nloops = concat_if_new((void **)loops, *nloops, loops_next, num_next_loops,
2042                 sizeof(struct clast_stmt *));
2043         free(loops_next);
2044         free(stmts_next);
2045     }
2046 
2047     if (CLAST_STMT_IS_A(node, stmt_user)) {
2048         struct clast_user_stmt *user_stmt = (struct clast_user_stmt *) node;
2049         // printf("user stmt: S%d\n", user_stmt->statement->number);
2050         ret = add_if_new((void **)stmts, *nstmts, &user_stmt->statement->number, sizeof(int));
2051         if (ret) (*nstmts)++;
2052         clast_filter((user_stmt->stmt).next, filter, &loops_next,
2053                 &num_next_loops, &stmts_next, &num_next_stmts);
2054         *nstmts = concat_if_new((void **)stmts, *nstmts, stmts_next, num_next_stmts, sizeof(int));
2055         *nloops = concat_if_new((void **)loops, *nloops, loops_next, num_next_loops,
2056                 sizeof(struct clast_stmt *));
2057         free(loops_next);
2058         free(stmts_next);
2059     }
2060     if (CLAST_STMT_IS_A(node, stmt_for)) {
2061         struct clast_for *for_stmt = (struct clast_for *) node;
2062         clast_filter(for_stmt->body, filter, &loops_next,
2063                 &num_next_loops, &stmts_next, &num_next_stmts);
2064         *nstmts = concat_if_new((void **)stmts, *nstmts, stmts_next, num_next_stmts, sizeof(int));
2065         *nloops = concat_if_new((void **)loops, *nloops, loops_next, num_next_loops,
2066                 sizeof(struct clast_stmt *));
2067 
2068         if (iter == NULL || !strcmp(for_stmt->iterator, iter)) {
2069             if (stmts_filter == NULL ||
2070                     (filter_type == subset && list_compare(stmts_next, num_next_stmts,
2071                                                            stmts_filter, nstmts_filter) <= 0)
2072                     || (filter_type == exact && list_compare(stmts_next, num_next_stmts,
2073                             stmts_filter, nstmts_filter) == 0 )) {
2074                 ret = add_if_new((void **)loops, *nloops, &for_stmt, sizeof(struct clast_for *));
2075                 if (ret) (*nloops)++;
2076             }
2077         }
2078         free(loops_next);
2079         free(stmts_next);
2080 
2081         clast_filter((for_stmt->stmt).next, filter, &loops_next,
2082                 &num_next_loops, &stmts_next, &num_next_stmts);
2083         *nstmts = concat_if_new((void **)stmts, *nstmts, stmts_next, num_next_stmts, sizeof(int));
2084         *nloops = concat_if_new((void **)loops, *nloops, loops_next, num_next_loops,
2085                 sizeof(struct clast_stmt *));
2086         free(loops_next);
2087         free(stmts_next);
2088     }
2089 }
2090