]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/graphite-isl-ast-to-gimple.c
fc4af5a25ea7d2d58a636294a252f355f335bf08
[thirdparty/gcc.git] / gcc / graphite-isl-ast-to-gimple.c
1 /* Translation of ISL AST to Gimple.
2 Copyright (C) 2014-2015 Free Software Foundation, Inc.
3 Contributed by Roman Gareev <gareevroman@gmail.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"
22
23 #ifdef HAVE_isl
24 /* Workaround for GMP 5.1.3 bug, see PR56019. */
25 #include <stddef.h>
26
27 #include <isl/constraint.h>
28 #include <isl/set.h>
29 #include <isl/union_set.h>
30 #include <isl/map.h>
31 #include <isl/union_map.h>
32 #include <isl/ast_build.h>
33
34 /* Since ISL-0.13, the extern is in val_gmp.h. */
35 #if !defined(HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE) && defined(__cplusplus)
36 extern "C" {
37 #endif
38 #include <isl/val_gmp.h>
39 #if !defined(HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE) && defined(__cplusplus)
40 }
41 #endif
42
43 #include "system.h"
44 #include "coretypes.h"
45 #include "backend.h"
46 #include "cfghooks.h"
47 #include "tree.h"
48 #include "gimple.h"
49 #include "params.h"
50 #include "fold-const.h"
51 #include "gimple-iterator.h"
52 #include "tree-ssa-loop.h"
53 #include "tree-pass.h"
54 #include "cfgloop.h"
55 #include "tree-data-ref.h"
56 #include "graphite-poly.h"
57 #include "tree-ssa-loop-manip.h"
58 #include "tree-scalar-evolution.h"
59 #include "gimple-ssa.h"
60 #include "tree-phinodes.h"
61 #include "tree-into-ssa.h"
62 #include "ssa-iterators.h"
63 #include <map>
64 #include "graphite-isl-ast-to-gimple.h"
65
66 /* This flag is set when an error occurred during the translation of
67 ISL AST to Gimple. */
68
69 static bool graphite_regenerate_error;
70
71 /* We always try to use signed 128 bit types, but fall back to smaller types
72 in case a platform does not provide types of these sizes. In the future we
73 should use isl to derive the optimal type for each subexpression. */
74
75 static int max_mode_int_precision =
76 GET_MODE_PRECISION (mode_for_size (MAX_FIXED_MODE_SIZE, MODE_INT, 0));
77 static int graphite_expression_type_precision = 128 <= max_mode_int_precision ?
78 128 : max_mode_int_precision;
79
80 struct ast_build_info
81 {
82 ast_build_info()
83 : is_parallelizable(false)
84 { };
85 bool is_parallelizable;
86 };
87
88 /* Converts a GMP constant VAL to a tree and returns it. */
89
90 static tree
91 gmp_cst_to_tree (tree type, mpz_t val)
92 {
93 tree t = type ? type : integer_type_node;
94 mpz_t tmp;
95
96 mpz_init (tmp);
97 mpz_set (tmp, val);
98 wide_int wi = wi::from_mpz (t, tmp, true);
99 mpz_clear (tmp);
100
101 return wide_int_to_tree (t, wi);
102 }
103
104 /* Verifies properties that GRAPHITE should maintain during translation. */
105
106 static inline void
107 graphite_verify (void)
108 {
109 checking_verify_loop_structure ();
110 checking_verify_loop_closed_ssa (true);
111 }
112
113 /* IVS_PARAMS maps ISL's scattering and parameter identifiers
114 to corresponding trees. */
115
116 typedef std::map<isl_id *, tree> ivs_params;
117
118 /* Free all memory allocated for ISL's identifiers. */
119
120 void ivs_params_clear (ivs_params &ip)
121 {
122 std::map<isl_id *, tree>::iterator it;
123 for (it = ip.begin ();
124 it != ip.end (); it++)
125 {
126 isl_id_free (it->first);
127 }
128 }
129
130 class translate_isl_ast_to_gimple
131 {
132 public:
133 translate_isl_ast_to_gimple (sese_info_p r)
134 : region (r)
135 { }
136
137 /* Translates an ISL AST node NODE to GCC representation in the
138 context of a SESE. */
139 edge translate_isl_ast (loop_p context_loop, __isl_keep isl_ast_node *node,
140 edge next_e, ivs_params &ip);
141
142 /* Translates an isl_ast_node_for to Gimple. */
143 edge translate_isl_ast_node_for (loop_p context_loop,
144 __isl_keep isl_ast_node *node,
145 edge next_e, ivs_params &ip);
146
147 /* Create the loop for a isl_ast_node_for.
148
149 - NEXT_E is the edge where new generated code should be attached. */
150 edge translate_isl_ast_for_loop (loop_p context_loop,
151 __isl_keep isl_ast_node *node_for,
152 edge next_e,
153 tree type, tree lb, tree ub,
154 ivs_params &ip);
155
156 /* Translates an isl_ast_node_if to Gimple. */
157 edge translate_isl_ast_node_if (loop_p context_loop,
158 __isl_keep isl_ast_node *node,
159 edge next_e, ivs_params &ip);
160
161 /* Translates an isl_ast_node_user to Gimple.
162
163 FIXME: We should remove iv_map.create (loop->num + 1), if it is
164 possible. */
165 edge translate_isl_ast_node_user (__isl_keep isl_ast_node *node,
166 edge next_e, ivs_params &ip);
167
168 /* Translates an isl_ast_node_block to Gimple. */
169 edge translate_isl_ast_node_block (loop_p context_loop,
170 __isl_keep isl_ast_node *node,
171 edge next_e, ivs_params &ip);
172
173 /* Converts a unary isl_ast_expr_op expression E to a GCC expression tree of
174 type TYPE. */
175 tree unary_op_to_tree (tree type, __isl_take isl_ast_expr *expr,
176 ivs_params &ip);
177
178 /* Converts a binary isl_ast_expr_op expression E to a GCC expression tree of
179 type TYPE. */
180 tree binary_op_to_tree (tree type, __isl_take isl_ast_expr *expr,
181 ivs_params &ip);
182
183 /* Converts a ternary isl_ast_expr_op expression E to a GCC expression tree of
184 type TYPE. */
185 tree ternary_op_to_tree (tree type, __isl_take isl_ast_expr *expr,
186 ivs_params &ip);
187
188 /* Converts an isl_ast_expr_op expression E with unknown number of arguments
189 to a GCC expression tree of type TYPE. */
190 tree nary_op_to_tree (tree type, __isl_take isl_ast_expr *expr,
191 ivs_params &ip);
192
193 /* Converts an ISL AST expression E back to a GCC expression tree of
194 type TYPE. */
195 tree gcc_expression_from_isl_expression (tree type,
196 __isl_take isl_ast_expr *,
197 ivs_params &ip);
198
199 /* Return the tree variable that corresponds to the given isl ast identifier
200 expression (an isl_ast_expr of type isl_ast_expr_id).
201
202 FIXME: We should replace blind conversation of id's type with derivation
203 of the optimal type when we get the corresponding isl support. Blindly
204 converting type sizes may be problematic when we switch to smaller
205 types. */
206 tree gcc_expression_from_isl_ast_expr_id (tree type,
207 __isl_keep isl_ast_expr *expr_id,
208 ivs_params &ip);
209
210 /* Converts an isl_ast_expr_int expression E to a GCC expression tree of
211 type TYPE. */
212 tree gcc_expression_from_isl_expr_int (tree type,
213 __isl_take isl_ast_expr *expr);
214
215 /* Converts an isl_ast_expr_op expression E to a GCC expression tree of
216 type TYPE. */
217 tree gcc_expression_from_isl_expr_op (tree type,
218 __isl_take isl_ast_expr *expr,
219 ivs_params &ip);
220
221 /* Creates a new LOOP corresponding to isl_ast_node_for. Inserts an
222 induction variable for the new LOOP. New LOOP is attached to CFG
223 starting at ENTRY_EDGE. LOOP is inserted into the loop tree and
224 becomes the child loop of the OUTER_LOOP. NEWIVS_INDEX binds
225 ISL's scattering name to the induction variable created for the
226 loop of STMT. The new induction variable is inserted in the NEWIVS
227 vector and is of type TYPE. */
228 struct loop *graphite_create_new_loop (edge entry_edge,
229 __isl_keep isl_ast_node *node_for,
230 loop_p outer, tree type,
231 tree lb, tree ub, ivs_params &ip);
232
233 /* All loops generated by create_empty_loop_on_edge have the form of
234 a post-test loop:
235
236 do
237
238 {
239 body of the loop;
240 } while (lower bound < upper bound);
241
242 We create a new if region protecting the loop to be executed, if
243 the execution count is zero (lower bound > upper bound). */
244 edge graphite_create_new_loop_guard (edge entry_edge,
245 __isl_keep isl_ast_node *node_for,
246 tree *type,
247 tree *lb, tree *ub, ivs_params &ip);
248
249 /* Creates a new if region corresponding to ISL's cond. */
250 edge graphite_create_new_guard (edge entry_edge,
251 __isl_take isl_ast_expr *if_cond,
252 ivs_params &ip);
253
254 /* Inserts in iv_map a tuple (OLD_LOOP->num, NEW_NAME) for the induction
255 variables of the loops around GBB in SESE.
256
257 FIXME: Instead of using a vec<tree> that maps each loop id to a possible
258 chrec, we could consider using a map<int, tree> that maps loop ids to the
259 corresponding tree expressions. */
260 void build_iv_mapping (vec<tree> iv_map, gimple_poly_bb_p gbb,
261 __isl_keep isl_ast_expr *user_expr, ivs_params &ip,
262 sese_l &region);
263 private:
264 sese_info_p region;
265 };
266
267 /* Return the tree variable that corresponds to the given isl ast identifier
268 expression (an isl_ast_expr of type isl_ast_expr_id).
269
270 FIXME: We should replace blind conversation of id's type with derivation
271 of the optimal type when we get the corresponding isl support. Blindly
272 converting type sizes may be problematic when we switch to smaller
273 types. */
274
275 tree
276 translate_isl_ast_to_gimple::
277 gcc_expression_from_isl_ast_expr_id (tree type,
278 __isl_keep isl_ast_expr *expr_id,
279 ivs_params &ip)
280 {
281 gcc_assert (isl_ast_expr_get_type (expr_id) == isl_ast_expr_id);
282 isl_id *tmp_isl_id = isl_ast_expr_get_id (expr_id);
283 std::map<isl_id *, tree>::iterator res;
284 res = ip.find (tmp_isl_id);
285 isl_id_free (tmp_isl_id);
286 gcc_assert (res != ip.end () &&
287 "Could not map isl_id to tree expression");
288 isl_ast_expr_free (expr_id);
289 tree t = res->second;
290 tree *val = region->parameter_rename_map->get(t);
291
292 if (!val)
293 val = &t;
294 return fold_convert (type, *val);
295 }
296
297 /* Converts an isl_ast_expr_int expression E to a GCC expression tree of
298 type TYPE. */
299
300 tree
301 translate_isl_ast_to_gimple::
302 gcc_expression_from_isl_expr_int (tree type, __isl_take isl_ast_expr *expr)
303 {
304 gcc_assert (isl_ast_expr_get_type (expr) == isl_ast_expr_int);
305 isl_val *val = isl_ast_expr_get_val (expr);
306 mpz_t val_mpz_t;
307 mpz_init (val_mpz_t);
308 tree res;
309 if (isl_val_get_num_gmp (val, val_mpz_t) == -1)
310 res = NULL_TREE;
311 else
312 res = gmp_cst_to_tree (type, val_mpz_t);
313 isl_val_free (val);
314 isl_ast_expr_free (expr);
315 mpz_clear (val_mpz_t);
316 return res;
317 }
318
319 /* Converts a binary isl_ast_expr_op expression E to a GCC expression tree of
320 type TYPE. */
321
322 tree
323 translate_isl_ast_to_gimple::
324 binary_op_to_tree (tree type, __isl_take isl_ast_expr *expr, ivs_params &ip)
325 {
326 isl_ast_expr *arg_expr = isl_ast_expr_get_op_arg (expr, 0);
327 tree tree_lhs_expr = gcc_expression_from_isl_expression (type, arg_expr, ip);
328 arg_expr = isl_ast_expr_get_op_arg (expr, 1);
329 tree tree_rhs_expr = gcc_expression_from_isl_expression (type, arg_expr, ip);
330 enum isl_ast_op_type expr_type = isl_ast_expr_get_op_type (expr);
331 isl_ast_expr_free (expr);
332 switch (expr_type)
333 {
334 case isl_ast_op_add:
335 return fold_build2 (PLUS_EXPR, type, tree_lhs_expr, tree_rhs_expr);
336
337 case isl_ast_op_sub:
338 return fold_build2 (MINUS_EXPR, type, tree_lhs_expr, tree_rhs_expr);
339
340 case isl_ast_op_mul:
341 return fold_build2 (MULT_EXPR, type, tree_lhs_expr, tree_rhs_expr);
342
343 case isl_ast_op_div:
344 return fold_build2 (EXACT_DIV_EXPR, type, tree_lhs_expr, tree_rhs_expr);
345
346 case isl_ast_op_pdiv_q:
347 return fold_build2 (TRUNC_DIV_EXPR, type, tree_lhs_expr, tree_rhs_expr);
348
349 case isl_ast_op_pdiv_r:
350 return fold_build2 (TRUNC_MOD_EXPR, type, tree_lhs_expr, tree_rhs_expr);
351
352 case isl_ast_op_fdiv_q:
353 return fold_build2 (FLOOR_DIV_EXPR, type, tree_lhs_expr, tree_rhs_expr);
354
355 case isl_ast_op_and:
356 return fold_build2 (TRUTH_ANDIF_EXPR, type,
357 tree_lhs_expr, tree_rhs_expr);
358
359 case isl_ast_op_or:
360 return fold_build2 (TRUTH_ORIF_EXPR, type, tree_lhs_expr, tree_rhs_expr);
361
362 case isl_ast_op_eq:
363 return fold_build2 (EQ_EXPR, type, tree_lhs_expr, tree_rhs_expr);
364
365 case isl_ast_op_le:
366 return fold_build2 (LE_EXPR, type, tree_lhs_expr, tree_rhs_expr);
367
368 case isl_ast_op_lt:
369 return fold_build2 (LT_EXPR, type, tree_lhs_expr, tree_rhs_expr);
370
371 case isl_ast_op_ge:
372 return fold_build2 (GE_EXPR, type, tree_lhs_expr, tree_rhs_expr);
373
374 case isl_ast_op_gt:
375 return fold_build2 (GT_EXPR, type, tree_lhs_expr, tree_rhs_expr);
376
377 default:
378 gcc_unreachable ();
379 }
380 }
381
382 /* Converts a ternary isl_ast_expr_op expression E to a GCC expression tree of
383 type TYPE. */
384
385 tree
386 translate_isl_ast_to_gimple::
387 ternary_op_to_tree (tree type, __isl_take isl_ast_expr *expr, ivs_params &ip)
388 {
389 gcc_assert (isl_ast_expr_get_op_type (expr) == isl_ast_op_minus);
390 isl_ast_expr *arg_expr = isl_ast_expr_get_op_arg (expr, 0);
391 tree tree_first_expr
392 = gcc_expression_from_isl_expression (type, arg_expr, ip);
393 arg_expr = isl_ast_expr_get_op_arg (expr, 1);
394 tree tree_second_expr
395 = gcc_expression_from_isl_expression (type, arg_expr, ip);
396 arg_expr = isl_ast_expr_get_op_arg (expr, 2);
397 tree tree_third_expr
398 = gcc_expression_from_isl_expression (type, arg_expr, ip);
399 isl_ast_expr_free (expr);
400 return fold_build3 (COND_EXPR, type, tree_first_expr,
401 tree_second_expr, tree_third_expr);
402 }
403
404 /* Converts a unary isl_ast_expr_op expression E to a GCC expression tree of
405 type TYPE. */
406
407 tree
408 translate_isl_ast_to_gimple::
409 unary_op_to_tree (tree type, __isl_take isl_ast_expr *expr, ivs_params &ip)
410 {
411 gcc_assert (isl_ast_expr_get_op_type (expr) == isl_ast_op_minus);
412 isl_ast_expr *arg_expr = isl_ast_expr_get_op_arg (expr, 0);
413 tree tree_expr = gcc_expression_from_isl_expression (type, arg_expr, ip);
414 isl_ast_expr_free (expr);
415 return fold_build1 (NEGATE_EXPR, type, tree_expr);
416 }
417
418 /* Converts an isl_ast_expr_op expression E with unknown number of arguments
419 to a GCC expression tree of type TYPE. */
420
421 tree
422 translate_isl_ast_to_gimple::
423 nary_op_to_tree (tree type, __isl_take isl_ast_expr *expr, ivs_params &ip)
424 {
425 enum tree_code op_code;
426 switch (isl_ast_expr_get_op_type (expr))
427 {
428 case isl_ast_op_max:
429 op_code = MAX_EXPR;
430 break;
431
432 case isl_ast_op_min:
433 op_code = MIN_EXPR;
434 break;
435
436 default:
437 gcc_unreachable ();
438 }
439 isl_ast_expr *arg_expr = isl_ast_expr_get_op_arg (expr, 0);
440 tree res = gcc_expression_from_isl_expression (type, arg_expr, ip);
441 int i;
442 for (i = 1; i < isl_ast_expr_get_op_n_arg (expr); i++)
443 {
444 arg_expr = isl_ast_expr_get_op_arg (expr, i);
445 tree t = gcc_expression_from_isl_expression (type, arg_expr, ip);
446 res = fold_build2 (op_code, type, res, t);
447 }
448 isl_ast_expr_free (expr);
449 return res;
450 }
451
452 /* Converts an isl_ast_expr_op expression E to a GCC expression tree of
453 type TYPE. */
454
455 tree
456 translate_isl_ast_to_gimple::
457 gcc_expression_from_isl_expr_op (tree type, __isl_take isl_ast_expr *expr,
458 ivs_params &ip)
459 {
460 gcc_assert (isl_ast_expr_get_type (expr) == isl_ast_expr_op);
461 switch (isl_ast_expr_get_op_type (expr))
462 {
463 /* These isl ast expressions are not supported yet. */
464 case isl_ast_op_error:
465 case isl_ast_op_call:
466 case isl_ast_op_and_then:
467 case isl_ast_op_or_else:
468 case isl_ast_op_select:
469 gcc_unreachable ();
470
471 case isl_ast_op_max:
472 case isl_ast_op_min:
473 return nary_op_to_tree (type, expr, ip);
474
475 case isl_ast_op_add:
476 case isl_ast_op_sub:
477 case isl_ast_op_mul:
478 case isl_ast_op_div:
479 case isl_ast_op_pdiv_q:
480 case isl_ast_op_pdiv_r:
481 case isl_ast_op_fdiv_q:
482 case isl_ast_op_and:
483 case isl_ast_op_or:
484 case isl_ast_op_eq:
485 case isl_ast_op_le:
486 case isl_ast_op_lt:
487 case isl_ast_op_ge:
488 case isl_ast_op_gt:
489 return binary_op_to_tree (type, expr, ip);
490
491 case isl_ast_op_minus:
492 return unary_op_to_tree (type, expr, ip);
493
494 case isl_ast_op_cond:
495 return ternary_op_to_tree (type, expr, ip);
496
497 default:
498 gcc_unreachable ();
499 }
500
501 return NULL_TREE;
502 }
503
504 /* Converts an ISL AST expression E back to a GCC expression tree of
505 type TYPE. */
506
507 tree
508 translate_isl_ast_to_gimple::
509 gcc_expression_from_isl_expression (tree type, __isl_take isl_ast_expr *expr,
510 ivs_params &ip)
511 {
512 switch (isl_ast_expr_get_type (expr))
513 {
514 case isl_ast_expr_id:
515 return gcc_expression_from_isl_ast_expr_id (type, expr, ip);
516
517 case isl_ast_expr_int:
518 return gcc_expression_from_isl_expr_int (type, expr);
519
520 case isl_ast_expr_op:
521 return gcc_expression_from_isl_expr_op (type, expr, ip);
522
523 default:
524 gcc_unreachable ();
525 }
526
527 return NULL_TREE;
528 }
529
530 /* Creates a new LOOP corresponding to isl_ast_node_for. Inserts an
531 induction variable for the new LOOP. New LOOP is attached to CFG
532 starting at ENTRY_EDGE. LOOP is inserted into the loop tree and
533 becomes the child loop of the OUTER_LOOP. NEWIVS_INDEX binds
534 ISL's scattering name to the induction variable created for the
535 loop of STMT. The new induction variable is inserted in the NEWIVS
536 vector and is of type TYPE. */
537
538 struct loop *
539 translate_isl_ast_to_gimple::
540 graphite_create_new_loop (edge entry_edge, __isl_keep isl_ast_node *node_for,
541 loop_p outer, tree type, tree lb, tree ub,
542 ivs_params &ip)
543 {
544 isl_ast_expr *for_inc = isl_ast_node_for_get_inc (node_for);
545 tree stride = gcc_expression_from_isl_expression (type, for_inc, ip);
546 tree ivvar = create_tmp_var (type, "graphite_IV");
547 tree iv, iv_after_increment;
548 loop_p loop = create_empty_loop_on_edge
549 (entry_edge, lb, stride, ub, ivvar, &iv, &iv_after_increment,
550 outer ? outer : entry_edge->src->loop_father);
551
552 isl_ast_expr *for_iterator = isl_ast_node_for_get_iterator (node_for);
553 isl_id *id = isl_ast_expr_get_id (for_iterator);
554 std::map<isl_id *, tree>::iterator res;
555 res = ip.find (id);
556 if (ip.count (id))
557 isl_id_free (res->first);
558 ip[id] = iv;
559 isl_ast_expr_free (for_iterator);
560 return loop;
561 }
562
563 /* Create the loop for a isl_ast_node_for.
564
565 - NEXT_E is the edge where new generated code should be attached. */
566
567 edge
568 translate_isl_ast_to_gimple::
569 translate_isl_ast_for_loop (loop_p context_loop,
570 __isl_keep isl_ast_node *node_for, edge next_e,
571 tree type, tree lb, tree ub,
572 ivs_params &ip)
573 {
574 gcc_assert (isl_ast_node_get_type (node_for) == isl_ast_node_for);
575 struct loop *loop = graphite_create_new_loop (next_e, node_for, context_loop,
576 type, lb, ub, ip);
577 edge last_e = single_exit (loop);
578 edge to_body = single_succ_edge (loop->header);
579 basic_block after = to_body->dest;
580
581 /* Create a basic block for loop close phi nodes. */
582 last_e = single_succ_edge (split_edge (last_e));
583
584 /* Translate the body of the loop. */
585 isl_ast_node *for_body = isl_ast_node_for_get_body (node_for);
586 next_e = translate_isl_ast (loop, for_body, to_body, ip);
587 isl_ast_node_free (for_body);
588 redirect_edge_succ_nodup (next_e, after);
589 set_immediate_dominator (CDI_DOMINATORS, next_e->dest, next_e->src);
590
591 if (flag_loop_parallelize_all)
592 {
593 isl_id *id = isl_ast_node_get_annotation (node_for);
594 gcc_assert (id);
595 ast_build_info *for_info = (ast_build_info *) isl_id_get_user (id);
596 loop->can_be_parallel = for_info->is_parallelizable;
597 free (for_info);
598 isl_id_free (id);
599 }
600
601 return last_e;
602 }
603
604 /* We use this function to get the upper bound because of the form,
605 which is used by isl to represent loops:
606
607 for (iterator = init; cond; iterator += inc)
608
609 {
610
611 ...
612
613 }
614
615 The loop condition is an arbitrary expression, which contains the
616 current loop iterator.
617
618 (e.g. iterator + 3 < B && C > iterator + A)
619
620 We have to know the upper bound of the iterator to generate a loop
621 in Gimple form. It can be obtained from the special representation
622 of the loop condition, which is generated by isl,
623 if the ast_build_atomic_upper_bound option is set. In this case,
624 isl generates a loop condition that consists of the current loop
625 iterator, + an operator (< or <=) and an expression not involving
626 the iterator, which is processed and returned by this function.
627
628 (e.g iterator <= upper-bound-expression-without-iterator) */
629
630 static __isl_give isl_ast_expr *
631 get_upper_bound (__isl_keep isl_ast_node *node_for)
632 {
633 gcc_assert (isl_ast_node_get_type (node_for) == isl_ast_node_for);
634 isl_ast_expr *for_cond = isl_ast_node_for_get_cond (node_for);
635 gcc_assert (isl_ast_expr_get_type (for_cond) == isl_ast_expr_op);
636 isl_ast_expr *res;
637 switch (isl_ast_expr_get_op_type (for_cond))
638 {
639 case isl_ast_op_le:
640 res = isl_ast_expr_get_op_arg (for_cond, 1);
641 break;
642
643 case isl_ast_op_lt:
644 {
645 // (iterator < ub) => (iterator <= ub - 1)
646 isl_val *one =
647 isl_val_int_from_si (isl_ast_expr_get_ctx (for_cond), 1);
648 isl_ast_expr *ub = isl_ast_expr_get_op_arg (for_cond, 1);
649 res = isl_ast_expr_sub (ub, isl_ast_expr_from_val (one));
650 break;
651 }
652
653 default:
654 gcc_unreachable ();
655 }
656 isl_ast_expr_free (for_cond);
657 return res;
658 }
659
660 /* All loops generated by create_empty_loop_on_edge have the form of
661 a post-test loop:
662
663 do
664
665 {
666 body of the loop;
667 } while (lower bound < upper bound);
668
669 We create a new if region protecting the loop to be executed, if
670 the execution count is zero (lower bound > upper bound). */
671
672 edge
673 translate_isl_ast_to_gimple::
674 graphite_create_new_loop_guard (edge entry_edge,
675 __isl_keep isl_ast_node *node_for, tree *type,
676 tree *lb, tree *ub, ivs_params &ip)
677 {
678 gcc_assert (isl_ast_node_get_type (node_for) == isl_ast_node_for);
679 tree cond_expr;
680 edge exit_edge;
681
682 *type =
683 build_nonstandard_integer_type (graphite_expression_type_precision, 0);
684 isl_ast_expr *for_init = isl_ast_node_for_get_init (node_for);
685 *lb = gcc_expression_from_isl_expression (*type, for_init, ip);
686 isl_ast_expr *upper_bound = get_upper_bound (node_for);
687 *ub = gcc_expression_from_isl_expression (*type, upper_bound, ip);
688
689 /* When ub is simply a constant or a parameter, use lb <= ub. */
690 if (TREE_CODE (*ub) == INTEGER_CST || TREE_CODE (*ub) == SSA_NAME)
691 cond_expr = fold_build2 (LE_EXPR, boolean_type_node, *lb, *ub);
692 else
693 {
694 tree one = (POINTER_TYPE_P (*type)
695 ? convert_to_ptrofftype (integer_one_node)
696 : fold_convert (*type, integer_one_node));
697 /* Adding +1 and using LT_EXPR helps with loop latches that have a
698 loop iteration count of "PARAMETER - 1". For PARAMETER == 0 this
699 becomes 2^k-1 due to integer overflow, and the condition lb <= ub
700 is true, even if we do not want this. However lb < ub + 1 is false,
701 as expected. */
702 tree ub_one = fold_build2 (POINTER_TYPE_P (*type) ? POINTER_PLUS_EXPR
703 : PLUS_EXPR, *type, *ub, one);
704
705 cond_expr = fold_build2 (LT_EXPR, boolean_type_node, *lb, ub_one);
706 }
707
708 if (integer_onep (cond_expr))
709 exit_edge = entry_edge;
710 else
711 exit_edge = create_empty_if_region_on_edge (entry_edge, cond_expr);
712
713 return exit_edge;
714 }
715
716 /* Translates an isl_ast_node_for to Gimple. */
717
718 edge
719 translate_isl_ast_to_gimple::
720 translate_isl_ast_node_for (loop_p context_loop, __isl_keep isl_ast_node *node,
721 edge next_e, ivs_params &ip)
722 {
723 gcc_assert (isl_ast_node_get_type (node) == isl_ast_node_for);
724 tree type, lb, ub;
725 edge last_e = graphite_create_new_loop_guard (next_e, node, &type,
726 &lb, &ub, ip);
727
728 if (last_e == next_e)
729 /* There was no guard generated. */
730 return translate_isl_ast_for_loop (context_loop, node, last_e,
731 type, lb, ub, ip);
732
733 edge true_e = get_true_edge_from_guard_bb (next_e->dest);
734 translate_isl_ast_for_loop (context_loop, node, true_e, type, lb, ub, ip);
735 return last_e;
736 }
737
738 /* Inserts in iv_map a tuple (OLD_LOOP->num, NEW_NAME) for the induction
739 variables of the loops around GBB in SESE.
740
741 FIXME: Instead of using a vec<tree> that maps each loop id to a possible
742 chrec, we could consider using a map<int, tree> that maps loop ids to the
743 corresponding tree expressions. */
744
745 void
746 translate_isl_ast_to_gimple::
747 build_iv_mapping (vec<tree> iv_map, gimple_poly_bb_p gbb,
748 __isl_keep isl_ast_expr *user_expr, ivs_params &ip,
749 sese_l &region)
750 {
751 gcc_assert (isl_ast_expr_get_type (user_expr) == isl_ast_expr_op &&
752 isl_ast_expr_get_op_type (user_expr) == isl_ast_op_call);
753 int i;
754 isl_ast_expr *arg_expr;
755 for (i = 1; i < isl_ast_expr_get_op_n_arg (user_expr); i++)
756 {
757 arg_expr = isl_ast_expr_get_op_arg (user_expr, i);
758 tree type =
759 build_nonstandard_integer_type (graphite_expression_type_precision, 0);
760 tree t = gcc_expression_from_isl_expression (type, arg_expr, ip);
761 loop_p old_loop = gbb_loop_at_index (gbb, region, i - 1);
762 iv_map[old_loop->num] = t;
763 }
764 }
765
766 /* Translates an isl_ast_node_user to Gimple.
767
768 FIXME: We should remove iv_map.create (loop->num + 1), if it is possible. */
769
770 edge
771 translate_isl_ast_to_gimple::
772 translate_isl_ast_node_user (__isl_keep isl_ast_node *node,
773 edge next_e, ivs_params &ip)
774 {
775 gcc_assert (isl_ast_node_get_type (node) == isl_ast_node_user);
776 isl_ast_expr *user_expr = isl_ast_node_user_get_expr (node);
777 isl_ast_expr *name_expr = isl_ast_expr_get_op_arg (user_expr, 0);
778 gcc_assert (isl_ast_expr_get_type (name_expr) == isl_ast_expr_id);
779 isl_id *name_id = isl_ast_expr_get_id (name_expr);
780 poly_bb_p pbb = (poly_bb_p) isl_id_get_user (name_id);
781 gcc_assert (pbb);
782 gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
783 vec<tree> iv_map;
784 isl_ast_expr_free (name_expr);
785 isl_id_free (name_id);
786
787 gcc_assert (GBB_BB (gbb) != ENTRY_BLOCK_PTR_FOR_FN (cfun) &&
788 "The entry block should not even appear within a scop");
789
790 int nb_loops = number_of_loops (cfun);
791 iv_map.create (nb_loops);
792 iv_map.safe_grow_cleared (nb_loops);
793
794 build_iv_mapping (iv_map, gbb, user_expr, ip, pbb->scop->scop_info->region);
795 isl_ast_expr_free (user_expr);
796 next_e = copy_bb_and_scalar_dependences (GBB_BB (gbb),
797 pbb->scop->scop_info, next_e,
798 iv_map,
799 &graphite_regenerate_error);
800 iv_map.release ();
801 mark_virtual_operands_for_renaming (cfun);
802 update_ssa (TODO_update_ssa);
803 return next_e;
804 }
805
806 /* Translates an isl_ast_node_block to Gimple. */
807
808 edge
809 translate_isl_ast_to_gimple::
810 translate_isl_ast_node_block (loop_p context_loop,
811 __isl_keep isl_ast_node *node,
812 edge next_e, ivs_params &ip)
813 {
814 gcc_assert (isl_ast_node_get_type (node) == isl_ast_node_block);
815 isl_ast_node_list *node_list = isl_ast_node_block_get_children (node);
816 int i;
817 for (i = 0; i < isl_ast_node_list_n_ast_node (node_list); i++)
818 {
819 isl_ast_node *tmp_node = isl_ast_node_list_get_ast_node (node_list, i);
820 next_e = translate_isl_ast (context_loop, tmp_node, next_e, ip);
821 isl_ast_node_free (tmp_node);
822 }
823 isl_ast_node_list_free (node_list);
824 return next_e;
825 }
826
827 /* Creates a new if region corresponding to ISL's cond. */
828
829 edge
830 translate_isl_ast_to_gimple::
831 graphite_create_new_guard (edge entry_edge, __isl_take isl_ast_expr *if_cond,
832 ivs_params &ip)
833 {
834 tree type =
835 build_nonstandard_integer_type (graphite_expression_type_precision, 0);
836 tree cond_expr = gcc_expression_from_isl_expression (type, if_cond, ip);
837 edge exit_edge = create_empty_if_region_on_edge (entry_edge, cond_expr);
838 return exit_edge;
839 }
840
841 /* Translates an isl_ast_node_if to Gimple. */
842
843 edge
844 translate_isl_ast_to_gimple::
845 translate_isl_ast_node_if (loop_p context_loop,
846 __isl_keep isl_ast_node *node,
847 edge next_e, ivs_params &ip)
848 {
849 gcc_assert (isl_ast_node_get_type (node) == isl_ast_node_if);
850 isl_ast_expr *if_cond = isl_ast_node_if_get_cond (node);
851 edge last_e = graphite_create_new_guard (next_e, if_cond, ip);
852
853 edge true_e = get_true_edge_from_guard_bb (next_e->dest);
854 isl_ast_node *then_node = isl_ast_node_if_get_then (node);
855 translate_isl_ast (context_loop, then_node, true_e, ip);
856 isl_ast_node_free (then_node);
857
858 edge false_e = get_false_edge_from_guard_bb (next_e->dest);
859 isl_ast_node *else_node = isl_ast_node_if_get_else (node);
860 if (isl_ast_node_get_type (else_node) != isl_ast_node_error)
861 translate_isl_ast (context_loop, else_node, false_e, ip);
862 isl_ast_node_free (else_node);
863 return last_e;
864 }
865
866 /* Translates an ISL AST node NODE to GCC representation in the
867 context of a SESE. */
868
869 edge
870 translate_isl_ast_to_gimple::translate_isl_ast (loop_p context_loop,
871 __isl_keep isl_ast_node *node,
872 edge next_e, ivs_params &ip)
873 {
874 switch (isl_ast_node_get_type (node))
875 {
876 case isl_ast_node_error:
877 gcc_unreachable ();
878
879 case isl_ast_node_for:
880 return translate_isl_ast_node_for (context_loop, node,
881 next_e, ip);
882
883 case isl_ast_node_if:
884 return translate_isl_ast_node_if (context_loop, node,
885 next_e, ip);
886
887 case isl_ast_node_user:
888 return translate_isl_ast_node_user (node, next_e, ip);
889
890 case isl_ast_node_block:
891 return translate_isl_ast_node_block (context_loop, node,
892 next_e, ip);
893
894 default:
895 gcc_unreachable ();
896 }
897 }
898
899 /* Prints NODE to FILE. */
900
901 void
902 print_isl_ast_node (FILE *file, __isl_keep isl_ast_node *node,
903 __isl_keep isl_ctx *ctx)
904 {
905 isl_printer *prn = isl_printer_to_file (ctx, file);
906 prn = isl_printer_set_output_format (prn, ISL_FORMAT_C);
907 prn = isl_printer_print_ast_node (prn, node);
908 prn = isl_printer_print_str (prn, "\n");
909 isl_printer_free (prn);
910 }
911
912 /* Add ISL's parameter identifiers and corresponding.trees to ivs_params */
913
914 static void
915 add_parameters_to_ivs_params (scop_p scop, ivs_params &ip)
916 {
917 sese_info_p region = scop->scop_info;
918 unsigned nb_parameters = isl_set_dim (scop->param_context, isl_dim_param);
919 gcc_assert (nb_parameters == SESE_PARAMS (region).length ());
920 unsigned i;
921 for (i = 0; i < nb_parameters; i++)
922 {
923 isl_id *tmp_id = isl_set_get_dim_id (scop->param_context,
924 isl_dim_param, i);
925 ip[tmp_id] = SESE_PARAMS (region)[i];
926 }
927 }
928
929
930 /* Generates a build, which specifies the constraints on the parameters. */
931
932 static __isl_give isl_ast_build *
933 generate_isl_context (scop_p scop)
934 {
935 isl_set *context_isl = isl_set_params (isl_set_copy (scop->param_context));
936 return isl_ast_build_from_context (context_isl);
937 }
938
939 /* Get the maximal number of schedule dimensions in the scop SCOP. */
940
941 static
942 int get_max_schedule_dimensions (scop_p scop)
943 {
944 int i;
945 poly_bb_p pbb;
946 int schedule_dims = 0;
947
948 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
949 {
950 int pbb_schedule_dims = isl_map_dim (pbb->transformed, isl_dim_out);
951 if (pbb_schedule_dims > schedule_dims)
952 schedule_dims = pbb_schedule_dims;
953 }
954
955 return schedule_dims;
956 }
957
958 /* Extend the schedule to NB_SCHEDULE_DIMS schedule dimensions.
959
960 For schedules with different dimensionality, the isl AST generator can not
961 define an order and will just randomly choose an order. The solution to this
962 problem is to extend all schedules to the maximal number of schedule
963 dimensions (using '0's for the remaining values). */
964
965 static __isl_give isl_map *
966 extend_schedule (__isl_take isl_map *schedule, int nb_schedule_dims)
967 {
968 int tmp_dims = isl_map_dim (schedule, isl_dim_out);
969 schedule =
970 isl_map_add_dims (schedule, isl_dim_out, nb_schedule_dims - tmp_dims);
971 isl_val *zero =
972 isl_val_int_from_si (isl_map_get_ctx (schedule), 0);
973 int i;
974 for (i = tmp_dims; i < nb_schedule_dims; i++)
975 {
976 schedule =
977 isl_map_fix_val (schedule, isl_dim_out, i, isl_val_copy (zero));
978 }
979 isl_val_free (zero);
980 return schedule;
981 }
982
983 /* Generates a schedule, which specifies an order used to
984 visit elements in a domain. */
985
986 static __isl_give isl_union_map *
987 generate_isl_schedule (scop_p scop)
988 {
989 int nb_schedule_dims = get_max_schedule_dimensions (scop);
990 int i;
991 poly_bb_p pbb;
992 isl_union_map *schedule_isl =
993 isl_union_map_empty (isl_set_get_space (scop->param_context));
994
995 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
996 {
997 /* Dead code elimination: when the domain of a PBB is empty,
998 don't generate code for the PBB. */
999 if (isl_set_is_empty (pbb->domain))
1000 continue;
1001
1002 isl_map *bb_schedule = isl_map_copy (pbb->transformed);
1003 bb_schedule = isl_map_intersect_domain (bb_schedule,
1004 isl_set_copy (pbb->domain));
1005 bb_schedule = extend_schedule (bb_schedule, nb_schedule_dims);
1006 schedule_isl =
1007 isl_union_map_union (schedule_isl,
1008 isl_union_map_from_map (bb_schedule));
1009 }
1010 return schedule_isl;
1011 }
1012
1013 /* This method is executed before the construction of a for node. */
1014 static __isl_give isl_id *
1015 ast_build_before_for (__isl_keep isl_ast_build *build, void *user)
1016 {
1017 isl_union_map *dependences = (isl_union_map *) user;
1018 ast_build_info *for_info = XNEW (struct ast_build_info);
1019 isl_union_map *schedule = isl_ast_build_get_schedule (build);
1020 isl_space *schedule_space = isl_ast_build_get_schedule_space (build);
1021 int dimension = isl_space_dim (schedule_space, isl_dim_out);
1022 for_info->is_parallelizable =
1023 !carries_deps (schedule, dependences, dimension);
1024 isl_union_map_free (schedule);
1025 isl_space_free (schedule_space);
1026 isl_id *id = isl_id_alloc (isl_ast_build_get_ctx (build), "", for_info);
1027 return id;
1028 }
1029
1030 /* Set the separate option for all dimensions.
1031 This helps to reduce control overhead. */
1032
1033 static __isl_give isl_ast_build *
1034 set_options (__isl_take isl_ast_build *control,
1035 __isl_keep isl_union_map *schedule)
1036 {
1037 isl_ctx *ctx = isl_union_map_get_ctx (schedule);
1038 isl_space *range_space = isl_space_set_alloc (ctx, 0, 1);
1039 range_space =
1040 isl_space_set_tuple_name (range_space, isl_dim_set, "separate");
1041 isl_union_set *range =
1042 isl_union_set_from_set (isl_set_universe (range_space));
1043 isl_union_set *domain = isl_union_map_range (isl_union_map_copy (schedule));
1044 domain = isl_union_set_universe (domain);
1045 isl_union_map *options = isl_union_map_from_domain_and_range (domain, range);
1046 return isl_ast_build_set_options (control, options);
1047 }
1048
1049 static __isl_give isl_ast_node *
1050 scop_to_isl_ast (scop_p scop, ivs_params &ip)
1051 {
1052 /* Generate loop upper bounds that consist of the current loop iterator,
1053 an operator (< or <=) and an expression not involving the iterator.
1054 If this option is not set, then the current loop iterator may appear several
1055 times in the upper bound. See the isl manual for more details. */
1056 isl_options_set_ast_build_atomic_upper_bound (scop->isl_context, true);
1057
1058 add_parameters_to_ivs_params (scop, ip);
1059 isl_union_map *schedule_isl = generate_isl_schedule (scop);
1060 isl_ast_build *context_isl = generate_isl_context (scop);
1061 context_isl = set_options (context_isl, schedule_isl);
1062 isl_union_map *dependences = NULL;
1063 if (flag_loop_parallelize_all)
1064 {
1065 dependences = scop_get_dependences (scop);
1066 context_isl =
1067 isl_ast_build_set_before_each_for (context_isl, ast_build_before_for,
1068 dependences);
1069 }
1070 isl_ast_node *ast_isl = isl_ast_build_ast_from_schedule (context_isl,
1071 schedule_isl);
1072 if(dependences)
1073 isl_union_map_free (dependences);
1074 isl_ast_build_free (context_isl);
1075 return ast_isl;
1076 }
1077
1078 /* Copy def from sese REGION to the newly created TO_REGION. TR is defined by
1079 DEF_STMT. GSI points to entry basic block of the TO_REGION. */
1080
1081 static void
1082 copy_def (tree tr, gimple *def_stmt, sese_info_p region, sese_info_p to_region,
1083 gimple_stmt_iterator *gsi)
1084 {
1085 if (!defined_in_sese_p (tr, region->region))
1086 return;
1087
1088 ssa_op_iter iter;
1089 use_operand_p use_p;
1090 FOR_EACH_SSA_USE_OPERAND (use_p, def_stmt, iter, SSA_OP_USE)
1091 {
1092 tree use_tr = USE_FROM_PTR (use_p);
1093
1094 /* Do not copy parameters that have been generated in the header of the
1095 scop. */
1096 if (region->parameter_rename_map->get(use_tr))
1097 continue;
1098
1099 gimple *def_of_use = SSA_NAME_DEF_STMT (use_tr);
1100 if (!def_of_use)
1101 continue;
1102
1103 copy_def (use_tr, def_of_use, region, to_region, gsi);
1104 }
1105
1106 gimple *copy = gimple_copy (def_stmt);
1107 gsi_insert_after (gsi, copy, GSI_NEW_STMT);
1108
1109 /* Create new names for all the definitions created by COPY and
1110 add replacement mappings for each new name. */
1111 def_operand_p def_p;
1112 ssa_op_iter op_iter;
1113 FOR_EACH_SSA_DEF_OPERAND (def_p, copy, op_iter, SSA_OP_ALL_DEFS)
1114 {
1115 tree old_name = DEF_FROM_PTR (def_p);
1116 tree new_name = create_new_def_for (old_name, copy, def_p);
1117 region->parameter_rename_map->put(old_name, new_name);
1118 }
1119
1120 update_stmt (copy);
1121 }
1122
1123 static void
1124 copy_internal_parameters (sese_info_p region, sese_info_p to_region)
1125 {
1126 /* For all the parameters which definitino is in the if_region->false_region,
1127 insert code on true_region (if_region->true_region->entry). */
1128
1129 int i;
1130 tree tr;
1131 gimple_stmt_iterator gsi = gsi_start_bb(to_region->region.entry->dest);
1132
1133 FOR_EACH_VEC_ELT (region->params, i, tr)
1134 {
1135 // If def is not in region.
1136 gimple *def_stmt = SSA_NAME_DEF_STMT (tr);
1137 if (def_stmt)
1138 copy_def (tr, def_stmt, region, to_region, &gsi);
1139 }
1140 }
1141
1142 /* GIMPLE Loop Generator: generates loops from STMT in GIMPLE form for
1143 the given SCOP. Return true if code generation succeeded.
1144
1145 FIXME: This is not yet a full implementation of the code generator
1146 with ISL ASTs. Generation of GIMPLE code has to be completed. */
1147
1148 bool
1149 graphite_regenerate_ast_isl (scop_p scop)
1150 {
1151 loop_p context_loop;
1152 sese_info_p region = scop->scop_info;
1153 ifsese if_region = NULL;
1154 isl_ast_node *root_node;
1155 ivs_params ip;
1156
1157 timevar_push (TV_GRAPHITE_CODE_GEN);
1158 graphite_regenerate_error = false;
1159 root_node = scop_to_isl_ast (scop, ip);
1160
1161 if (dump_file && (dump_flags & TDF_DETAILS))
1162 {
1163 fprintf (dump_file, "\nISL AST generated by ISL: \n");
1164 print_isl_ast_node (dump_file, root_node, scop->isl_context);
1165 fprintf (dump_file, "\n");
1166 }
1167
1168 recompute_all_dominators ();
1169 graphite_verify ();
1170
1171 if_region = move_sese_in_condition (region);
1172 sese_insert_phis_for_liveouts (region,
1173 if_region->region->region.exit->src,
1174 if_region->false_region->region.exit,
1175 if_region->true_region->region.exit);
1176 recompute_all_dominators ();
1177 graphite_verify ();
1178
1179 context_loop = region->region.entry->src->loop_father;
1180
1181 /* Copy all the parameters which are defined in the region. */
1182 copy_internal_parameters(if_region->false_region, if_region->true_region);
1183
1184 translate_isl_ast_to_gimple t(region);
1185 edge e = single_succ_edge (if_region->true_region->region.entry->dest);
1186 split_edge (e);
1187 t.translate_isl_ast (context_loop, root_node, e, ip);
1188
1189 mark_virtual_operands_for_renaming (cfun);
1190 update_ssa (TODO_update_ssa);
1191
1192 graphite_verify ();
1193 scev_reset ();
1194 recompute_all_dominators ();
1195 graphite_verify ();
1196
1197 if (graphite_regenerate_error)
1198 set_ifsese_condition (if_region, integer_zero_node);
1199
1200 free (if_region->true_region);
1201 free (if_region->region);
1202 free (if_region);
1203
1204 ivs_params_clear (ip);
1205 isl_ast_node_free (root_node);
1206 timevar_pop (TV_GRAPHITE_CODE_GEN);
1207
1208 if (dump_file && (dump_flags & TDF_DETAILS))
1209 {
1210 loop_p loop;
1211 int num_no_dependency = 0;
1212
1213 FOR_EACH_LOOP (loop, 0)
1214 if (loop->can_be_parallel)
1215 num_no_dependency++;
1216
1217 fprintf (dump_file, "\n%d loops carried no dependency.\n",
1218 num_no_dependency);
1219 }
1220
1221 return !graphite_regenerate_error;
1222 }
1223 #endif /* HAVE_isl */