]>
Commit | Line | Data |
---|---|---|
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 | ||
5 | This file is part of GCC. | |
6 | ||
7 | GCC is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3, or (at your option) | |
10 | any later version. | |
11 | ||
12 | GCC is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along 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 | |
59 | typedef 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 | ||
68 | static tree | |
69 | gmp_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 | ||
85 | static void | |
86 | value_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 | ||
96 | static void | |
97 | value_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. */ | |
108 | static bool gloog_error; | |
109 | ||
c6bb733d | 110 | /* Verifies properties that GRAPHITE should maintain during translation. */ |
111 | ||
112 | static inline void | |
113 | graphite_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 | |
125 | typedef 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 | ||
137 | struct 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 | ||
148 | inline hashval_t | |
149 | clast_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 | ||
164 | inline bool | |
165 | clast_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 | ||
172 | inline void | |
173 | clast_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 | ||
182 | typedef 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 | |
187 | static inline clast_name_index_p | |
7cfe5b1f | 188 | new_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 | ||
211 | static inline int | |
d9dd21a8 | 212 | clast_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 | ||
233 | static inline int | |
d9dd21a8 | 234 | clast_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 | ||
254 | static inline bool | |
d9dd21a8 | 255 | clast_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 | |
278 | static inline void | |
d9dd21a8 | 279 | save_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 | ||
304 | typedef 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 | ||
313 | static tree | |
32819af5 | 314 | clast_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 | 335 | static tree |
28013ca9 | 336 | max_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 | 379 | static tree |
17e7716e | 380 | clast_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 | ||
385 | static tree | |
386 | clast_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 | ||
405 | static tree | |
17e7716e | 406 | clast_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 | |
522 | static tree | |
24a2ecdb | 523 | type_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 | ||
567 | static tree | |
954e0498 | 568 | type_for_value (mpz_t val) |
f20b6ea9 | 569 | { |
954e0498 | 570 | return type_for_interval (val, val); |
f20b6ea9 | 571 | } |
572 | ||
32819af5 | 573 | static tree |
574 | type_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 | |
579 | static tree | |
24a2ecdb | 580 | type_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 | |
604 | static tree | |
4c48fb0e | 605 | type_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 | ||
664 | static tree | |
24a2ecdb | 665 | type_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 | ||
711 | static tree | |
712 | type_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 | |
734 | static tree | |
24a2ecdb | 735 | type_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 | 765 | static bool |
766 | clast_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 | ||
779 | static tree | |
17e7716e | 780 | graphite_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 | ||
832 | static tree | |
17e7716e | 833 | graphite_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 | ||
854 | static edge | |
17e7716e | 855 | graphite_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 | ||
866 | static void | |
867 | compute_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 | 893 | static void |
894 | compute_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 | |
927 | static tree | |
7cfe5b1f | 928 | type_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 | |
953 | static struct loop * | |
17e7716e | 954 | graphite_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 | |
981 | static void | |
f1f41a6c | 982 | build_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 | |
1012 | static bb_pbb_def * | |
1013 | new_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 | ||
1026 | static void | |
d9dd21a8 | 1027 | mark_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 | 1042 | poly_bb_p |
d9dd21a8 | 1043 | find_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 | 1062 | scop_p |
d9dd21a8 | 1063 | get_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 | 1091 | static edge |
17e7716e | 1092 | translate_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 | 1125 | static edge |
17e7716e | 1126 | graphite_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 | 1161 | static edge |
d9dd21a8 | 1162 | translate_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 | 1170 | static edge |
17e7716e | 1171 | translate_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 | 1208 | static edge |
17e7716e | 1209 | translate_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 | ||
1228 | static edge | |
1229 | translate_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 | 1267 | static edge |
17e7716e | 1268 | translate_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 | 1286 | static edge |
17e7716e | 1287 | translate_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 | 1327 | static CloogUnionDomain * |
1328 | add_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 | ||
1393 | static FILE * | |
1394 | init_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 | ||
1418 | static | |
9af5ce0c | 1419 | isl_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 | 1457 | static CloogUnionDomain * |
87e20041 | 1458 | build_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 | ||
1489 | static CloogOptions * | |
98b9957e | 1490 | set_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 | ||
1537 | void | |
1538 | print_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 | 1548 | DEBUG_FUNCTION void |
c6bb733d | 1549 | debug_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 | ||
1556 | static | |
1557 | int 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 | 1573 | static CloogInput * |
d9dd21a8 | 1574 | generate_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 | 1596 | static struct clast_stmt * |
d9dd21a8 | 1597 | scop_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 | ||
1622 | void | |
1623 | print_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 | 1643 | DEBUG_FUNCTION void |
c6bb733d | 1644 | debug_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 | ||
1654 | bool | |
d9dd21a8 | 1655 | gloog (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 |