]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/graphite-clast-to-gimple.c
2013-11-19 Richard Biener <rguenther@suse.de>
[thirdparty/gcc.git] / gcc / graphite-clast-to-gimple.c
CommitLineData
c6bb733d 1/* Translation of CLAST (CLooG AST) to Gimple.
711789cc 2 Copyright (C) 2009-2013 Free Software Foundation, Inc.
c6bb733d 3 Contributed by Sebastian Pop <sebastian.pop@amd.com>.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21#include "config.h"
87e20041 22
23#ifdef HAVE_cloog
24#include <isl/set.h>
25#include <isl/map.h>
26#include <isl/union_map.h>
27#include <isl/list.h>
28#include <isl/constraint.h>
29#include <isl/ilp.h>
30#include <isl/aff.h>
31#include <cloog/cloog.h>
32#include <cloog/isl/domain.h>
33#endif
34
c6bb733d 35#include "system.h"
36#include "coretypes.h"
52f91c04 37#include "diagnostic-core.h"
41a8aa41 38#include "tree.h"
e795d6e1 39#include "gimple.h"
dcf1a1ec 40#include "gimple-iterator.h"
e795d6e1 41#include "gimplify-me.h"
073c1fd5 42#include "gimple-ssa.h"
05d9c18a 43#include "tree-ssa-loop-manip.h"
073c1fd5 44#include "tree-ssa-loop.h"
45#include "tree-into-ssa.h"
f0a18dd2 46#include "tree-pass.h"
c6bb733d 47#include "cfgloop.h"
48#include "tree-chrec.h"
49#include "tree-data-ref.h"
50#include "tree-scalar-evolution.h"
c6bb733d 51#include "sese.h"
52
53#ifdef HAVE_cloog
54#include "cloog/cloog.h"
c6bb733d 55#include "graphite-poly.h"
c6bb733d 56#include "graphite-clast-to-gimple.h"
d9dd21a8 57#include "graphite-htab.h"
32819af5 58
59typedef const struct clast_expr *clast_name_p;
c6bb733d 60
e828ad34 61#ifndef CLOOG_LANGUAGE_C
62#define CLOOG_LANGUAGE_C LANGUAGE_C
63#endif
64
87e20041 65
66/* Converts a GMP constant VAL to a tree and returns it. */
67
68static tree
69gmp_cst_to_tree (tree type, mpz_t val)
70{
71 tree t = type ? type : integer_type_node;
72 mpz_t tmp;
73 double_int di;
74
75 mpz_init (tmp);
76 mpz_set (tmp, val);
77 di = mpz_get_double_int (t, tmp, true);
78 mpz_clear (tmp);
79
80 return double_int_to_tree (t, di);
81}
82
83/* Sets RES to the min of V1 and V2. */
84
85static void
86value_min (mpz_t res, mpz_t v1, mpz_t v2)
87{
88 if (mpz_cmp (v1, v2) < 0)
89 mpz_set (res, v1);
90 else
91 mpz_set (res, v2);
92}
93
94/* Sets RES to the max of V1 and V2. */
95
96static void
97value_max (mpz_t res, mpz_t v1, mpz_t v2)
98{
99 if (mpz_cmp (v1, v2) < 0)
100 mpz_set (res, v2);
101 else
102 mpz_set (res, v1);
103}
104
105
2487de19 106/* This flag is set when an error occurred during the translation of
107 CLAST to Gimple. */
108static bool gloog_error;
109
c6bb733d 110/* Verifies properties that GRAPHITE should maintain during translation. */
111
112static inline void
113graphite_verify (void)
114{
115#ifdef ENABLE_CHECKING
116 verify_loop_structure ();
ca77c6ec 117 verify_loop_closed_ssa (true);
c6bb733d 118#endif
119}
120
c5f2229b 121/* Stores the INDEX in a vector and the loop nesting LEVEL for a given
24a2ecdb 122 clast NAME. BOUND_ONE and BOUND_TWO represent the exact lower and
123 upper bounds that can be inferred from the polyhedral representation. */
c9ef6b0e 124
125typedef struct clast_name_index {
126 int index;
c5f2229b 127 int level;
24a2ecdb 128 mpz_t bound_one, bound_two;
c9ef6b0e 129 const char *name;
32819af5 130 /* If free_name is set, the content of name was allocated by us and needs
131 to be freed. */
132 char *free_name;
c9ef6b0e 133} *clast_name_index_p;
134
d9dd21a8 135/* Helper for hashing clast_name_index. */
136
137struct clast_index_hasher
138{
139 typedef clast_name_index value_type;
140 typedef clast_name_index compare_type;
141 static inline hashval_t hash (const value_type *);
142 static inline bool equal (const value_type *, const compare_type *);
143 static inline void remove (value_type *);
144};
145
146/* Computes a hash function for database element E. */
147
148inline hashval_t
149clast_index_hasher::hash (const value_type *e)
150{
151 hashval_t hash = 0;
152
153 int length = strlen (e->name);
154 int i;
155
156 for (i = 0; i < length; ++i)
157 hash = hash | (e->name[i] << (i % 4));
158
159 return hash;
160}
161
162/* Compares database elements ELT1 and ELT2. */
163
164inline bool
165clast_index_hasher::equal (const value_type *elt1, const compare_type *elt2)
166{
167 return strcmp (elt1->name, elt2->name) == 0;
168}
169
170/* Free the memory taken by a clast_name_index struct. */
171
172inline void
173clast_index_hasher::remove (value_type *c)
174{
175 if (c->free_name)
176 free (c->free_name);
177 mpz_clear (c->bound_one);
178 mpz_clear (c->bound_two);
179 free (c);
180}
181
182typedef hash_table <clast_index_hasher> clast_index_htab_type;
183
c9ef6b0e 184/* Returns a pointer to a new element of type clast_name_index_p built
24a2ecdb 185 from NAME, INDEX, LEVEL, BOUND_ONE, and BOUND_TWO. */
c9ef6b0e 186
187static inline clast_name_index_p
7cfe5b1f 188new_clast_name_index (const char *name, int index, int level,
24a2ecdb 189 mpz_t bound_one, mpz_t bound_two)
c9ef6b0e 190{
191 clast_name_index_p res = XNEW (struct clast_name_index);
32819af5 192 char *new_name = XNEWVEC (char, strlen (name) + 1);
193 strcpy (new_name, name);
c9ef6b0e 194
32819af5 195 res->name = new_name;
196 res->free_name = new_name;
c5f2229b 197 res->level = level;
c9ef6b0e 198 res->index = index;
24a2ecdb 199 mpz_init (res->bound_one);
200 mpz_init (res->bound_two);
201 mpz_set (res->bound_one, bound_one);
202 mpz_set (res->bound_two, bound_two);
c9ef6b0e 203 return res;
204}
205
c5f2229b 206/* For a given clast NAME, returns -1 if NAME is not in the
207 INDEX_TABLE, otherwise returns the loop level for the induction
208 variable NAME, or if it is a parameter, the parameter number in the
209 vector of parameters. */
210
211static inline int
d9dd21a8 212clast_name_to_level (clast_name_p name, clast_index_htab_type index_table)
c5f2229b 213{
214 struct clast_name_index tmp;
d9dd21a8 215 clast_name_index **slot;
c5f2229b 216
c5f2229b 217 gcc_assert (name->type == clast_expr_name);
218 tmp.name = ((const struct clast_name *) name)->name;
32819af5 219 tmp.free_name = NULL;
c5f2229b 220
d9dd21a8 221 slot = index_table.find_slot (&tmp, NO_INSERT);
c5f2229b 222
223 if (slot && *slot)
224 return ((struct clast_name_index *) *slot)->level;
225
226 return -1;
227}
228
c9ef6b0e 229/* For a given clast NAME, returns -1 if it does not correspond to any
230 parameter, or otherwise, returns the index in the PARAMS or
231 SCATTERING_DIMENSIONS vector. */
232
233static inline int
d9dd21a8 234clast_name_to_index (struct clast_name *name, clast_index_htab_type index_table)
c9ef6b0e 235{
236 struct clast_name_index tmp;
d9dd21a8 237 clast_name_index **slot;
c9ef6b0e 238
451d3b40 239 tmp.name = ((const struct clast_name *) name)->name;
32819af5 240 tmp.free_name = NULL;
2e6bc1c7 241
d9dd21a8 242 slot = index_table.find_slot (&tmp, NO_INSERT);
c9ef6b0e 243
244 if (slot && *slot)
d9dd21a8 245 return (*slot)->index;
c9ef6b0e 246
247 return -1;
248}
249
24a2ecdb 250/* For a given clast NAME, initializes the lower and upper bounds BOUND_ONE
251 and BOUND_TWO stored in the INDEX_TABLE. Returns true when NAME has been
7cfe5b1f 252 found in the INDEX_TABLE, false otherwise. */
253
254static inline bool
d9dd21a8 255clast_name_to_lb_ub (struct clast_name *name, clast_index_htab_type index_table,
32819af5 256 mpz_t bound_one, mpz_t bound_two)
7cfe5b1f 257{
258 struct clast_name_index tmp;
d9dd21a8 259 clast_name_index **slot;
7cfe5b1f 260
32819af5 261 tmp.name = name->name;
262 tmp.free_name = NULL;
7cfe5b1f 263
d9dd21a8 264 slot = index_table.find_slot (&tmp, NO_INSERT);
7cfe5b1f 265
266 if (slot && *slot)
267 {
24a2ecdb 268 mpz_set (bound_one, ((struct clast_name_index *) *slot)->bound_one);
269 mpz_set (bound_two, ((struct clast_name_index *) *slot)->bound_two);
7cfe5b1f 270 return true;
271 }
272
273 return false;
274}
275
c5f2229b 276/* Records in INDEX_TABLE the INDEX and LEVEL for NAME. */
c9ef6b0e 277
278static inline void
d9dd21a8 279save_clast_name_index (clast_index_htab_type index_table, const char *name,
24a2ecdb 280 int index, int level, mpz_t bound_one, mpz_t bound_two)
c9ef6b0e 281{
282 struct clast_name_index tmp;
d9dd21a8 283 clast_name_index **slot;
c9ef6b0e 284
285 tmp.name = name;
32819af5 286 tmp.free_name = NULL;
d9dd21a8 287 slot = index_table.find_slot (&tmp, INSERT);
c9ef6b0e 288
289 if (slot)
cfd3faac 290 {
dd045aee 291 free (*slot);
cfd3faac 292
24a2ecdb 293 *slot = new_clast_name_index (name, index, level, bound_one, bound_two);
cfd3faac 294 }
c9ef6b0e 295}
c6bb733d 296\f
297
17e7716e 298/* NEWIVS_INDEX binds CLooG's scattering name to the index of the tree
299 induction variable in NEWIVS.
300
301 PARAMS_INDEX binds CLooG's parameter name to the index of the tree
302 parameter in PARAMS. */
303
304typedef struct ivs_params {
f1f41a6c 305 vec<tree> params, *newivs;
d9dd21a8 306 clast_index_htab_type newivs_index, params_index;
17e7716e 307 sese region;
308} *ivs_params_p;
309
c6bb733d 310/* Returns the tree variable from the name NAME that was given in
311 Cloog representation. */
312
313static tree
32819af5 314clast_name_to_gcc (struct clast_name *name, ivs_params_p ip)
c6bb733d 315{
316 int index;
c6bb733d 317
d9dd21a8 318 if (ip->params.exists () && ip->params_index.is_created ())
c6bb733d 319 {
17e7716e 320 index = clast_name_to_index (name, ip->params_index);
c6bb733d 321
322 if (index >= 0)
f1f41a6c 323 return ip->params[index];
c6bb733d 324 }
325
d9dd21a8 326 gcc_assert (ip->newivs && ip->newivs_index.is_created ());
17e7716e 327 index = clast_name_to_index (name, ip->newivs_index);
c6bb733d 328 gcc_assert (index >= 0);
329
f1f41a6c 330 return (*ip->newivs)[index];
c6bb733d 331}
332
28013ca9 333/* Returns the maximal precision type for expressions TYPE1 and TYPE2. */
c6bb733d 334
f20b6ea9 335static tree
28013ca9 336max_precision_type (tree type1, tree type2)
f20b6ea9 337{
e84af3c1 338 enum machine_mode mode;
28013ca9 339 int p1, p2, precision;
340 tree type;
341
342 if (POINTER_TYPE_P (type1))
343 return type1;
344
345 if (POINTER_TYPE_P (type2))
346 return type2;
347
348 if (TYPE_UNSIGNED (type1)
349 && TYPE_UNSIGNED (type2))
350 return TYPE_PRECISION (type1) > TYPE_PRECISION (type2) ? type1 : type2;
351
352 p1 = TYPE_PRECISION (type1);
353 p2 = TYPE_PRECISION (type2);
7c0d15dc 354
355 if (p1 > p2)
356 precision = TYPE_UNSIGNED (type1) ? p1 * 2 : p1;
357 else
358 precision = TYPE_UNSIGNED (type2) ? p2 * 2 : p2;
359
e84af3c1 360 if (precision > BITS_PER_WORD)
361 {
362 gloog_error = true;
363 return integer_type_node;
364 }
365
366 mode = smallest_mode_for_size (precision, MODE_INT);
367 precision = GET_MODE_PRECISION (mode);
368 type = build_nonstandard_integer_type (precision, false);
f20b6ea9 369
370 if (!type)
371 {
372 gloog_error = true;
373 return integer_type_node;
374 }
e84af3c1 375
f20b6ea9 376 return type;
377}
378
c6bb733d 379static tree
17e7716e 380clast_to_gcc_expression (tree, struct clast_expr *, ivs_params_p);
c6bb733d 381
382/* Converts a Cloog reduction expression R with reduction operation OP
383 to a GCC expression tree of type TYPE. */
384
385static tree
386clast_to_gcc_expression_red (tree type, enum tree_code op,
17e7716e 387 struct clast_reduction *r, ivs_params_p ip)
c6bb733d 388{
389 int i;
17e7716e 390 tree res = clast_to_gcc_expression (type, r->elts[0], ip);
c6bb733d 391 tree operand_type = (op == POINTER_PLUS_EXPR) ? sizetype : type;
392
393 for (i = 1; i < r->n; i++)
394 {
17e7716e 395 tree t = clast_to_gcc_expression (operand_type, r->elts[i], ip);
c6bb733d 396 res = fold_build2 (op, type, res, t);
397 }
398
399 return res;
400}
401
402/* Converts a Cloog AST expression E back to a GCC expression tree of
403 type TYPE. */
404
405static tree
17e7716e 406clast_to_gcc_expression (tree type, struct clast_expr *e, ivs_params_p ip)
c6bb733d 407{
408 switch (e->type)
409 {
32819af5 410 case clast_expr_name:
411 {
412 return clast_name_to_gcc ((struct clast_name *) e, ip);
413 }
2e6bc1c7 414 case clast_expr_term:
c6bb733d 415 {
416 struct clast_term *t = (struct clast_term *) e;
417
418 if (t->var)
419 {
2d6fe479 420 if (mpz_cmp_si (t->val, 1) == 0)
c6bb733d 421 {
32819af5 422 tree name = clast_to_gcc_expression (type, t->var, ip);
b43389bd 423
424 if (POINTER_TYPE_P (TREE_TYPE (name)) != POINTER_TYPE_P (type))
a0553bff 425 name = convert_to_ptrofftype (name);
b43389bd 426
427 name = fold_convert (type, name);
428 return name;
c6bb733d 429 }
430
2d6fe479 431 else if (mpz_cmp_si (t->val, -1) == 0)
c6bb733d 432 {
32819af5 433 tree name = clast_to_gcc_expression (type, t->var, ip);
b43389bd 434
435 if (POINTER_TYPE_P (TREE_TYPE (name)) != POINTER_TYPE_P (type))
a0553bff 436 name = convert_to_ptrofftype (name);
b43389bd 437
c6bb733d 438 name = fold_convert (type, name);
b43389bd 439
c6bb733d 440 return fold_build1 (NEGATE_EXPR, type, name);
441 }
442 else
443 {
32819af5 444 tree name = clast_to_gcc_expression (type, t->var, ip);
c6bb733d 445 tree cst = gmp_cst_to_tree (type, t->val);
b43389bd 446
447 if (POINTER_TYPE_P (TREE_TYPE (name)) != POINTER_TYPE_P (type))
a0553bff 448 name = convert_to_ptrofftype (name);
b43389bd 449
c6bb733d 450 name = fold_convert (type, name);
b43389bd 451
2487de19 452 if (!POINTER_TYPE_P (type))
453 return fold_build2 (MULT_EXPR, type, cst, name);
454
455 gloog_error = true;
456 return cst;
c6bb733d 457 }
458 }
459 else
460 return gmp_cst_to_tree (type, t->val);
461 }
462
2e6bc1c7 463 case clast_expr_red:
c6bb733d 464 {
465 struct clast_reduction *r = (struct clast_reduction *) e;
466
467 switch (r->type)
468 {
469 case clast_red_sum:
470 return clast_to_gcc_expression_red
471 (type, POINTER_TYPE_P (type) ? POINTER_PLUS_EXPR : PLUS_EXPR,
17e7716e 472 r, ip);
c6bb733d 473
474 case clast_red_min:
17e7716e 475 return clast_to_gcc_expression_red (type, MIN_EXPR, r, ip);
c6bb733d 476
477 case clast_red_max:
17e7716e 478 return clast_to_gcc_expression_red (type, MAX_EXPR, r, ip);
c6bb733d 479
480 default:
481 gcc_unreachable ();
482 }
483 break;
484 }
485
2e6bc1c7 486 case clast_expr_bin:
c6bb733d 487 {
488 struct clast_binary *b = (struct clast_binary *) e;
489 struct clast_expr *lhs = (struct clast_expr *) b->LHS;
17e7716e 490 tree tl = clast_to_gcc_expression (type, lhs, ip);
c6bb733d 491 tree tr = gmp_cst_to_tree (type, b->RHS);
492
493 switch (b->type)
494 {
495 case clast_bin_fdiv:
496 return fold_build2 (FLOOR_DIV_EXPR, type, tl, tr);
497
498 case clast_bin_cdiv:
499 return fold_build2 (CEIL_DIV_EXPR, type, tl, tr);
500
501 case clast_bin_div:
502 return fold_build2 (EXACT_DIV_EXPR, type, tl, tr);
503
504 case clast_bin_mod:
505 return fold_build2 (TRUNC_MOD_EXPR, type, tl, tr);
506
507 default:
508 gcc_unreachable ();
509 }
510 }
511
512 default:
513 gcc_unreachable ();
514 }
515
516 return NULL_TREE;
517}
518
24a2ecdb 519/* Return a type that could represent the values between BOUND_ONE and
520 BOUND_TWO. */
f20b6ea9 521
522static tree
24a2ecdb 523type_for_interval (mpz_t bound_one, mpz_t bound_two)
f20b6ea9 524{
75663c96 525 bool unsigned_p;
f20b6ea9 526 tree type;
d23456ee 527 enum machine_mode mode;
e45543a0 528 int wider_precision;
24a2ecdb 529 int precision = MAX (mpz_sizeinbase (bound_one, 2),
530 mpz_sizeinbase (bound_two, 2));
f20b6ea9 531
d23456ee 532 if (precision > BITS_PER_WORD)
533 {
534 gloog_error = true;
535 return integer_type_node;
536 }
537
24a2ecdb 538 if (mpz_cmp (bound_one, bound_two) <= 0)
539 unsigned_p = (mpz_sgn (bound_one) >= 0);
75663c96 540 else
24a2ecdb 541 unsigned_p = (mpz_sgn (bound_two) >= 0);
be90fd3f 542
d23456ee 543 mode = smallest_mode_for_size (precision, MODE_INT);
e45543a0 544 wider_precision = GET_MODE_PRECISION (mode);
545
546 /* As we want to generate signed types as much as possible, try to
24a2ecdb 547 fit the interval [bound_one, bound_two] in a signed type. For example,
e45543a0 548 supposing that we have the interval [0, 100], instead of
549 generating unsigned char, we want to generate a signed char. */
550 if (unsigned_p && precision < wider_precision)
551 unsigned_p = false;
552
553 type = build_nonstandard_integer_type (wider_precision, unsigned_p);
d23456ee 554
f20b6ea9 555 if (!type)
556 {
557 gloog_error = true;
558 return integer_type_node;
559 }
560
561 return type;
562}
563
564/* Return a type that could represent the integer value VAL, or
565 otherwise return NULL_TREE. */
566
567static tree
954e0498 568type_for_value (mpz_t val)
f20b6ea9 569{
954e0498 570 return type_for_interval (val, val);
f20b6ea9 571}
572
32819af5 573static tree
574type_for_clast_expr (struct clast_expr *, ivs_params_p, mpz_t, mpz_t);
575
24a2ecdb 576/* Return the type for the clast_term T. Initializes BOUND_ONE and
577 BOUND_TWO to the bounds of the term. */
f20b6ea9 578
579static tree
24a2ecdb 580type_for_clast_term (struct clast_term *t, ivs_params_p ip, mpz_t bound_one,
581 mpz_t bound_two)
f20b6ea9 582{
32819af5 583 tree type;
2e6bc1c7 584 gcc_assert (t->expr.type == clast_expr_term);
f20b6ea9 585
32819af5 586 if (!t->var)
4c48fb0e 587 {
24a2ecdb 588 mpz_set (bound_one, t->val);
589 mpz_set (bound_two, t->val);
4c48fb0e 590 return type_for_value (t->val);
591 }
592
32819af5 593 type = type_for_clast_expr (t->var, ip, bound_one, bound_two);
4c48fb0e 594
24a2ecdb 595 mpz_mul (bound_one, bound_one, t->val);
596 mpz_mul (bound_two, bound_two, t->val);
4c48fb0e 597
32819af5 598 return max_precision_type (type, type_for_interval (bound_one, bound_two));
f20b6ea9 599}
600
24a2ecdb 601/* Return the type for the clast_reduction R. Initializes BOUND_ONE
602 and BOUND_TWO to the bounds of the reduction expression. */
f20b6ea9 603
604static tree
4c48fb0e 605type_for_clast_red (struct clast_reduction *r, ivs_params_p ip,
24a2ecdb 606 mpz_t bound_one, mpz_t bound_two)
f20b6ea9 607{
608 int i;
24a2ecdb 609 tree type = type_for_clast_expr (r->elts[0], ip, bound_one, bound_two);
4c48fb0e 610 mpz_t b1, b2, m1, m2;
f20b6ea9 611
612 if (r->n == 1)
4c48fb0e 613 return type;
f20b6ea9 614
4c48fb0e 615 mpz_init (b1);
616 mpz_init (b2);
617 mpz_init (m1);
618 mpz_init (m2);
f20b6ea9 619
4c48fb0e 620 for (i = 1; i < r->n; i++)
621 {
622 tree t = type_for_clast_expr (r->elts[i], ip, b1, b2);
623 type = max_precision_type (type, t);
624
625 switch (r->type)
626 {
627 case clast_red_sum:
24a2ecdb 628 value_min (m1, bound_one, bound_two);
4c48fb0e 629 value_min (m2, b1, b2);
24a2ecdb 630 mpz_add (bound_one, m1, m2);
4c48fb0e 631
24a2ecdb 632 value_max (m1, bound_one, bound_two);
4c48fb0e 633 value_max (m2, b1, b2);
24a2ecdb 634 mpz_add (bound_two, m1, m2);
4c48fb0e 635 break;
636
637 case clast_red_min:
24a2ecdb 638 value_min (bound_one, bound_one, bound_two);
639 value_min (bound_two, b1, b2);
4c48fb0e 640 break;
641
642 case clast_red_max:
24a2ecdb 643 value_max (bound_one, bound_one, bound_two);
644 value_max (bound_two, b1, b2);
4c48fb0e 645 break;
646
647 default:
648 gcc_unreachable ();
649 break;
650 }
f20b6ea9 651 }
652
4c48fb0e 653 mpz_clear (b1);
654 mpz_clear (b2);
655 mpz_clear (m1);
656 mpz_clear (m2);
657
658 /* Return a type that can represent the result of the reduction. */
24a2ecdb 659 return max_precision_type (type, type_for_interval (bound_one, bound_two));
f20b6ea9 660}
661
662/* Return the type for the clast_binary B used in STMT. */
663
664static tree
24a2ecdb 665type_for_clast_bin (struct clast_binary *b, ivs_params_p ip, mpz_t bound_one,
666 mpz_t bound_two)
f20b6ea9 667{
4c48fb0e 668 mpz_t one;
24a2ecdb 669 tree l = type_for_clast_expr ((struct clast_expr *) b->LHS, ip,
670 bound_one, bound_two);
954e0498 671 tree r = type_for_value (b->RHS);
4c48fb0e 672 tree type = max_precision_type (l, r);
673
674 switch (b->type)
675 {
676 case clast_bin_fdiv:
24a2ecdb 677 mpz_mdiv (bound_one, bound_one, b->RHS);
678 mpz_mdiv (bound_two, bound_two, b->RHS);
4c48fb0e 679 break;
680
681 case clast_bin_cdiv:
24a2ecdb 682 mpz_mdiv (bound_one, bound_one, b->RHS);
683 mpz_mdiv (bound_two, bound_two, b->RHS);
4c48fb0e 684 mpz_init (one);
24a2ecdb 685 mpz_add (bound_one, bound_one, one);
686 mpz_add (bound_two, bound_two, one);
4c48fb0e 687 mpz_clear (one);
688 break;
689
690 case clast_bin_div:
24a2ecdb 691 mpz_div (bound_one, bound_one, b->RHS);
692 mpz_div (bound_two, bound_two, b->RHS);
4c48fb0e 693 break;
694
695 case clast_bin_mod:
24a2ecdb 696 mpz_mod (bound_one, bound_one, b->RHS);
697 mpz_mod (bound_two, bound_two, b->RHS);
4c48fb0e 698 break;
699
700 default:
701 gcc_unreachable ();
702 }
703
704 /* Return a type that can represent the result of the reduction. */
24a2ecdb 705 return max_precision_type (type, type_for_interval (bound_one, bound_two));
f20b6ea9 706}
707
32819af5 708/* Return the type for the clast_name NAME. Initializes BOUND_ONE and
709 BOUND_TWO to the bounds of the term. */
710
711static tree
712type_for_clast_name (struct clast_name *name, ivs_params_p ip, mpz_t bound_one,
713 mpz_t bound_two)
714{
715 bool found = false;
716
d9dd21a8 717 if (ip->params.exists () && ip->params_index.is_created ())
32819af5 718 found = clast_name_to_lb_ub (name, ip->params_index, bound_one, bound_two);
719
720 if (!found)
721 {
d9dd21a8 722 gcc_assert (ip->newivs && ip->newivs_index.is_created ());
32819af5 723 found = clast_name_to_lb_ub (name, ip->newivs_index, bound_one,
724 bound_two);
725 gcc_assert (found);
726 }
727
728 return TREE_TYPE (clast_name_to_gcc (name, ip));
729}
730
f20b6ea9 731/* Returns the type for the CLAST expression E when used in statement
732 STMT. */
c6bb733d 733
734static tree
24a2ecdb 735type_for_clast_expr (struct clast_expr *e, ivs_params_p ip, mpz_t bound_one,
736 mpz_t bound_two)
c6bb733d 737{
738 switch (e->type)
739 {
2e6bc1c7 740 case clast_expr_term:
24a2ecdb 741 return type_for_clast_term ((struct clast_term *) e, ip,
742 bound_one, bound_two);
c6bb733d 743
2e6bc1c7 744 case clast_expr_red:
24a2ecdb 745 return type_for_clast_red ((struct clast_reduction *) e, ip,
746 bound_one, bound_two);
c6bb733d 747
2e6bc1c7 748 case clast_expr_bin:
24a2ecdb 749 return type_for_clast_bin ((struct clast_binary *) e, ip,
750 bound_one, bound_two);
c6bb733d 751
32819af5 752 case clast_expr_name:
753 return type_for_clast_name ((struct clast_name *) e, ip,
754 bound_one, bound_two);
755
c6bb733d 756 default:
757 gcc_unreachable ();
758 }
759
760 return NULL_TREE;
761}
762
87e20041 763/* Returns true if the clast expression E is a constant with VALUE. */
c6bb733d 764
87e20041 765static bool
766clast_expr_const_value_p (struct clast_expr *e, int value)
c6bb733d 767{
87e20041 768 struct clast_term *t;
769 if (e->type != clast_expr_term)
770 return false;
771 t = (struct clast_term *)e;
772 if (t->var)
773 return false;
774 return 0 == mpz_cmp_si (t->val, value);
c6bb733d 775}
776
777/* Translates a clast equation CLEQ to a tree. */
778
779static tree
17e7716e 780graphite_translate_clast_equation (struct clast_equation *cleq,
781 ivs_params_p ip)
c6bb733d 782{
783 enum tree_code comp;
87e20041 784 tree type, lhs, rhs, ltype, rtype;
785 mpz_t bound_one, bound_two;
786 struct clast_expr *clhs, *crhs;
c6bb733d 787
87e20041 788 clhs = cleq->LHS;
789 crhs = cleq->RHS;
c6bb733d 790 if (cleq->sign == 0)
791 comp = EQ_EXPR;
c6bb733d 792 else if (cleq->sign > 0)
793 comp = GE_EXPR;
c6bb733d 794 else
795 comp = LE_EXPR;
796
87e20041 797 /* Special cases to reduce range of arguments to hopefully
798 don't need types with larger precision than the input. */
799 if (crhs->type == clast_expr_red
800 && comp != EQ_EXPR)
801 {
802 struct clast_reduction *r = (struct clast_reduction *) crhs;
803 /* X >= A+1 --> X > A and
804 X <= A-1 --> X < A */
805 if (r->n == 2
806 && r->type == clast_red_sum
807 && clast_expr_const_value_p (r->elts[1], comp == GE_EXPR ? 1 : -1))
808 {
809 crhs = r->elts[0];
810 comp = comp == GE_EXPR ? GT_EXPR : LT_EXPR;
811 }
812 }
813
814 mpz_init (bound_one);
815 mpz_init (bound_two);
816
817 ltype = type_for_clast_expr (clhs, ip, bound_one, bound_two);
818 rtype = type_for_clast_expr (crhs, ip, bound_one, bound_two);
819
820 mpz_clear (bound_one);
821 mpz_clear (bound_two);
822 type = max_precision_type (ltype, rtype);
823
824 lhs = clast_to_gcc_expression (type, clhs, ip);
825 rhs = clast_to_gcc_expression (type, crhs, ip);
826
c6bb733d 827 return fold_build2 (comp, boolean_type_node, lhs, rhs);
828}
829
830/* Creates the test for the condition in STMT. */
831
832static tree
17e7716e 833graphite_create_guard_cond_expr (struct clast_guard *stmt,
834 ivs_params_p ip)
c6bb733d 835{
836 tree cond = NULL;
837 int i;
838
839 for (i = 0; i < stmt->n; i++)
840 {
17e7716e 841 tree eq = graphite_translate_clast_equation (&stmt->eq[i], ip);
c6bb733d 842
843 if (cond)
844 cond = fold_build2 (TRUTH_AND_EXPR, TREE_TYPE (eq), cond, eq);
845 else
846 cond = eq;
847 }
848
849 return cond;
850}
851
852/* Creates a new if region corresponding to Cloog's guard. */
853
854static edge
17e7716e 855graphite_create_new_guard (edge entry_edge, struct clast_guard *stmt,
856 ivs_params_p ip)
c6bb733d 857{
17e7716e 858 tree cond_expr = graphite_create_guard_cond_expr (stmt, ip);
c6bb733d 859 edge exit_edge = create_empty_if_region_on_edge (entry_edge, cond_expr);
860 return exit_edge;
861}
862
7cfe5b1f 863/* Compute the lower bound LOW and upper bound UP for the parameter
864 PARAM in scop SCOP based on the constraints in the context. */
865
866static void
867compute_bounds_for_param (scop_p scop, int param, mpz_t low, mpz_t up)
868{
87e20041 869 isl_int v;
870 isl_aff *aff = isl_aff_zero_on_domain
871 (isl_local_space_from_space (isl_set_get_space (scop->context)));
872
873 aff = isl_aff_add_coefficient_si (aff, isl_dim_param, param, 1);
874
875 isl_int_init (v);
876 isl_set_min (scop->context, aff, &v);
877 isl_int_get_gmp (v, low);
878 isl_set_max (scop->context, aff, &v);
879 isl_int_get_gmp (v, up);
880 isl_int_clear (v);
881 isl_aff_free (aff);
7cfe5b1f 882}
883
f20b6ea9 884/* Compute the lower bound LOW and upper bound UP for the induction
87e20041 885 variable of loop LOOP.
c6bb733d 886
87e20041 887 FIXME: This one is not entirely correct, as min/max expressions in the
888 calculation can yield to incorrect results. To be completely
889 correct, we need to evaluate each subexpression generated by
890 CLooG. CLooG does not yet support this, so this is as good as
891 it can be. */
bf662ce7 892
87e20041 893static void
894compute_bounds_for_loop (struct clast_for *loop, mpz_t low, mpz_t up)
f20b6ea9 895{
87e20041 896 isl_set *domain;
897 isl_aff *dimension;
898 isl_local_space *local_space;
899 isl_int isl_value;
900 enum isl_lp_result lp_result;
901
902 domain = isl_set_copy (isl_set_from_cloog_domain (loop->domain));
903 local_space = isl_local_space_from_space (isl_set_get_space (domain));
904 dimension = isl_aff_zero_on_domain (local_space);
905 dimension = isl_aff_add_coefficient_si (dimension, isl_dim_in,
906 isl_set_dim (domain, isl_dim_set) - 1,
907 1);
908
909 isl_int_init (isl_value);
910
911 lp_result = isl_set_min (domain, dimension, &isl_value);
912 assert (lp_result == isl_lp_ok);
913 isl_int_get_gmp (isl_value, low);
914
915 lp_result = isl_set_max (domain, dimension, &isl_value);
916 assert (lp_result == isl_lp_ok);
917 isl_int_get_gmp (isl_value, up);
918
919 isl_int_clear (isl_value);
920 isl_set_free (domain);
921 isl_aff_free (dimension);
c6bb733d 922}
923
f20b6ea9 924/* Returns the type for the induction variable for the loop translated
925 from STMT_FOR. */
c6bb733d 926
927static tree
7cfe5b1f 928type_for_clast_for (struct clast_for *stmt_for, ivs_params_p ip)
c6bb733d 929{
24a2ecdb 930 mpz_t bound_one, bound_two;
4c48fb0e 931 tree lb_type, ub_type;
932
24a2ecdb 933 mpz_init (bound_one);
934 mpz_init (bound_two);
4c48fb0e 935
24a2ecdb 936 lb_type = type_for_clast_expr (stmt_for->LB, ip, bound_one, bound_two);
937 ub_type = type_for_clast_expr (stmt_for->UB, ip, bound_one, bound_two);
4c48fb0e 938
24a2ecdb 939 mpz_clear (bound_one);
940 mpz_clear (bound_two);
c6bb733d 941
7cfe5b1f 942 return max_precision_type (lb_type, ub_type);
c6bb733d 943}
944
945/* Creates a new LOOP corresponding to Cloog's STMT. Inserts an
946 induction variable for the new LOOP. New LOOP is attached to CFG
947 starting at ENTRY_EDGE. LOOP is inserted into the loop tree and
948 becomes the child loop of the OUTER_LOOP. NEWIVS_INDEX binds
949 CLooG's scattering name to the induction variable created for the
950 loop of STMT. The new induction variable is inserted in the NEWIVS
35048891 951 vector and is of type TYPE. */
c6bb733d 952
953static struct loop *
17e7716e 954graphite_create_new_loop (edge entry_edge, struct clast_for *stmt,
955 loop_p outer, tree type, tree lb, tree ub,
956 int level, ivs_params_p ip)
c6bb733d 957{
7cfe5b1f 958 mpz_t low, up;
959
c6bb733d 960 tree stride = gmp_cst_to_tree (type, stmt->stride);
961 tree ivvar = create_tmp_var (type, "graphite_IV");
962 tree iv, iv_after_increment;
963 loop_p loop = create_empty_loop_on_edge
964 (entry_edge, lb, stride, ub, ivvar, &iv, &iv_after_increment,
965 outer ? outer : entry_edge->src->loop_father);
966
7cfe5b1f 967 mpz_init (low);
968 mpz_init (up);
87e20041 969 compute_bounds_for_loop (stmt, low, up);
17e7716e 970 save_clast_name_index (ip->newivs_index, stmt->iterator,
f1f41a6c 971 (*ip->newivs).length (), level, low, up);
7cfe5b1f 972 mpz_clear (low);
973 mpz_clear (up);
f1f41a6c 974 (*ip->newivs).safe_push (iv);
c6bb733d 975 return loop;
976}
977
4ed27c8e 978/* Inserts in iv_map a tuple (OLD_LOOP->num, NEW_NAME) for the
979 induction variables of the loops around GBB in SESE. */
c6bb733d 980
981static void
f1f41a6c 982build_iv_mapping (vec<tree> iv_map, struct clast_user_stmt *user_stmt,
17e7716e 983 ivs_params_p ip)
c6bb733d 984{
985 struct clast_stmt *t;
4ed27c8e 986 int depth = 0;
c6bb733d 987 CloogStatement *cs = user_stmt->statement;
32819af5 988 poly_bb_p pbb = (poly_bb_p) cs->usr;
4ed27c8e 989 gimple_bb_p gbb = PBB_BLACK_BOX (pbb);
24a2ecdb 990 mpz_t bound_one, bound_two;
4c48fb0e 991
24a2ecdb 992 mpz_init (bound_one);
993 mpz_init (bound_two);
c6bb733d 994
4ed27c8e 995 for (t = user_stmt->substitutions; t; t = t->next, depth++)
c6bb733d 996 {
997 struct clast_expr *expr = (struct clast_expr *)
998 ((struct clast_assignment *)t)->RHS;
24a2ecdb 999 tree type = type_for_clast_expr (expr, ip, bound_one, bound_two);
17e7716e 1000 tree new_name = clast_to_gcc_expression (type, expr, ip);
1001 loop_p old_loop = gbb_loop_at_index (gbb, ip->region, depth);
4ed27c8e 1002
f1f41a6c 1003 iv_map[old_loop->num] = new_name;
c6bb733d 1004 }
4c48fb0e 1005
24a2ecdb 1006 mpz_clear (bound_one);
1007 mpz_clear (bound_two);
c6bb733d 1008}
1009
4ed27c8e 1010/* Construct bb_pbb_def with BB and PBB. */
c6bb733d 1011
1012static bb_pbb_def *
1013new_bb_pbb_def (basic_block bb, poly_bb_p pbb)
1014{
1015 bb_pbb_def *bb_pbb_p;
1016
1017 bb_pbb_p = XNEW (bb_pbb_def);
1018 bb_pbb_p->bb = bb;
1019 bb_pbb_p->pbb = pbb;
1020
1021 return bb_pbb_p;
1022}
1023
1024/* Mark BB with it's relevant PBB via hashing table BB_PBB_MAPPING. */
1025
1026static void
d9dd21a8 1027mark_bb_with_pbb (poly_bb_p pbb, basic_block bb,
1028 bb_pbb_htab_type bb_pbb_mapping)
c6bb733d 1029{
1030 bb_pbb_def tmp;
d9dd21a8 1031 bb_pbb_def **x;
c6bb733d 1032
1033 tmp.bb = bb;
d9dd21a8 1034 x = bb_pbb_mapping.find_slot (&tmp, INSERT);
c6bb733d 1035
cfd3faac 1036 if (x && !*x)
c6bb733d 1037 *x = new_bb_pbb_def (bb, pbb);
1038}
1039
2eb8c11d 1040/* Find BB's related poly_bb_p in hash table BB_PBB_MAPPING. */
1041
87e20041 1042poly_bb_p
d9dd21a8 1043find_pbb_via_hash (bb_pbb_htab_type bb_pbb_mapping, basic_block bb)
2eb8c11d 1044{
1045 bb_pbb_def tmp;
d9dd21a8 1046 bb_pbb_def **slot;
2eb8c11d 1047
1048 tmp.bb = bb;
d9dd21a8 1049 slot = bb_pbb_mapping.find_slot (&tmp, NO_INSERT);
2eb8c11d 1050
1051 if (slot && *slot)
1052 return ((bb_pbb_def *) *slot)->pbb;
1053
1054 return NULL;
1055}
1056
87e20041 1057/* Return the scop of the loop and initialize PBBS the set of
1058 poly_bb_p that belong to the LOOP. BB_PBB_MAPPING is a map created
1059 by the CLAST code generator between a generated basic_block and its
1060 related poly_bb_p. */
2eb8c11d 1061
87e20041 1062scop_p
d9dd21a8 1063get_loop_body_pbbs (loop_p loop, bb_pbb_htab_type bb_pbb_mapping,
f1f41a6c 1064 vec<poly_bb_p> *pbbs)
2eb8c11d 1065{
87e20041 1066 unsigned i;
2eb8c11d 1067 basic_block *bbs = get_loop_body_in_dom_order (loop);
87e20041 1068 scop_p scop = NULL;
2eb8c11d 1069
1070 for (i = 0; i < loop->num_nodes; i++)
1071 {
87e20041 1072 poly_bb_p pbb = find_pbb_via_hash (bb_pbb_mapping, bbs[i]);
2eb8c11d 1073
87e20041 1074 if (pbb == NULL)
1075 continue;
2eb8c11d 1076
87e20041 1077 scop = PBB_SCOP (pbb);
f1f41a6c 1078 (*pbbs).safe_push (pbb);
2eb8c11d 1079 }
1080
1081 free (bbs);
87e20041 1082 return scop;
2eb8c11d 1083}
1084
9a75e57c 1085/* Translates a clast user statement STMT to gimple.
1086
c6bb733d 1087 - NEXT_E is the edge where new generated code should be attached.
2edfa860 1088 - CONTEXT_LOOP is the loop in which the generated code will be placed
17e7716e 1089 - BB_PBB_MAPPING is is a basic_block and it's related poly_bb_p mapping. */
1090
9a75e57c 1091static edge
17e7716e 1092translate_clast_user (struct clast_user_stmt *stmt, edge next_e,
d9dd21a8 1093 bb_pbb_htab_type bb_pbb_mapping, ivs_params_p ip)
9a75e57c 1094{
4ed27c8e 1095 int i, nb_loops;
2edfa860 1096 basic_block new_bb;
32819af5 1097 poly_bb_p pbb = (poly_bb_p) stmt->statement->usr;
4ed27c8e 1098 gimple_bb_p gbb = PBB_BLACK_BOX (pbb);
f1f41a6c 1099 vec<tree> iv_map;
9a75e57c 1100
1101 if (GBB_BB (gbb) == ENTRY_BLOCK_PTR)
1102 return next_e;
1103
41f75a99 1104 nb_loops = number_of_loops (cfun);
f1f41a6c 1105 iv_map.create (nb_loops);
4ed27c8e 1106 for (i = 0; i < nb_loops; i++)
f1f41a6c 1107 iv_map.quick_push (NULL_TREE);
4ed27c8e 1108
17e7716e 1109 build_iv_mapping (iv_map, stmt, ip);
1110 next_e = copy_bb_and_scalar_dependences (GBB_BB (gbb), ip->region,
1034b719 1111 next_e, iv_map, &gloog_error);
f1f41a6c 1112 iv_map.release ();
4ed27c8e 1113
2edfa860 1114 new_bb = next_e->src;
1115 mark_bb_with_pbb (pbb, new_bb, bb_pbb_mapping);
278611f2 1116 mark_virtual_operands_for_renaming (cfun);
9a75e57c 1117 update_ssa (TODO_update_ssa);
bafaa7f6 1118
0f5b569a 1119 return next_e;
9a75e57c 1120}
1121
32e78944 1122/* Creates a new if region protecting the loop to be executed, if the execution
b7bde372 1123 count is zero (lb > ub). */
c5c86259 1124
32e78944 1125static edge
17e7716e 1126graphite_create_new_loop_guard (edge entry_edge, struct clast_for *stmt,
7cfe5b1f 1127 tree *type, tree *lb, tree *ub,
17e7716e 1128 ivs_params_p ip)
32e78944 1129{
1130 tree cond_expr;
1131 edge exit_edge;
35048891 1132
7cfe5b1f 1133 *type = type_for_clast_for (stmt, ip);
17e7716e 1134 *lb = clast_to_gcc_expression (*type, stmt->LB, ip);
1135 *ub = clast_to_gcc_expression (*type, stmt->UB, ip);
35048891 1136
c7cee0e4 1137 /* When ub is simply a constant or a parameter, use lb <= ub. */
35048891 1138 if (TREE_CODE (*ub) == INTEGER_CST || TREE_CODE (*ub) == SSA_NAME)
1139 cond_expr = fold_build2 (LE_EXPR, boolean_type_node, *lb, *ub);
7c0d15dc 1140 else
c7cee0e4 1141 {
35048891 1142 tree one = (POINTER_TYPE_P (*type)
a0553bff 1143 ? convert_to_ptrofftype (integer_one_node)
35048891 1144 : fold_convert (*type, integer_one_node));
c7cee0e4 1145 /* Adding +1 and using LT_EXPR helps with loop latches that have a
1146 loop iteration count of "PARAMETER - 1". For PARAMETER == 0 this becomes
1147 2^k-1 due to integer overflow, and the condition lb <= ub is true,
1148 even if we do not want this. However lb < ub + 1 is false, as
1149 expected. */
35048891 1150 tree ub_one = fold_build2 (POINTER_TYPE_P (*type) ? POINTER_PLUS_EXPR
1151 : PLUS_EXPR, *type, *ub, one);
c7cee0e4 1152
35048891 1153 cond_expr = fold_build2 (LT_EXPR, boolean_type_node, *lb, ub_one);
c7cee0e4 1154 }
32e78944 1155
1156 exit_edge = create_empty_if_region_on_edge (entry_edge, cond_expr);
1157
1158 return exit_edge;
1159}
1160
4ed27c8e 1161static edge
d9dd21a8 1162translate_clast (loop_p, struct clast_stmt *, edge, bb_pbb_htab_type,
1163 int, ivs_params_p);
32e78944 1164
1165/* Create the loop for a clast for statement.
9a75e57c 1166
9a75e57c 1167 - NEXT_E is the edge where new generated code should be attached.
17e7716e 1168 - BB_PBB_MAPPING is is a basic_block and it's related poly_bb_p mapping. */
35048891 1169
9a75e57c 1170static edge
17e7716e 1171translate_clast_for_loop (loop_p context_loop, struct clast_for *stmt,
d9dd21a8 1172 edge next_e, bb_pbb_htab_type bb_pbb_mapping,
1173 int level, tree type, tree lb, tree ub,
1174 ivs_params_p ip)
9a75e57c 1175{
17e7716e 1176 struct loop *loop = graphite_create_new_loop (next_e, stmt, context_loop,
1177 type, lb, ub, level, ip);
9a75e57c 1178 edge last_e = single_exit (loop);
2edfa860 1179 edge to_body = single_succ_edge (loop->header);
1180 basic_block after = to_body->dest;
9a75e57c 1181
1182 /* Create a basic block for loop close phi nodes. */
1183 last_e = single_succ_edge (split_edge (last_e));
2edfa860 1184
1185 /* Translate the body of the loop. */
17e7716e 1186 next_e = translate_clast (loop, stmt->body, to_body, bb_pbb_mapping,
1187 level + 1, ip);
2edfa860 1188 redirect_edge_succ_nodup (next_e, after);
1189 set_immediate_dominator (CDI_DOMINATORS, next_e->dest, next_e->src);
1190
bffcae34 1191 isl_set *domain = isl_set_from_cloog_domain (stmt->domain);
1192 int scheduling_dim = isl_set_n_dim (domain);
1193
2edfa860 1194 if (flag_loop_parallelize_all
bffcae34 1195 && loop_is_parallel_p (loop, bb_pbb_mapping, scheduling_dim))
2edfa860 1196 loop->can_be_parallel = true;
9a75e57c 1197
0f5b569a 1198 return last_e;
9a75e57c 1199}
1200
32e78944 1201/* Translates a clast for statement STMT to gimple. First a guard is created
b7bde372 1202 protecting the loop, if it is executed zero times. In this guard we create
1203 the real loop structure.
32e78944 1204
32e78944 1205 - NEXT_E is the edge where new generated code should be attached.
17e7716e 1206 - BB_PBB_MAPPING is is a basic_block and it's related poly_bb_p mapping. */
1207
32e78944 1208static edge
17e7716e 1209translate_clast_for (loop_p context_loop, struct clast_for *stmt, edge next_e,
d9dd21a8 1210 bb_pbb_htab_type bb_pbb_mapping, int level,
1211 ivs_params_p ip)
32e78944 1212{
35048891 1213 tree type, lb, ub;
7cfe5b1f 1214 edge last_e = graphite_create_new_loop_guard (next_e, stmt, &type,
17e7716e 1215 &lb, &ub, ip);
32e78944 1216 edge true_e = get_true_edge_from_guard_bb (next_e->dest);
32e78944 1217
17e7716e 1218 translate_clast_for_loop (context_loop, stmt, true_e, bb_pbb_mapping, level,
1219 type, lb, ub, ip);
32e78944 1220 return last_e;
1221}
1222
04f7c859 1223/* Translates a clast assignment STMT to gimple.
1224
1225 - NEXT_E is the edge where new generated code should be attached.
1226 - BB_PBB_MAPPING is is a basic_block and it's related poly_bb_p mapping. */
1227
1228static edge
1229translate_clast_assignment (struct clast_assignment *stmt, edge next_e,
1230 int level, ivs_params_p ip)
1231{
1232 gimple_seq stmts;
24a2ecdb 1233 mpz_t bound_one, bound_two;
04f7c859 1234 tree type, new_name, var;
1235 edge res = single_succ_edge (split_edge (next_e));
1236 struct clast_expr *expr = (struct clast_expr *) stmt->RHS;
1237
24a2ecdb 1238 mpz_init (bound_one);
1239 mpz_init (bound_two);
1240 type = type_for_clast_expr (expr, ip, bound_one, bound_two);
04f7c859 1241 var = create_tmp_var (type, "graphite_var");
1242 new_name = force_gimple_operand (clast_to_gcc_expression (type, expr, ip),
1243 &stmts, true, var);
04f7c859 1244 if (stmts)
1245 {
1246 gsi_insert_seq_on_edge (next_e, stmts);
1247 gsi_commit_edge_inserts ();
1248 }
1249
1250 save_clast_name_index (ip->newivs_index, stmt->LHS,
f1f41a6c 1251 (*ip->newivs).length (), level,
24a2ecdb 1252 bound_one, bound_two);
f1f41a6c 1253 (*ip->newivs).safe_push (new_name);
04f7c859 1254
24a2ecdb 1255 mpz_clear (bound_one);
1256 mpz_clear (bound_two);
04f7c859 1257
1258 return res;
1259}
1260
9a75e57c 1261/* Translates a clast guard statement STMT to gimple.
1262
9a75e57c 1263 - NEXT_E is the edge where new generated code should be attached.
2edfa860 1264 - CONTEXT_LOOP is the loop in which the generated code will be placed
17e7716e 1265 - BB_PBB_MAPPING is is a basic_block and it's related poly_bb_p mapping. */
1266
9a75e57c 1267static edge
17e7716e 1268translate_clast_guard (loop_p context_loop, struct clast_guard *stmt,
d9dd21a8 1269 edge next_e, bb_pbb_htab_type bb_pbb_mapping, int level,
17e7716e 1270 ivs_params_p ip)
0f5b569a 1271{
17e7716e 1272 edge last_e = graphite_create_new_guard (next_e, stmt, ip);
9a75e57c 1273 edge true_e = get_true_edge_from_guard_bb (next_e->dest);
9a75e57c 1274
17e7716e 1275 translate_clast (context_loop, stmt->then, true_e, bb_pbb_mapping, level, ip);
0f5b569a 1276 return last_e;
9a75e57c 1277}
c6bb733d 1278
9a75e57c 1279/* Translates a CLAST statement STMT to GCC representation in the
1280 context of a SESE.
1281
1282 - NEXT_E is the edge where new generated code should be attached.
2edfa860 1283 - CONTEXT_LOOP is the loop in which the generated code will be placed
9a75e57c 1284 - BB_PBB_MAPPING is is a basic_block and it's related poly_bb_p mapping. */
17e7716e 1285
c6bb733d 1286static edge
17e7716e 1287translate_clast (loop_p context_loop, struct clast_stmt *stmt, edge next_e,
d9dd21a8 1288 bb_pbb_htab_type bb_pbb_mapping, int level, ivs_params_p ip)
c6bb733d 1289{
2d0a2aaa 1290 if (!stmt)
c6bb733d 1291 return next_e;
1292
1293 if (CLAST_STMT_IS_A (stmt, stmt_root))
0f5b569a 1294 ; /* Do nothing. */
c6bb733d 1295
0f5b569a 1296 else if (CLAST_STMT_IS_A (stmt, stmt_user))
17e7716e 1297 next_e = translate_clast_user ((struct clast_user_stmt *) stmt,
1298 next_e, bb_pbb_mapping, ip);
c6bb733d 1299
0f5b569a 1300 else if (CLAST_STMT_IS_A (stmt, stmt_for))
17e7716e 1301 next_e = translate_clast_for (context_loop, (struct clast_for *) stmt,
1302 next_e, bb_pbb_mapping, level, ip);
c6bb733d 1303
0f5b569a 1304 else if (CLAST_STMT_IS_A (stmt, stmt_guard))
17e7716e 1305 next_e = translate_clast_guard (context_loop, (struct clast_guard *) stmt,
1306 next_e, bb_pbb_mapping, level, ip);
0f5b569a 1307
1308 else if (CLAST_STMT_IS_A (stmt, stmt_block))
17e7716e 1309 next_e = translate_clast (context_loop, ((struct clast_block *) stmt)->body,
1310 next_e, bb_pbb_mapping, level, ip);
04f7c859 1311
1312 else if (CLAST_STMT_IS_A (stmt, stmt_ass))
1313 next_e = translate_clast_assignment ((struct clast_assignment *) stmt,
1314 next_e, level, ip);
0f5b569a 1315 else
9af5ce0c 1316 gcc_unreachable ();
c6bb733d 1317
0f5b569a 1318 recompute_all_dominators ();
1319 graphite_verify ();
1320
17e7716e 1321 return translate_clast (context_loop, stmt->next, next_e, bb_pbb_mapping,
1322 level, ip);
c6bb733d 1323}
1324
32819af5 1325/* Add parameter and iterator names to the CloogUnionDomain. */
c6bb733d 1326
32819af5 1327static CloogUnionDomain *
1328add_names_to_union_domain (scop_p scop, CloogUnionDomain *union_domain,
d9dd21a8 1329 int nb_scattering_dims,
1330 clast_index_htab_type params_index)
c6bb733d 1331{
1332 sese region = SCOP_REGION (scop);
1333 int i;
1334 int nb_iterators = scop_max_loop_depth (scop);
f1f41a6c 1335 int nb_parameters = SESE_PARAMS (region).length ();
32819af5 1336 mpz_t bound_one, bound_two;
c6bb733d 1337
32819af5 1338 mpz_init (bound_one);
1339 mpz_init (bound_two);
c9ef6b0e 1340
1341 for (i = 0; i < nb_parameters; i++)
1342 {
f1f41a6c 1343 tree param = SESE_PARAMS (region)[i];
c9ef6b0e 1344 const char *name = get_name (param);
1345 int len;
32819af5 1346 char *parameter;
c9ef6b0e 1347
1348 if (!name)
1349 name = "T";
1350
1351 len = strlen (name);
1352 len += 17;
32819af5 1353 parameter = XNEWVEC (char, len + 1);
1354 snprintf (parameter, len, "%s_%d", name, SSA_NAME_VERSION (param));
1355 save_clast_name_index (params_index, parameter, i, i, bound_one,
1356 bound_two);
1357 union_domain = cloog_union_domain_set_name (union_domain, CLOOG_PARAM, i,
1358 parameter);
1359 compute_bounds_for_param (scop, i, bound_one, bound_two);
1360 free (parameter);
c9ef6b0e 1361 }
1362
32819af5 1363 mpz_clear (bound_one);
1364 mpz_clear (bound_two);
c6bb733d 1365
1366 for (i = 0; i < nb_iterators; i++)
1367 {
1368 int len = 4 + 16;
32819af5 1369 char *iterator;
1370 iterator = XNEWVEC (char, len);
1371 snprintf (iterator, len, "git_%d", i);
1372 union_domain = cloog_union_domain_set_name (union_domain, CLOOG_ITER, i,
1373 iterator);
1374 free (iterator);
c6bb733d 1375 }
1376
32819af5 1377 for (i = 0; i < nb_scattering_dims; i++)
c6bb733d 1378 {
1379 int len = 5 + 16;
32819af5 1380 char *scattering;
1381 scattering = XNEWVEC (char, len);
1382 snprintf (scattering, len, "scat_%d", i);
1383 union_domain = cloog_union_domain_set_name (union_domain, CLOOG_SCAT, i,
1384 scattering);
1385 free (scattering);
c6bb733d 1386 }
1387
32819af5 1388 return union_domain;
c6bb733d 1389}
1390
acad129f 1391/* Initialize a CLooG input file. */
1392
1393static FILE *
1394init_cloog_input_file (int scop_number)
1395{
1396 FILE *graphite_out_file;
1397 int len = strlen (dump_base_name);
1398 char *dumpname = XNEWVEC (char, len + 25);
1399 char *s_scop_number = XNEWVEC (char, 15);
1400
1401 memcpy (dumpname, dump_base_name, len + 1);
1402 strip_off_ending (dumpname, len);
1403 sprintf (s_scop_number, ".%d", scop_number);
1404 strcat (dumpname, s_scop_number);
1405 strcat (dumpname, ".cloog");
1406 graphite_out_file = fopen (dumpname, "w+b");
1407
1408 if (graphite_out_file == 0)
1409 fatal_error ("can%'t open %s for writing: %m", dumpname);
1410
1411 free (dumpname);
1412
1413 return graphite_out_file;
1414}
1415
87e20041 1416/* Extend the scattering to NEW_DIMS scattering dimensions. */
1417
1418static
9af5ce0c 1419isl_map *extend_scattering (isl_map *scattering, int new_dims)
87e20041 1420{
1421 int old_dims, i;
1422 isl_space *space;
1423 isl_basic_map *change_scattering;
1424 isl_map *change_scattering_map;
1425
1426 old_dims = isl_map_dim (scattering, isl_dim_out);
1427
1428 space = isl_space_alloc (isl_map_get_ctx (scattering), 0, old_dims, new_dims);
1429 change_scattering = isl_basic_map_universe (isl_space_copy (space));
1430
1431 for (i = 0; i < old_dims; i++)
1432 {
1433 isl_constraint *c;
1434 c = isl_equality_alloc
1435 (isl_local_space_from_space (isl_space_copy (space)));
1436 isl_constraint_set_coefficient_si (c, isl_dim_in, i, 1);
1437 isl_constraint_set_coefficient_si (c, isl_dim_out, i, -1);
1438 change_scattering = isl_basic_map_add_constraint (change_scattering, c);
1439 }
1440
1441 for (i = old_dims; i < new_dims; i++)
1442 {
1443 isl_constraint *c;
1444 c = isl_equality_alloc
1445 (isl_local_space_from_space (isl_space_copy (space)));
1446 isl_constraint_set_coefficient_si (c, isl_dim_out, i, 1);
1447 change_scattering = isl_basic_map_add_constraint (change_scattering, c);
1448 }
1449
1450 change_scattering_map = isl_map_from_basic_map (change_scattering);
1451 change_scattering_map = isl_map_align_params (change_scattering_map, space);
1452 return isl_map_apply_range (scattering, change_scattering_map);
1453}
1454
32819af5 1455/* Build cloog union domain for SCoP. */
c6bb733d 1456
32819af5 1457static CloogUnionDomain *
87e20041 1458build_cloog_union_domain (scop_p scop, int nb_scattering_dims)
c6bb733d 1459{
1460 int i;
c6bb733d 1461 poly_bb_p pbb;
32819af5 1462 CloogUnionDomain *union_domain =
1463 cloog_union_domain_alloc (scop_nb_params (scop));
c6bb733d 1464
f1f41a6c 1465 FOR_EACH_VEC_ELT (SCOP_BBS (scop), i, pbb)
c6bb733d 1466 {
32819af5 1467 CloogDomain *domain;
1468 CloogScattering *scattering;
c6bb733d 1469
1470 /* Dead code elimination: when the domain of a PBB is empty,
1471 don't generate code for the PBB. */
9af5ce0c 1472 if (isl_set_is_empty (pbb->domain))
c6bb733d 1473 continue;
1474
9af5ce0c 1475 domain = cloog_domain_from_isl_set (isl_set_copy (pbb->domain));
1476 scattering = cloog_scattering_from_isl_map
1477 (extend_scattering (isl_map_copy (pbb->transformed),
1478 nb_scattering_dims));
c6bb733d 1479
32819af5 1480 union_domain = cloog_union_domain_add_domain (union_domain, "", domain,
1481 scattering, pbb);
c6bb733d 1482 }
1483
32819af5 1484 return union_domain;
c6bb733d 1485}
1486
1487/* Return the options that will be used in GLOOG. */
1488
1489static CloogOptions *
98b9957e 1490set_cloog_options (void)
c6bb733d 1491{
98b9957e 1492 CloogOptions *options = cloog_options_malloc (cloog_state);
c6bb733d 1493
1494 /* Change cloog output language to C. If we do use FORTRAN instead, cloog
1495 will stop e.g. with "ERROR: unbounded loops not allowed in FORTRAN.", if
1496 we pass an incomplete program to cloog. */
e828ad34 1497 options->language = CLOOG_LANGUAGE_C;
c6bb733d 1498
1499 /* Enable complex equality spreading: removes dummy statements
1500 (assignments) in the generated code which repeats the
1501 substitution equations for statements. This is useless for
1502 GLooG. */
1503 options->esp = 1;
1504
ebd32a89 1505 /* Silence CLooG to avoid failing tests due to debug output to stderr. */
1506 options->quiet = 1;
c6bb733d 1507
1508 /* Allow cloog to build strides with a stride width different to one.
1509 This example has stride = 4:
1510
1511 for (i = 0; i < 20; i += 4)
1512 A */
1513 options->strides = 1;
1514
87e20041 1515 /* We want the clast to provide the iteration domains of the executed loops.
1516 This allows us to derive minimal/maximal values for the induction
1517 variables. */
1518 options->save_domains = 1;
1519
c6bb733d 1520 /* Disable optimizations and make cloog generate source code closer to the
1521 input. This is useful for debugging, but later we want the optimized
1522 code.
1523
1524 XXX: We can not disable optimizations, as loop blocking is not working
1525 without them. */
1526 if (0)
1527 {
1528 options->f = -1;
1529 options->l = INT_MAX;
1530 }
1531
1532 return options;
1533}
1534
1535/* Prints STMT to STDERR. */
1536
1537void
1538print_clast_stmt (FILE *file, struct clast_stmt *stmt)
1539{
98b9957e 1540 CloogOptions *options = set_cloog_options ();
c6bb733d 1541
2e6bc1c7 1542 clast_pprint (file, stmt, 0, options);
c6bb733d 1543 cloog_options_free (options);
1544}
1545
1546/* Prints STMT to STDERR. */
1547
4b987fac 1548DEBUG_FUNCTION void
c6bb733d 1549debug_clast_stmt (struct clast_stmt *stmt)
1550{
1551 print_clast_stmt (stderr, stmt);
1552}
1553
87e20041 1554/* Get the maximal number of scattering dimensions in the scop SCOP. */
1555
1556static
1557int get_max_scattering_dimensions (scop_p scop)
1558{
1559 int i;
1560 poly_bb_p pbb;
1561 int scattering_dims = 0;
1562
f1f41a6c 1563 FOR_EACH_VEC_ELT (SCOP_BBS (scop), i, pbb)
87e20041 1564 {
1565 int pbb_scatt_dims = isl_map_dim (pbb->transformed, isl_dim_out);
1566 if (pbb_scatt_dims > scattering_dims)
1567 scattering_dims = pbb_scatt_dims;
1568 }
1569
1570 return scattering_dims;
1571}
1572
32819af5 1573static CloogInput *
d9dd21a8 1574generate_cloog_input (scop_p scop, clast_index_htab_type params_index)
32819af5 1575{
1576 CloogUnionDomain *union_domain;
1577 CloogInput *cloog_input;
1578 CloogDomain *context;
87e20041 1579 int nb_scattering_dims = get_max_scattering_dimensions (scop);
32819af5 1580
87e20041 1581 union_domain = build_cloog_union_domain (scop, nb_scattering_dims);
32819af5 1582 union_domain = add_names_to_union_domain (scop, union_domain,
1583 nb_scattering_dims,
1584 params_index);
87e20041 1585 context = cloog_domain_from_isl_set (isl_set_copy (scop->context));
32819af5 1586
1587 cloog_input = cloog_input_alloc (context, union_domain);
1588
1589 return cloog_input;
1590}
1591
c6bb733d 1592/* Translate SCOP to a CLooG program and clast. These two
1593 representations should be freed together: a clast cannot be used
1594 without a program. */
1595
32819af5 1596static struct clast_stmt *
d9dd21a8 1597scop_to_clast (scop_p scop, clast_index_htab_type params_index)
c6bb733d 1598{
32819af5 1599 CloogInput *cloog_input;
1600 struct clast_stmt *clast;
98b9957e 1601 CloogOptions *options = set_cloog_options ();
c6bb733d 1602
32819af5 1603 cloog_input = generate_cloog_input (scop, params_index);
1604
1605 /* Dump a .cloog input file, if requested. This feature is only
1606 enabled in the Graphite branch. */
1607 if (0)
1608 {
1609 static size_t file_scop_number = 0;
1610 FILE *cloog_file = init_cloog_input_file (file_scop_number);
1611 cloog_input_dump_cloog (cloog_file, cloog_input, options);
1612 }
1613
1614 clast = cloog_clast_create_from_input (cloog_input, options);
c6bb733d 1615
1616 cloog_options_free (options);
32819af5 1617 return clast;
c6bb733d 1618}
1619
1620/* Prints to FILE the code generated by CLooG for SCOP. */
1621
1622void
1623print_generated_program (FILE *file, scop_p scop)
1624{
98b9957e 1625 CloogOptions *options = set_cloog_options ();
d9dd21a8 1626 clast_index_htab_type params_index;
32819af5 1627 struct clast_stmt *clast;
08a88144 1628
d9dd21a8 1629 params_index.create (10);
c6bb733d 1630
32819af5 1631 clast = scop_to_clast (scop, params_index);
c6bb733d 1632
1633 fprintf (file, " (clast: \n");
32819af5 1634 clast_pprint (file, clast, 0, options);
c6bb733d 1635 fprintf (file, " )\n");
1636
1637 cloog_options_free (options);
32819af5 1638 cloog_clast_free (clast);
c6bb733d 1639}
1640
1641/* Prints to STDERR the code generated by CLooG for SCOP. */
1642
4b987fac 1643DEBUG_FUNCTION void
c6bb733d 1644debug_generated_program (scop_p scop)
1645{
1646 print_generated_program (stderr, scop);
1647}
1648
c6bb733d 1649/* GIMPLE Loop Generator: generates loops from STMT in GIMPLE form for
1650 the given SCOP. Return true if code generation succeeded.
1651 BB_PBB_MAPPING is a basic_block and it's related poly_bb_p mapping.
1652*/
1653
1654bool
d9dd21a8 1655gloog (scop_p scop, bb_pbb_htab_type bb_pbb_mapping)
c6bb733d 1656{
e85cf4e5 1657 stack_vec<tree, 10> newivs;
2edfa860 1658 loop_p context_loop;
c6bb733d 1659 sese region = SCOP_REGION (scop);
1660 ifsese if_region = NULL;
d9dd21a8 1661 clast_index_htab_type newivs_index, params_index;
32819af5 1662 struct clast_stmt *clast;
17e7716e 1663 struct ivs_params ip;
525c22c4 1664
1665 timevar_push (TV_GRAPHITE_CODE_GEN);
2487de19 1666 gloog_error = false;
525c22c4 1667
d9dd21a8 1668 params_index.create (10);
32819af5 1669
1670 clast = scop_to_clast (scop, params_index);
c6bb733d 1671
1672 if (dump_file && (dump_flags & TDF_DETAILS))
1673 {
1674 fprintf (dump_file, "\nCLAST generated by CLooG: \n");
32819af5 1675 print_clast_stmt (dump_file, clast);
c6bb733d 1676 fprintf (dump_file, "\n");
1677 }
1678
c6bb733d 1679 recompute_all_dominators ();
1680 graphite_verify ();
1681
1682 if_region = move_sese_in_condition (region);
1683 sese_insert_phis_for_liveouts (region,
1684 if_region->region->exit->src,
1685 if_region->false_region->exit,
1686 if_region->true_region->exit);
c6bb733d 1687 recompute_all_dominators ();
1688 graphite_verify ();
c9ef6b0e 1689
2edfa860 1690 context_loop = SESE_ENTRY (region)->src->loop_father;
d9dd21a8 1691 newivs_index.create (10);
c6bb733d 1692
17e7716e 1693 ip.newivs = &newivs;
1694 ip.newivs_index = newivs_index;
1695 ip.params = SESE_PARAMS (region);
1696 ip.params_index = params_index;
1697 ip.region = region;
1698
32819af5 1699 translate_clast (context_loop, clast, if_region->true_region->entry,
17e7716e 1700 bb_pbb_mapping, 0, &ip);
c6bb733d 1701 graphite_verify ();
d081c1c0 1702 scev_reset ();
c6bb733d 1703 recompute_all_dominators ();
1704 graphite_verify ();
1705
2487de19 1706 if (gloog_error)
1707 set_ifsese_condition (if_region, integer_zero_node);
1708
d996851c 1709 free (if_region->true_region);
1710 free (if_region->region);
1711 free (if_region);
1712
d9dd21a8 1713 newivs_index.dispose ();
1714 params_index.dispose ();
32819af5 1715 cloog_clast_free (clast);
525c22c4 1716 timevar_pop (TV_GRAPHITE_CODE_GEN);
1717
2eb8c11d 1718 if (dump_file && (dump_flags & TDF_DETAILS))
c6bb733d 1719 {
2eb8c11d 1720 loop_p loop;
2eb8c11d 1721 int num_no_dependency = 0;
c6bb733d 1722
f21d4d00 1723 FOR_EACH_LOOP (loop, 0)
2eb8c11d 1724 if (loop->can_be_parallel)
1725 num_no_dependency++;
c6bb733d 1726
2eb8c11d 1727 fprintf (dump_file, "\n%d loops carried no dependency.\n",
1728 num_no_dependency);
c6bb733d 1729 }
1730
2487de19 1731 return !gloog_error;
c6bb733d 1732}
c6bb733d 1733#endif