1 /* Translation of ISL AST to Gimple.
2 Copyright (C) 2014 Free Software Foundation, Inc.
3 Contributed by Roman Gareev <gareevroman@gmail.com>.
5 This file is part of GCC.
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)
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.
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/>. */
26 #include <isl/union_map.h>
27 #include <isl/ast_build.h>
28 #if defined(__cplusplus)
31 #include <isl/val_gmp.h>
32 #if defined(__cplusplus)
38 #include "coretypes.h"
40 #include "basic-block.h"
41 #include "tree-ssa-alias.h"
42 #include "internal-fn.h"
43 #include "gimple-expr.h"
46 #include "gimple-iterator.h"
47 #include "tree-ssa-loop.h"
48 #include "tree-pass.h"
50 #include "tree-data-ref.h"
52 #include "tree-ssa-loop-manip.h"
53 #include "tree-scalar-evolution.h"
57 #include "graphite-poly.h"
58 #include "graphite-isl-ast-to-gimple.h"
60 /* This flag is set when an error occurred during the translation of
63 static bool graphite_regenerate_error
;
65 /* We always use signed 128, until isl is able to give information about
68 static tree
*graphite_expression_size_type
= &int128_integer_type_node
;
70 /* Converts a GMP constant VAL to a tree and returns it. */
73 gmp_cst_to_tree (tree type
, mpz_t val
)
75 tree t
= type
? type
: integer_type_node
;
80 wide_int wi
= wi::from_mpz (t
, tmp
, true);
83 return wide_int_to_tree (t
, wi
);
86 /* Verifies properties that GRAPHITE should maintain during translation. */
89 graphite_verify (void)
91 #ifdef ENABLE_CHECKING
92 verify_loop_structure ();
93 verify_loop_closed_ssa (true);
97 /* IVS_PARAMS maps ISL's scattering and parameter identifiers
98 to corresponding trees. */
100 typedef std::map
<isl_id
*, tree
> ivs_params
;
102 /* Free all memory allocated for ISL's identifiers. */
104 void ivs_params_clear (ivs_params
&ip
)
106 std::map
<isl_id
*, tree
>::iterator it
;
107 for (it
= ip
.begin ();
108 it
!= ip
.end (); it
++)
110 isl_id_free (it
->first
);
115 gcc_expression_from_isl_expression (tree type
, __isl_take isl_ast_expr
*,
118 /* Return the tree variable that corresponds to the given isl ast identifier
119 expression (an isl_ast_expr of type isl_ast_expr_id). */
122 gcc_expression_from_isl_ast_expr_id (__isl_keep isl_ast_expr
*expr_id
,
125 gcc_assert (isl_ast_expr_get_type (expr_id
) == isl_ast_expr_id
);
126 isl_id
*tmp_isl_id
= isl_ast_expr_get_id (expr_id
);
127 std::map
<isl_id
*, tree
>::iterator res
;
128 res
= ip
.find (tmp_isl_id
);
129 isl_id_free (tmp_isl_id
);
130 gcc_assert (res
!= ip
.end () &&
131 "Could not map isl_id to tree expression");
132 isl_ast_expr_free (expr_id
);
136 /* Converts an isl_ast_expr_int expression E to a GCC expression tree of
140 gcc_expression_from_isl_expr_int (tree type
, __isl_take isl_ast_expr
*expr
)
142 gcc_assert (isl_ast_expr_get_type (expr
) == isl_ast_expr_int
);
143 isl_val
*val
= isl_ast_expr_get_val (expr
);
145 mpz_init (val_mpz_t
);
147 if (isl_val_get_num_gmp (val
, val_mpz_t
) == -1)
150 res
= gmp_cst_to_tree (type
, val_mpz_t
);
152 isl_ast_expr_free (expr
);
153 mpz_clear (val_mpz_t
);
157 /* Converts a binary isl_ast_expr_op expression E to a GCC expression tree of
161 binary_op_to_tree (tree type
, __isl_take isl_ast_expr
*expr
, ivs_params
&ip
)
163 isl_ast_expr
*arg_expr
= isl_ast_expr_get_op_arg (expr
, 0);
164 tree tree_lhs_expr
= gcc_expression_from_isl_expression (type
, arg_expr
, ip
);
165 arg_expr
= isl_ast_expr_get_op_arg (expr
, 1);
166 tree tree_rhs_expr
= gcc_expression_from_isl_expression (type
, arg_expr
, ip
);
167 enum isl_ast_op_type expr_type
= isl_ast_expr_get_op_type (expr
);
168 isl_ast_expr_free (expr
);
172 return fold_build2 (PLUS_EXPR
, type
, tree_lhs_expr
, tree_rhs_expr
);
175 return fold_build2 (MINUS_EXPR
, type
, tree_lhs_expr
, tree_rhs_expr
);
178 return fold_build2 (MULT_EXPR
, type
, tree_lhs_expr
, tree_rhs_expr
);
181 return fold_build2 (EXACT_DIV_EXPR
, type
, tree_lhs_expr
, tree_rhs_expr
);
183 case isl_ast_op_fdiv_q
:
184 return fold_build2 (FLOOR_DIV_EXPR
, type
, tree_lhs_expr
, tree_rhs_expr
);
187 return fold_build2 (TRUTH_ANDIF_EXPR
, type
,
188 tree_lhs_expr
, tree_rhs_expr
);
191 return fold_build2 (TRUTH_ORIF_EXPR
, type
, tree_lhs_expr
, tree_rhs_expr
);
194 return fold_build2 (EQ_EXPR
, type
, tree_lhs_expr
, tree_rhs_expr
);
197 return fold_build2 (LE_EXPR
, type
, tree_lhs_expr
, tree_rhs_expr
);
200 return fold_build2 (LT_EXPR
, type
, tree_lhs_expr
, tree_rhs_expr
);
203 return fold_build2 (GE_EXPR
, type
, tree_lhs_expr
, tree_rhs_expr
);
206 return fold_build2 (GT_EXPR
, type
, tree_lhs_expr
, tree_rhs_expr
);
213 /* Converts a ternary isl_ast_expr_op expression E to a GCC expression tree of
217 ternary_op_to_tree (tree type
, __isl_take isl_ast_expr
*expr
, ivs_params
&ip
)
219 gcc_assert (isl_ast_expr_get_op_type (expr
) == isl_ast_op_minus
);
220 isl_ast_expr
*arg_expr
= isl_ast_expr_get_op_arg (expr
, 0);
222 = gcc_expression_from_isl_expression (type
, arg_expr
, ip
);
223 arg_expr
= isl_ast_expr_get_op_arg (expr
, 1);
224 tree tree_second_expr
225 = gcc_expression_from_isl_expression (type
, arg_expr
, ip
);
226 arg_expr
= isl_ast_expr_get_op_arg (expr
, 2);
228 = gcc_expression_from_isl_expression (type
, arg_expr
, ip
);
229 isl_ast_expr_free (expr
);
230 return fold_build3 (COND_EXPR
, type
, tree_first_expr
,
231 tree_second_expr
, tree_third_expr
);
234 /* Converts a unary isl_ast_expr_op expression E to a GCC expression tree of
238 unary_op_to_tree (tree type
, __isl_take isl_ast_expr
*expr
, ivs_params
&ip
)
240 gcc_assert (isl_ast_expr_get_op_type (expr
) == isl_ast_op_minus
);
241 isl_ast_expr
*arg_expr
= isl_ast_expr_get_op_arg (expr
, 0);
242 tree tree_expr
= gcc_expression_from_isl_expression (type
, arg_expr
, ip
);
243 isl_ast_expr_free (expr
);
244 return fold_build1 (NEGATE_EXPR
, type
, tree_expr
);
247 /* Converts an isl_ast_expr_op expression E with unknown number of arguments
248 to a GCC expression tree of type TYPE. */
251 nary_op_to_tree (tree type
, __isl_take isl_ast_expr
*expr
, ivs_params
&ip
)
253 enum tree_code op_code
;
254 switch (isl_ast_expr_get_op_type (expr
))
267 isl_ast_expr
*arg_expr
= isl_ast_expr_get_op_arg (expr
, 0);
268 tree res
= gcc_expression_from_isl_expression (type
, arg_expr
, ip
);
270 for (i
= 1; i
< isl_ast_expr_get_op_n_arg (expr
); i
++)
272 arg_expr
= isl_ast_expr_get_op_arg (expr
, i
);
273 tree t
= gcc_expression_from_isl_expression (type
, arg_expr
, ip
);
274 res
= fold_build2 (op_code
, type
, res
, t
);
276 isl_ast_expr_free (expr
);
281 /* Converts an isl_ast_expr_op expression E to a GCC expression tree of
285 gcc_expression_from_isl_expr_op (tree type
, __isl_take isl_ast_expr
*expr
,
288 gcc_assert (isl_ast_expr_get_type (expr
) == isl_ast_expr_op
);
289 switch (isl_ast_expr_get_op_type (expr
))
291 /* These isl ast expressions are not supported yet. */
292 case isl_ast_op_error
:
293 case isl_ast_op_call
:
294 case isl_ast_op_and_then
:
295 case isl_ast_op_or_else
:
296 case isl_ast_op_pdiv_q
:
297 case isl_ast_op_pdiv_r
:
298 case isl_ast_op_select
:
303 return nary_op_to_tree (type
, expr
, ip
);
309 case isl_ast_op_fdiv_q
:
317 return binary_op_to_tree (type
, expr
, ip
);
319 case isl_ast_op_minus
:
320 return unary_op_to_tree (type
, expr
, ip
);
322 case isl_ast_op_cond
:
323 return ternary_op_to_tree (type
, expr
, ip
);
332 /* Converts an ISL AST expression E back to a GCC expression tree of
336 gcc_expression_from_isl_expression (tree type
, __isl_take isl_ast_expr
*expr
,
339 switch (isl_ast_expr_get_type (expr
))
341 case isl_ast_expr_id
:
342 return gcc_expression_from_isl_ast_expr_id (expr
, ip
);
344 case isl_ast_expr_int
:
345 return gcc_expression_from_isl_expr_int (type
, expr
);
347 case isl_ast_expr_op
:
348 return gcc_expression_from_isl_expr_op (type
, expr
, ip
);
357 /* Creates a new LOOP corresponding to isl_ast_node_for. Inserts an
358 induction variable for the new LOOP. New LOOP is attached to CFG
359 starting at ENTRY_EDGE. LOOP is inserted into the loop tree and
360 becomes the child loop of the OUTER_LOOP. NEWIVS_INDEX binds
361 ISL's scattering name to the induction variable created for the
362 loop of STMT. The new induction variable is inserted in the NEWIVS
363 vector and is of type TYPE. */
366 graphite_create_new_loop (edge entry_edge
, __isl_keep isl_ast_node
*node_for
,
367 loop_p outer
, tree type
, tree lb
, tree ub
,
370 isl_ast_expr
*for_inc
= isl_ast_node_for_get_inc (node_for
);
371 tree stride
= gcc_expression_from_isl_expression (type
, for_inc
, ip
);
372 tree ivvar
= create_tmp_var (type
, "graphite_IV");
373 tree iv
, iv_after_increment
;
374 loop_p loop
= create_empty_loop_on_edge
375 (entry_edge
, lb
, stride
, ub
, ivvar
, &iv
, &iv_after_increment
,
376 outer
? outer
: entry_edge
->src
->loop_father
);
378 isl_ast_expr
*for_iterator
= isl_ast_node_for_get_iterator (node_for
);
379 isl_id
*id
= isl_ast_expr_get_id (for_iterator
);
381 isl_ast_expr_free (for_iterator
);
386 translate_isl_ast (loop_p context_loop
, __isl_keep isl_ast_node
*node
,
387 edge next_e
, ivs_params
&ip
);
389 /* Create the loop for a isl_ast_node_for.
391 - NEXT_E is the edge where new generated code should be attached. */
394 translate_isl_ast_for_loop (loop_p context_loop
,
395 __isl_keep isl_ast_node
*node_for
, edge next_e
,
396 tree type
, tree lb
, tree ub
,
399 gcc_assert (isl_ast_node_get_type (node_for
) == isl_ast_node_for
);
400 struct loop
*loop
= graphite_create_new_loop (next_e
, node_for
, context_loop
,
402 edge last_e
= single_exit (loop
);
403 edge to_body
= single_succ_edge (loop
->header
);
404 basic_block after
= to_body
->dest
;
406 /* Create a basic block for loop close phi nodes. */
407 last_e
= single_succ_edge (split_edge (last_e
));
409 /* Translate the body of the loop. */
410 isl_ast_node
*for_body
= isl_ast_node_for_get_body (node_for
);
411 next_e
= translate_isl_ast (loop
, for_body
, to_body
, ip
);
412 isl_ast_node_free (for_body
);
413 redirect_edge_succ_nodup (next_e
, after
);
414 set_immediate_dominator (CDI_DOMINATORS
, next_e
->dest
, next_e
->src
);
416 /* TODO: Add checking for the loop parallelism. */
421 /* We use this function to get the upper bound because of the form,
422 which is used by isl to represent loops:
424 for (iterator = init; cond; iterator += inc)
432 The loop condition is an arbitrary expression, which contains the
433 current loop iterator.
435 (e.g. iterator + 3 < B && C > iterator + A)
437 We have to know the upper bound of the iterator to generate a loop
438 in Gimple form. It can be obtained from the special representation
439 of the loop condition, which is generated by isl,
440 if the ast_build_atomic_upper_bound option is set. In this case,
441 isl generates a loop condition that consists of the current loop
442 iterator, + an operator (< or <=) and an expression not involving
443 the iterator, which is processed and returned by this function.
445 (e.g iterator <= upper-bound-expression-without-iterator) */
447 static __isl_give isl_ast_expr
*
448 get_upper_bound (__isl_keep isl_ast_node
*node_for
)
450 gcc_assert (isl_ast_node_get_type (node_for
) == isl_ast_node_for
);
451 isl_ast_expr
*for_cond
= isl_ast_node_for_get_cond (node_for
);
452 gcc_assert (isl_ast_expr_get_type (for_cond
) == isl_ast_expr_op
);
454 switch (isl_ast_expr_get_op_type (for_cond
))
457 res
= isl_ast_expr_get_op_arg (for_cond
, 1);
462 // (iterator < ub) => (iterator <= ub - 1)
463 isl_val
*one
= isl_val_int_from_si (isl_ast_expr_get_ctx (for_cond
), 1);
464 isl_ast_expr
*ub
= isl_ast_expr_get_op_arg (for_cond
, 1);
465 res
= isl_ast_expr_sub (ub
, isl_ast_expr_from_val (one
));
472 isl_ast_expr_free (for_cond
);
476 /* All loops generated by create_empty_loop_on_edge have the form of
483 } while (lower bound < upper bound);
485 We create a new if region protecting the loop to be executed, if
486 the execution count is zero (lower bound > upper bound). */
489 graphite_create_new_loop_guard (edge entry_edge
,
490 __isl_keep isl_ast_node
*node_for
, tree
*type
,
491 tree
*lb
, tree
*ub
, ivs_params
&ip
)
493 gcc_assert (isl_ast_node_get_type (node_for
) == isl_ast_node_for
);
497 *type
= *graphite_expression_size_type
;
498 isl_ast_expr
*for_init
= isl_ast_node_for_get_init (node_for
);
499 *lb
= gcc_expression_from_isl_expression (*type
, for_init
, ip
);
500 isl_ast_expr
*upper_bound
= get_upper_bound (node_for
);
501 *ub
= gcc_expression_from_isl_expression (*type
, upper_bound
, ip
);
503 /* When ub is simply a constant or a parameter, use lb <= ub. */
504 if (TREE_CODE (*ub
) == INTEGER_CST
|| TREE_CODE (*ub
) == SSA_NAME
)
505 cond_expr
= fold_build2 (LE_EXPR
, boolean_type_node
, *lb
, *ub
);
508 tree one
= (POINTER_TYPE_P (*type
)
509 ? convert_to_ptrofftype (integer_one_node
)
510 : fold_convert (*type
, integer_one_node
));
511 /* Adding +1 and using LT_EXPR helps with loop latches that have a
512 loop iteration count of "PARAMETER - 1". For PARAMETER == 0 this
513 becomes 2^k-1 due to integer overflow, and the condition lb <= ub
514 is true, even if we do not want this. However lb < ub + 1 is false,
516 tree ub_one
= fold_build2 (POINTER_TYPE_P (*type
) ? POINTER_PLUS_EXPR
517 : PLUS_EXPR
, *type
, *ub
, one
);
519 cond_expr
= fold_build2 (LT_EXPR
, boolean_type_node
, *lb
, ub_one
);
522 exit_edge
= create_empty_if_region_on_edge (entry_edge
, cond_expr
);
527 /* Translates an isl_ast_node_for to Gimple. */
530 translate_isl_ast_node_for (loop_p context_loop
, __isl_keep isl_ast_node
*node
,
531 edge next_e
, ivs_params
&ip
)
533 gcc_assert (isl_ast_node_get_type (node
) == isl_ast_node_for
);
535 edge last_e
= graphite_create_new_loop_guard (next_e
, node
, &type
,
537 edge true_e
= get_true_edge_from_guard_bb (next_e
->dest
);
539 translate_isl_ast_for_loop (context_loop
, node
, true_e
,
544 /* Translates an ISL AST node NODE to GCC representation in the
545 context of a SESE. */
548 translate_isl_ast (loop_p context_loop
, __isl_keep isl_ast_node
*node
,
549 edge next_e
, ivs_params
&ip
)
551 switch (isl_ast_node_get_type (node
))
553 case isl_ast_node_error
:
556 case isl_ast_node_for
:
557 return translate_isl_ast_node_for (context_loop
, node
,
560 case isl_ast_node_if
:
563 case isl_ast_node_user
:
566 case isl_ast_node_block
:
574 /* Prints NODE to FILE. */
577 print_isl_ast_node (FILE *file
, __isl_keep isl_ast_node
*node
,
578 __isl_keep isl_ctx
*ctx
)
580 isl_printer
*prn
= isl_printer_to_file (ctx
, file
);
581 prn
= isl_printer_set_output_format (prn
, ISL_FORMAT_C
);
582 prn
= isl_printer_print_ast_node (prn
, node
);
583 prn
= isl_printer_print_str (prn
, "\n");
584 isl_printer_free (prn
);
587 /* Add ISL's parameter identifiers and corresponding.trees to ivs_params */
590 add_parameters_to_ivs_params (scop_p scop
, ivs_params
&ip
)
592 sese region
= SCOP_REGION (scop
);
593 unsigned nb_parameters
= isl_set_dim (scop
->context
, isl_dim_param
);
594 gcc_assert (nb_parameters
== SESE_PARAMS (region
).length ());
596 for (i
= 0; i
< nb_parameters
; i
++)
598 isl_id
*tmp_id
= isl_set_get_dim_id (scop
->context
, isl_dim_param
, i
);
599 ip
[tmp_id
] = SESE_PARAMS (region
)[i
];
604 /* Generates a build, which specifies the constraints on the parameters. */
606 static __isl_give isl_ast_build
*
607 generate_isl_context (scop_p scop
)
609 isl_set
*context_isl
= isl_set_params (isl_set_copy (scop
->context
));
610 return isl_ast_build_from_context (context_isl
);
613 /* Generates a schedule, which specifies an order used to
614 visit elements in a domain. */
616 static __isl_give isl_union_map
*
617 generate_isl_schedule (scop_p scop
)
621 isl_union_map
*schedule_isl
=
622 isl_union_map_empty (isl_set_get_space (scop
->context
));
624 FOR_EACH_VEC_ELT (SCOP_BBS (scop
), i
, pbb
)
626 /* Dead code elimination: when the domain of a PBB is empty,
627 don't generate code for the PBB. */
628 if (isl_set_is_empty (pbb
->domain
))
631 isl_map
*bb_schedule
= isl_map_copy (pbb
->transformed
);
632 bb_schedule
= isl_map_intersect_domain (bb_schedule
,
633 isl_set_copy (pbb
->domain
));
635 isl_union_map_union (schedule_isl
,
636 isl_union_map_from_map (bb_schedule
));
641 static __isl_give isl_ast_node
*
642 scop_to_isl_ast (scop_p scop
, ivs_params
&ip
)
644 /* Generate loop upper bounds that consist of the current loop iterator,
645 an operator (< or <=) and an expression not involving the iterator.
646 If this option is not set, then the current loop iterator may appear several
647 times in the upper bound. See the isl manual for more details. */
648 isl_options_set_ast_build_atomic_upper_bound (scop
->ctx
, true);
650 add_parameters_to_ivs_params (scop
, ip
);
651 isl_union_map
*schedule_isl
= generate_isl_schedule (scop
);
652 isl_ast_build
*context_isl
= generate_isl_context (scop
);
653 isl_ast_node
*ast_isl
= isl_ast_build_ast_from_schedule (context_isl
,
655 isl_ast_build_free (context_isl
);
659 /* GIMPLE Loop Generator: generates loops from STMT in GIMPLE form for
660 the given SCOP. Return true if code generation succeeded.
662 FIXME: This is not yet a full implementation of the code generator
663 with ISL ASTs. Generation of GIMPLE code has to be completed. */
666 graphite_regenerate_ast_isl (scop_p scop
)
669 sese region
= SCOP_REGION (scop
);
670 ifsese if_region
= NULL
;
671 isl_ast_node
*root_node
;
674 timevar_push (TV_GRAPHITE_CODE_GEN
);
675 graphite_regenerate_error
= false;
676 root_node
= scop_to_isl_ast (scop
, ip
);
678 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
680 fprintf (dump_file
, "\nISL AST generated by ISL: \n");
681 print_isl_ast_node (dump_file
, root_node
, scop
->ctx
);
682 fprintf (dump_file
, "\n");
685 recompute_all_dominators ();
688 if_region
= move_sese_in_condition (region
);
689 sese_insert_phis_for_liveouts (region
,
690 if_region
->region
->exit
->src
,
691 if_region
->false_region
->exit
,
692 if_region
->true_region
->exit
);
693 recompute_all_dominators ();
696 context_loop
= SESE_ENTRY (region
)->src
->loop_father
;
698 translate_isl_ast (context_loop
, root_node
, if_region
->true_region
->entry
,
702 recompute_all_dominators ();
705 if (graphite_regenerate_error
)
706 set_ifsese_condition (if_region
, integer_zero_node
);
708 free (if_region
->true_region
);
709 free (if_region
->region
);
712 ivs_params_clear (ip
);
713 isl_ast_node_free (root_node
);
714 timevar_pop (TV_GRAPHITE_CODE_GEN
);
716 return !graphite_regenerate_error
;