X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fgraphite-clast-to-gimple.c;h=340c8fc4ecb8136be240b94af50612fa7e805858;hb=f1b77cb4cafb84d8b76abaa80cbe0db02ff46bd7;hp=bf540a2d1ca2de19f1e61adc2b3ef5d93b6e44a9;hpb=c6bb733dc15d307a9a8f4e2f93301661ae2bf6c1;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/graphite-clast-to-gimple.c b/gcc/graphite-clast-to-gimple.c index bf540a2d1ca..340c8fc4ecb 100644 --- a/gcc/graphite-clast-to-gimple.c +++ b/gcc/graphite-clast-to-gimple.c @@ -1,5 +1,5 @@ /* Translation of CLAST (CLooG AST) to Gimple. - Copyright (C) 2009 Free Software Foundation, Inc. + Copyright (C) 2009, 2010 Free Software Foundation, Inc. Contributed by Sebastian Pop . This file is part of GCC. @@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see #include "value-prof.h" #include "pointer-set.h" #include "gimple.h" +#include "langhooks.h" #include "sese.h" #ifdef HAVE_cloog @@ -52,6 +53,10 @@ along with GCC; see the file COPYING3. If not see #include "graphite-clast-to-gimple.h" #include "graphite-dependences.h" +/* This flag is set when an error occurred during the translation of + CLAST to Gimple. */ +static bool gloog_error; + /* Verifies properties that GRAPHITE should maintain during translation. */ static inline void @@ -61,11 +66,115 @@ graphite_verify (void) verify_loop_structure (); verify_dominators (CDI_DOMINATORS); verify_dominators (CDI_POST_DOMINATORS); - verify_ssa (false); - verify_loop_closed_ssa (); + verify_loop_closed_ssa (true); #endif } +/* Stores the INDEX in a vector for a given clast NAME. */ + +typedef struct clast_name_index { + int index; + const char *name; +} *clast_name_index_p; + +/* Returns a pointer to a new element of type clast_name_index_p built + from NAME and INDEX. */ + +static inline clast_name_index_p +new_clast_name_index (const char *name, int index) +{ + clast_name_index_p res = XNEW (struct clast_name_index); + + res->name = name; + res->index = index; + return res; +} + +/* For a given clast NAME, returns -1 if it does not correspond to any + parameter, or otherwise, returns the index in the PARAMS or + SCATTERING_DIMENSIONS vector. */ + +static inline int +clast_name_to_index (const char *name, htab_t index_table) +{ + struct clast_name_index tmp; + PTR *slot; + + tmp.name = name; + slot = htab_find_slot (index_table, &tmp, NO_INSERT); + + if (slot && *slot) + return ((struct clast_name_index *) *slot)->index; + + return -1; +} + +/* Records in INDEX_TABLE the INDEX for NAME. */ + +static inline void +save_clast_name_index (htab_t index_table, const char *name, int index) +{ + struct clast_name_index tmp; + PTR *slot; + + tmp.name = name; + slot = htab_find_slot (index_table, &tmp, INSERT); + + if (slot) + { + if (*slot) + free (*slot); + + *slot = new_clast_name_index (name, index); + } +} + +/* Print to stderr the element ELT. */ + +static inline void +debug_clast_name_index (clast_name_index_p elt) +{ + fprintf (stderr, "(index = %d, name = %s)\n", elt->index, elt->name); +} + +/* Helper function for debug_rename_map. */ + +static inline int +debug_clast_name_indexes_1 (void **slot, void *s ATTRIBUTE_UNUSED) +{ + struct clast_name_index *entry = (struct clast_name_index *) *slot; + debug_clast_name_index (entry); + return 1; +} + +/* Print to stderr all the elements of MAP. */ + +void +debug_clast_name_indexes (htab_t map) +{ + htab_traverse (map, debug_clast_name_indexes_1, NULL); +} + +/* Computes a hash function for database element ELT. */ + +static inline hashval_t +clast_name_index_elt_info (const void *elt) +{ + return htab_hash_pointer (((const struct clast_name_index *) elt)->name); +} + +/* Compares database elements E1 and E2. */ + +static inline int +eq_clast_name_indexes (const void *e1, const void *e2) +{ + const struct clast_name_index *elt1 = (const struct clast_name_index *) e1; + const struct clast_name_index *elt2 = (const struct clast_name_index *) e2; + + return (elt1->name == elt2->name); +} + + /* For a given loop DEPTH in the loop nest of the original black box PBB, return the old induction variable associated to that loop. */ @@ -76,7 +185,7 @@ pbb_to_depth_to_oldiv (poly_bb_p pbb, int depth) sese region = SCOP_REGION (PBB_SCOP (pbb)); loop_p loop = gbb_loop_at_index (gbb, region, depth); - return (tree) loop->aux; + return loop->single_iv; } /* For a given scattering dimension, return the new induction variable @@ -95,11 +204,10 @@ newivs_to_depth_to_newiv (VEC (tree, heap) *newivs, int depth) static tree clast_name_to_gcc (const char *name, sese region, VEC (tree, heap) *newivs, - htab_t newivs_index) + htab_t newivs_index, htab_t params_index) { int index; VEC (tree, heap) *params = SESE_PARAMS (region); - htab_t params_index = SESE_PARAMS_INDEX (region); if (params && params_index) { @@ -116,19 +224,52 @@ clast_name_to_gcc (const char *name, sese region, VEC (tree, heap) *newivs, return newivs_to_depth_to_newiv (newivs, index); } -/* Returns the maximal precision type for expressions E1 and E2. */ +/* Returns the signed maximal precision type for expressions TYPE1 and TYPE2. */ -static inline tree -max_precision_type (tree e1, tree e2) +static tree +max_signed_precision_type (tree type1, tree type2) { - tree type1 = TREE_TYPE (e1); - tree type2 = TREE_TYPE (e2); + int p1 = TYPE_PRECISION (type1); + int p2 = TYPE_PRECISION (type2); + int precision; + tree type; + + if (p1 > p2) + precision = TYPE_UNSIGNED (type1) ? p1 * 2 : p1; + else + precision = TYPE_UNSIGNED (type2) ? p2 * 2 : p2; + + type = lang_hooks.types.type_for_size (precision, false); + + if (!type) + { + gloog_error = true; + return integer_type_node; + } + return type; +} + +/* Returns the maximal precision type for expressions TYPE1 and TYPE2. */ + +static tree +max_precision_type (tree type1, tree type2) +{ + if (POINTER_TYPE_P (type1)) + return type1; + + if (POINTER_TYPE_P (type2)) + return type2; + + if (!TYPE_UNSIGNED (type1) + || !TYPE_UNSIGNED (type2)) + return max_signed_precision_type (type1, type2); + return TYPE_PRECISION (type1) > TYPE_PRECISION (type2) ? type1 : type2; } static tree clast_to_gcc_expression (tree, struct clast_expr *, sese, VEC (tree, heap) *, - htab_t); + htab_t, htab_t); /* Converts a Cloog reduction expression R with reduction operation OP to a GCC expression tree of type TYPE. */ @@ -137,17 +278,17 @@ static tree clast_to_gcc_expression_red (tree type, enum tree_code op, struct clast_reduction *r, sese region, VEC (tree, heap) *newivs, - htab_t newivs_index) + htab_t newivs_index, htab_t params_index) { int i; tree res = clast_to_gcc_expression (type, r->elts[0], region, newivs, - newivs_index); + newivs_index, params_index); tree operand_type = (op == POINTER_PLUS_EXPR) ? sizetype : type; for (i = 1; i < r->n; i++) { tree t = clast_to_gcc_expression (operand_type, r->elts[i], region, - newivs, newivs_index); + newivs, newivs_index, params_index); res = fold_build2 (op, type, res, t); } @@ -160,7 +301,7 @@ clast_to_gcc_expression_red (tree type, enum tree_code op, static tree clast_to_gcc_expression (tree type, struct clast_expr *e, sese region, VEC (tree, heap) *newivs, - htab_t newivs_index) + htab_t newivs_index, htab_t params_index) { switch (e->type) { @@ -170,27 +311,46 @@ clast_to_gcc_expression (tree type, struct clast_expr *e, if (t->var) { - if (value_one_p (t->val)) + if (mpz_cmp_si (t->val, 1) == 0) { tree name = clast_name_to_gcc (t->var, region, newivs, - newivs_index); - return fold_convert (type, name); + newivs_index, params_index); + + if (POINTER_TYPE_P (TREE_TYPE (name)) != POINTER_TYPE_P (type)) + name = fold_convert (sizetype, name); + + name = fold_convert (type, name); + return name; } - else if (value_mone_p (t->val)) + else if (mpz_cmp_si (t->val, -1) == 0) { tree name = clast_name_to_gcc (t->var, region, newivs, - newivs_index); + newivs_index, params_index); + + if (POINTER_TYPE_P (TREE_TYPE (name)) != POINTER_TYPE_P (type)) + name = fold_convert (sizetype, name); + name = fold_convert (type, name); + return fold_build1 (NEGATE_EXPR, type, name); } else { tree name = clast_name_to_gcc (t->var, region, newivs, - newivs_index); + newivs_index, params_index); tree cst = gmp_cst_to_tree (type, t->val); + + if (POINTER_TYPE_P (TREE_TYPE (name)) != POINTER_TYPE_P (type)) + name = fold_convert (sizetype, name); + name = fold_convert (type, name); - return fold_build2 (MULT_EXPR, type, cst, name); + + if (!POINTER_TYPE_P (type)) + return fold_build2 (MULT_EXPR, type, cst, name); + + gloog_error = true; + return cst; } } else @@ -206,15 +366,17 @@ clast_to_gcc_expression (tree type, struct clast_expr *e, case clast_red_sum: return clast_to_gcc_expression_red (type, POINTER_TYPE_P (type) ? POINTER_PLUS_EXPR : PLUS_EXPR, - r, region, newivs, newivs_index); + r, region, newivs, newivs_index, params_index); case clast_red_min: return clast_to_gcc_expression_red (type, MIN_EXPR, r, region, - newivs, newivs_index); + newivs, newivs_index, + params_index); case clast_red_max: return clast_to_gcc_expression_red (type, MAX_EXPR, r, region, - newivs, newivs_index); + newivs, newivs_index, + params_index); default: gcc_unreachable (); @@ -227,7 +389,7 @@ clast_to_gcc_expression (tree type, struct clast_expr *e, struct clast_binary *b = (struct clast_binary *) e; struct clast_expr *lhs = (struct clast_expr *) b->LHS; tree tl = clast_to_gcc_expression (type, lhs, region, newivs, - newivs_index); + newivs_index, params_index); tree tr = gmp_cst_to_tree (type, b->RHS); switch (b->type) @@ -256,54 +418,187 @@ clast_to_gcc_expression (tree type, struct clast_expr *e, return NULL_TREE; } -/* Returns the type for the expression E. */ +/* Return the precision needed to represent the value VAL. */ + +static int +precision_for_value (mpz_t val) +{ + mpz_t x, y, two; + int precision; + + value_init (x); + value_init (y); + value_init (two); + value_set_si (x, 2); + value_assign (y, val); + value_set_si (two, 2); + precision = 1; + + if (value_neg_p (y)) + value_oppose (y, y); + + while (value_gt (y, x)) + { + value_multiply (x, x, two); + precision++; + } + + value_clear (x); + value_clear (y); + value_clear (two); + + return precision; +} + +/* Return the precision needed to represent the values between LOW and + UP. */ + +static int +precision_for_interval (mpz_t low, mpz_t up) +{ + mpz_t diff; + int precision; + + gcc_assert (value_le (low, up)); + + value_init (diff); + value_subtract (diff, up, low); + precision = precision_for_value (diff); + value_clear (diff); + + return precision; +} + +/* Return a type that could represent the integer value VAL, or + otherwise return NULL_TREE. */ + +static tree +gcc_type_for_interval (mpz_t low, mpz_t up, tree old_type) +{ + bool unsigned_p = true; + int precision, prec_up, prec_int; + tree type; + + gcc_assert (value_le (low, up)); + + /* Preserve the signedness of the old IV. */ + if ((old_type && !TYPE_UNSIGNED (old_type)) + || value_neg_p (low)) + unsigned_p = false; + + prec_up = precision_for_value (up); + prec_int = precision_for_interval (low, up); + precision = prec_up > prec_int ? prec_up : prec_int; + + type = lang_hooks.types.type_for_size (precision, unsigned_p); + if (!type) + { + gloog_error = true; + return integer_type_node; + } + + return type; +} + +/* Return a type that could represent the integer value VAL, or + otherwise return NULL_TREE. */ + +static tree +gcc_type_for_value (mpz_t val) +{ + return gcc_type_for_interval (val, val, NULL_TREE); +} + +/* Return the type for the clast_term T used in STMT. */ + +static tree +gcc_type_for_clast_term (struct clast_term *t, + sese region, VEC (tree, heap) *newivs, + htab_t newivs_index, htab_t params_index) +{ + gcc_assert (t->expr.type == expr_term); + + if (!t->var) + return gcc_type_for_value (t->val); + + return TREE_TYPE (clast_name_to_gcc (t->var, region, newivs, + newivs_index, params_index)); +} + +static tree +gcc_type_for_clast_expr (struct clast_expr *, sese, + VEC (tree, heap) *, htab_t, htab_t); + +/* Return the type for the clast_reduction R used in STMT. */ + +static tree +gcc_type_for_clast_red (struct clast_reduction *r, sese region, + VEC (tree, heap) *newivs, + htab_t newivs_index, htab_t params_index) +{ + int i; + tree type = NULL_TREE; + + if (r->n == 1) + return gcc_type_for_clast_expr (r->elts[0], region, newivs, + newivs_index, params_index); + + switch (r->type) + { + case clast_red_sum: + case clast_red_min: + case clast_red_max: + type = gcc_type_for_clast_expr (r->elts[0], region, newivs, + newivs_index, params_index); + for (i = 1; i < r->n; i++) + type = max_precision_type (type, gcc_type_for_clast_expr + (r->elts[i], region, newivs, + newivs_index, params_index)); + + return type; + + default: + break; + } + + gcc_unreachable (); + return NULL_TREE; +} + +/* Return the type for the clast_binary B used in STMT. */ + +static tree +gcc_type_for_clast_bin (struct clast_binary *b, + sese region, VEC (tree, heap) *newivs, + htab_t newivs_index, htab_t params_index) +{ + tree l = gcc_type_for_clast_expr ((struct clast_expr *) b->LHS, region, + newivs, newivs_index, params_index); + tree r = gcc_type_for_value (b->RHS); + return max_signed_precision_type (l, r); +} + +/* Returns the type for the CLAST expression E when used in statement + STMT. */ static tree gcc_type_for_clast_expr (struct clast_expr *e, sese region, VEC (tree, heap) *newivs, - htab_t newivs_index) + htab_t newivs_index, htab_t params_index) { switch (e->type) { case expr_term: - { - struct clast_term *t = (struct clast_term *) e; - - if (t->var) - return TREE_TYPE (clast_name_to_gcc (t->var, region, newivs, - newivs_index)); - else - return NULL_TREE; - } + return gcc_type_for_clast_term ((struct clast_term *) e, region, + newivs, newivs_index, params_index); case expr_red: - { - struct clast_reduction *r = (struct clast_reduction *) e; - - if (r->n == 1) - return gcc_type_for_clast_expr (r->elts[0], region, newivs, - newivs_index); - else - { - int i; - for (i = 0; i < r->n; i++) - { - tree type = gcc_type_for_clast_expr (r->elts[i], region, - newivs, newivs_index); - if (type) - return type; - } - return NULL_TREE; - } - } + return gcc_type_for_clast_red ((struct clast_reduction *) e, region, + newivs, newivs_index, params_index); case expr_bin: - { - struct clast_binary *b = (struct clast_binary *) e; - struct clast_expr *lhs = (struct clast_expr *) b->LHS; - return gcc_type_for_clast_expr (lhs, region, newivs, - newivs_index); - } + return gcc_type_for_clast_bin ((struct clast_binary *) e, region, + newivs, newivs_index, params_index); default: gcc_unreachable (); @@ -317,14 +612,13 @@ gcc_type_for_clast_expr (struct clast_expr *e, static tree gcc_type_for_clast_eq (struct clast_equation *cleq, sese region, VEC (tree, heap) *newivs, - htab_t newivs_index) + htab_t newivs_index, htab_t params_index) { - tree type = gcc_type_for_clast_expr (cleq->LHS, region, newivs, - newivs_index); - if (type) - return type; - - return gcc_type_for_clast_expr (cleq->RHS, region, newivs, newivs_index); + tree l = gcc_type_for_clast_expr (cleq->LHS, region, newivs, + newivs_index, params_index); + tree r = gcc_type_for_clast_expr (cleq->RHS, region, newivs, + newivs_index, params_index); + return max_precision_type (l, r); } /* Translates a clast equation CLEQ to a tree. */ @@ -333,14 +627,15 @@ static tree graphite_translate_clast_equation (sese region, struct clast_equation *cleq, VEC (tree, heap) *newivs, - htab_t newivs_index) + htab_t newivs_index, htab_t params_index) { enum tree_code comp; - tree type = gcc_type_for_clast_eq (cleq, region, newivs, newivs_index); + tree type = gcc_type_for_clast_eq (cleq, region, newivs, newivs_index, + params_index); tree lhs = clast_to_gcc_expression (type, cleq->LHS, region, newivs, - newivs_index); + newivs_index, params_index); tree rhs = clast_to_gcc_expression (type, cleq->RHS, region, newivs, - newivs_index); + newivs_index, params_index); if (cleq->sign == 0) comp = EQ_EXPR; @@ -359,7 +654,7 @@ graphite_translate_clast_equation (sese region, static tree graphite_create_guard_cond_expr (sese region, struct clast_guard *stmt, VEC (tree, heap) *newivs, - htab_t newivs_index) + htab_t newivs_index, htab_t params_index) { tree cond = NULL; int i; @@ -367,7 +662,8 @@ graphite_create_guard_cond_expr (sese region, struct clast_guard *stmt, for (i = 0; i < stmt->n; i++) { tree eq = graphite_translate_clast_equation (region, &stmt->eq[i], - newivs, newivs_index); + newivs, newivs_index, + params_index); if (cond) cond = fold_build2 (TRUTH_AND_EXPR, TREE_TYPE (eq), cond, eq); @@ -384,14 +680,88 @@ static edge graphite_create_new_guard (sese region, edge entry_edge, struct clast_guard *stmt, VEC (tree, heap) *newivs, - htab_t newivs_index) + htab_t newivs_index, htab_t params_index) { tree cond_expr = graphite_create_guard_cond_expr (region, stmt, newivs, - newivs_index); + newivs_index, params_index); edge exit_edge = create_empty_if_region_on_edge (entry_edge, cond_expr); return exit_edge; } +/* Compute the lower bound LOW and upper bound UP for the induction + variable at LEVEL for the statement PBB, based on the transformed + scattering of PBB: T|I|G|Cst, with T the scattering transform, I + the iteration domain, and G the context parameters. */ + +static void +compute_bounds_for_level (poly_bb_p pbb, int level, mpz_t low, mpz_t up) +{ + ppl_Pointset_Powerset_C_Polyhedron_t ps; + ppl_Linear_Expression_t le; + + combine_context_id_scat (&ps, pbb, false); + + /* Prepare the linear expression corresponding to the level that we + want to maximize/minimize. */ + { + ppl_dimension_type dim = pbb_nb_scattering_transform (pbb) + + pbb_dim_iter_domain (pbb) + pbb_nb_params (pbb); + + ppl_new_Linear_Expression_with_dimension (&le, dim); + ppl_set_coef (le, 2 * level + 1, 1); + } + + ppl_max_for_le_pointset (ps, le, up); + ppl_min_for_le_pointset (ps, le, low); +} + +/* Compute the type for the induction variable at LEVEL for the + statement PBB, based on the transformed schedule of PBB. OLD_TYPE + is the type of the old induction variable for that loop. */ + +static tree +compute_type_for_level_1 (poly_bb_p pbb, int level, tree old_type) +{ + mpz_t low, up; + tree type; + + value_init (low); + value_init (up); + + compute_bounds_for_level (pbb, level, low, up); + type = gcc_type_for_interval (low, up, old_type); + + value_clear (low); + value_clear (up); + return type; +} + +/* Compute the type for the induction variable at LEVEL for the + statement PBB, based on the transformed schedule of PBB. */ + +static tree +compute_type_for_level (poly_bb_p pbb, int level) +{ + tree oldiv = pbb_to_depth_to_oldiv (pbb, level); + tree type = TREE_TYPE (oldiv); + + if (type && POINTER_TYPE_P (type)) + { +#ifdef ENABLE_CHECKING + tree ctype = compute_type_for_level_1 (pbb, level, type); + + /* In the case of a pointer type, check that after the loop + transform, the lower and the upper bounds of the type fit the + oldiv pointer type. */ + gcc_assert (TYPE_PRECISION (type) >= TYPE_PRECISION (ctype) + && integer_zerop (lower_bound_in_type (ctype, ctype))); +#endif + return type; + } + + return compute_type_for_level_1 (pbb, level, type); +} + /* Walks a CLAST and returns the first statement in the body of a loop. */ @@ -414,38 +784,21 @@ clast_get_body_of_loop (struct clast_stmt *stmt) gcc_unreachable (); } -/* Given a CLOOG_IV, returns the type that it should have in GCC land. - If the information is not available, i.e. in the case one of the - transforms created the loop, just return integer_type_node. */ - -static tree -gcc_type_for_cloog_iv (const char *cloog_iv, gimple_bb_p gbb) -{ - struct ivtype_map_elt_s tmp; - PTR *slot; - - tmp.cloog_iv = cloog_iv; - slot = htab_find_slot (GBB_CLOOG_IV_TYPES (gbb), &tmp, NO_INSERT); - - if (slot && *slot) - return ((ivtype_map_elt) *slot)->type; - - return integer_type_node; -} - -/* Returns the induction variable for the loop that gets translated to - STMT. */ +/* Returns the type for the induction variable for the loop translated + from STMT_FOR. */ static tree -gcc_type_for_iv_of_clast_loop (struct clast_for *stmt_for) +gcc_type_for_iv_of_clast_loop (struct clast_for *stmt_for, int level, + tree lb_type, tree ub_type) { struct clast_stmt *stmt = (struct clast_stmt *) stmt_for; struct clast_user_stmt *body = clast_get_body_of_loop (stmt); - const char *cloog_iv = stmt_for->iterator; CloogStatement *cs = body->statement; poly_bb_p pbb = (poly_bb_p) cloog_statement_usr (cs); - return gcc_type_for_cloog_iv (cloog_iv, PBB_BLACK_BOX (pbb)); + return max_signed_precision_type (lb_type, max_precision_type + (ub_type, compute_type_for_level + (pbb, level - 1))); } /* Creates a new LOOP corresponding to Cloog's STMT. Inserts an @@ -460,13 +813,17 @@ static struct loop * graphite_create_new_loop (sese region, edge entry_edge, struct clast_for *stmt, loop_p outer, VEC (tree, heap) **newivs, - htab_t newivs_index) + htab_t newivs_index, htab_t params_index, int level) { - tree type = gcc_type_for_iv_of_clast_loop (stmt); + tree lb_type = gcc_type_for_clast_expr (stmt->LB, region, *newivs, + newivs_index, params_index); + tree ub_type = gcc_type_for_clast_expr (stmt->UB, region, *newivs, + newivs_index, params_index); + tree type = gcc_type_for_iv_of_clast_loop (stmt, level, lb_type, ub_type); tree lb = clast_to_gcc_expression (type, stmt->LB, region, *newivs, - newivs_index); + newivs_index, params_index); tree ub = clast_to_gcc_expression (type, stmt->UB, region, *newivs, - newivs_index); + newivs_index, params_index); tree stride = gmp_cst_to_tree (type, stmt->stride); tree ivvar = create_tmp_var (type, "graphite_IV"); tree iv, iv_after_increment; @@ -488,7 +845,8 @@ graphite_create_new_loop (sese region, edge entry_edge, static void build_iv_mapping (htab_t map, sese region, VEC (tree, heap) *newivs, htab_t newivs_index, - struct clast_user_stmt *user_stmt) + struct clast_user_stmt *user_stmt, + htab_t params_index) { struct clast_stmt *t; int index = 0; @@ -500,10 +858,10 @@ build_iv_mapping (htab_t map, sese region, struct clast_expr *expr = (struct clast_expr *) ((struct clast_assignment *)t)->RHS; tree type = gcc_type_for_clast_expr (expr, region, newivs, - newivs_index); + newivs_index, params_index); tree old_name = pbb_to_depth_to_oldiv (pbb, index); tree e = clast_to_gcc_expression (type, expr, region, newivs, - newivs_index); + newivs_index, params_index); set_rename (map, old_name, e); } } @@ -523,7 +881,7 @@ copy_renames (void **slot, void *s) tmp.old_name = old_name; x = htab_find_slot (res, &tmp, INSERT); - if (!*x) + if (x && !*x) *x = new_rename_map_elt (old_name, expr); return 1; @@ -554,278 +912,331 @@ mark_bb_with_pbb (poly_bb_p pbb, basic_block bb, htab_t bb_pbb_mapping) tmp.bb = bb; x = htab_find_slot (bb_pbb_mapping, &tmp, INSERT); - if (!*x) + if (x && !*x) *x = new_bb_pbb_def (bb, pbb); } -/* Returns the scattering dimension for STMTFOR. +/* Find BB's related poly_bb_p in hash table BB_PBB_MAPPING. */ - FIXME: This is a hackish solution to locate the scattering - dimension in newly created loops. Here the hackish solush - assume that the stmt_for->iterator is always something like: - scat_1 , scat_3 etc., where after "scat_" is loop level in - scattering dimension. -*/ +static poly_bb_p +find_pbb_via_hash (htab_t bb_pbb_mapping, basic_block bb) +{ + bb_pbb_def tmp; + PTR *slot; + + tmp.bb = bb; + slot = htab_find_slot (bb_pbb_mapping, &tmp, NO_INSERT); + + if (slot && *slot) + return ((bb_pbb_def *) *slot)->pbb; + + return NULL; +} -static int get_stmtfor_depth (struct clast_for *stmtfor) +/* Check data dependency in LOOP at scattering level LEVEL. + BB_PBB_MAPPING is a basic_block and it's related poly_bb_p + mapping. */ + +static bool +dependency_in_loop_p (loop_p loop, htab_t bb_pbb_mapping, int level) { - const char * iterator = stmtfor->iterator; - const char * depth; + unsigned i,j; + basic_block *bbs = get_loop_body_in_dom_order (loop); - depth = strchr (iterator, '_'); - if (!strncmp (iterator, "scat_", 5)) - return atoi (depth+1); + for (i = 0; i < loop->num_nodes; i++) + { + poly_bb_p pbb1 = find_pbb_via_hash (bb_pbb_mapping, bbs[i]); + + if (pbb1 == NULL) + continue; + + for (j = 0; j < loop->num_nodes; j++) + { + poly_bb_p pbb2 = find_pbb_via_hash (bb_pbb_mapping, bbs[j]); + + if (pbb2 == NULL) + continue; + + if (dependency_between_pbbs_p (pbb1, pbb2, level)) + { + free (bbs); + return true; + } + } + } + + free (bbs); - gcc_unreachable(); + return false; } -/* Translates a CLAST statement STMT to GCC representation in the - context of a SESE. +static edge +translate_clast (sese, loop_p, struct clast_stmt *, edge, htab_t, + VEC (tree, heap) **, htab_t, htab_t, int, htab_t); +/* Translates a clast user statement STMT to gimple. + + - REGION is the sese region we used to generate the scop. - NEXT_E is the edge where new generated code should be attached. - CONTEXT_LOOP is the loop in which the generated code will be placed - RENAME_MAP contains a set of tuples of new names associated to the original variables names. - BB_PBB_MAPPING is is a basic_block and it's related poly_bb_p mapping. -*/ - + - PARAMS_INDEX connects the cloog parameters with the gimple parameters in + the sese region. */ static edge -translate_clast (sese region, struct loop *context_loop, - struct clast_stmt *stmt, edge next_e, - htab_t rename_map, VEC (tree, heap) **newivs, - htab_t newivs_index, htab_t bb_pbb_mapping) +translate_clast_user (sese region, struct clast_user_stmt *stmt, edge next_e, + htab_t rename_map, VEC (tree, heap) **newivs, + htab_t newivs_index, htab_t bb_pbb_mapping, + htab_t params_index) { - if (!stmt) + gimple_bb_p gbb; + basic_block new_bb; + poly_bb_p pbb = (poly_bb_p) cloog_statement_usr (stmt->statement); + gbb = PBB_BLACK_BOX (pbb); + + if (GBB_BB (gbb) == ENTRY_BLOCK_PTR) return next_e; - if (CLAST_STMT_IS_A (stmt, stmt_root)) - return translate_clast (region, context_loop, stmt->next, next_e, - rename_map, newivs, newivs_index, bb_pbb_mapping); + build_iv_mapping (rename_map, region, *newivs, newivs_index, stmt, + params_index); + next_e = copy_bb_and_scalar_dependences (GBB_BB (gbb), region, + next_e, rename_map); + new_bb = next_e->src; + mark_bb_with_pbb (pbb, new_bb, bb_pbb_mapping); + update_ssa (TODO_update_ssa); - if (CLAST_STMT_IS_A (stmt, stmt_user)) - { - gimple_bb_p gbb; - basic_block new_bb; - CloogStatement *cs = ((struct clast_user_stmt *) stmt)->statement; - poly_bb_p pbb = (poly_bb_p) cloog_statement_usr (cs); - gbb = PBB_BLACK_BOX (pbb); - - if (GBB_BB (gbb) == ENTRY_BLOCK_PTR) - return next_e; - - build_iv_mapping (rename_map, region, *newivs, newivs_index, - (struct clast_user_stmt *) stmt); - next_e = copy_bb_and_scalar_dependences (GBB_BB (gbb), region, - next_e, rename_map); - new_bb = next_e->src; - mark_bb_with_pbb (pbb, new_bb, bb_pbb_mapping); - recompute_all_dominators (); - update_ssa (TODO_update_ssa); - graphite_verify (); - return translate_clast (region, context_loop, stmt->next, next_e, - rename_map, newivs, newivs_index, - bb_pbb_mapping); - } + return next_e; +} - if (CLAST_STMT_IS_A (stmt, stmt_for)) - { - struct clast_for *stmtfor = (struct clast_for *)stmt; - struct loop *loop - = graphite_create_new_loop (region, next_e, stmtfor, - context_loop, newivs, newivs_index); - edge last_e = single_exit (loop); - edge to_body = single_succ_edge (loop->header); - basic_block after = to_body->dest; - - loop->aux = XNEW (int); - /* Pass scattering level information of the new loop by LOOP->AUX. */ - *((int *)(loop->aux)) = get_stmtfor_depth (stmtfor); - - /* Create a basic block for loop close phi nodes. */ - last_e = single_succ_edge (split_edge (last_e)); - - /* Translate the body of the loop. */ - next_e = translate_clast - (region, loop, ((struct clast_for *) stmt)->body, - single_succ_edge (loop->header), rename_map, newivs, - newivs_index, bb_pbb_mapping); - redirect_edge_succ_nodup (next_e, after); - set_immediate_dominator (CDI_DOMINATORS, next_e->dest, next_e->src); - - /* Remove from rename_map all the tuples containing variables - defined in loop's body. */ - insert_loop_close_phis (rename_map, loop); - - recompute_all_dominators (); - graphite_verify (); - return translate_clast (region, context_loop, stmt->next, last_e, - rename_map, newivs, newivs_index, - bb_pbb_mapping); - } +/* Creates a new if region protecting the loop to be executed, if the execution + count is zero (lb > ub). */ +static edge +graphite_create_new_loop_guard (sese region, edge entry_edge, + struct clast_for *stmt, + VEC (tree, heap) *newivs, + htab_t newivs_index, htab_t params_index) +{ + tree cond_expr; + edge exit_edge; + tree lb_type = gcc_type_for_clast_expr (stmt->LB, region, newivs, + newivs_index, params_index); + tree ub_type = gcc_type_for_clast_expr (stmt->UB, region, newivs, + newivs_index, params_index); + tree type = max_precision_type (lb_type, ub_type); + tree lb = clast_to_gcc_expression (type, stmt->LB, region, newivs, + newivs_index, params_index); + tree ub = clast_to_gcc_expression (type, stmt->UB, region, newivs, + newivs_index, params_index); + tree ub_one; + + /* Adding +1 and using LT_EXPR helps with loop latches that have a + loop iteration count of "PARAMETER - 1". For PARAMETER == 0 this becomes + 2^{32|64}, and the condition lb <= ub is true, even if we do not want this. + However lb < ub + 1 is false, as expected. */ + tree one; + mpz_t gmp_one; + + mpz_init (gmp_one); + mpz_set_si (gmp_one, 1); + one = gmp_cst_to_tree (type, gmp_one); + mpz_clear (gmp_one); + + ub_one = fold_build2 (POINTER_TYPE_P (type) ? POINTER_PLUS_EXPR : PLUS_EXPR, + type, ub, one); + + /* When ub + 1 wraps around, use lb <= ub. */ + if (integer_zerop (ub_one)) + cond_expr = fold_build2 (LE_EXPR, boolean_type_node, lb, ub); + else + cond_expr = fold_build2 (LT_EXPR, boolean_type_node, lb, ub_one); - if (CLAST_STMT_IS_A (stmt, stmt_guard)) - { - edge last_e = graphite_create_new_guard (region, next_e, - ((struct clast_guard *) stmt), - *newivs, newivs_index); - edge true_e = get_true_edge_from_guard_bb (next_e->dest); - edge false_e = get_false_edge_from_guard_bb (next_e->dest); - edge exit_true_e = single_succ_edge (true_e->dest); - edge exit_false_e = single_succ_edge (false_e->dest); - htab_t before_guard = htab_create (10, rename_map_elt_info, - eq_rename_map_elts, free); - - htab_traverse (rename_map, copy_renames, before_guard); - next_e = translate_clast (region, context_loop, - ((struct clast_guard *) stmt)->then, - true_e, rename_map, newivs, newivs_index, - bb_pbb_mapping); - insert_guard_phis (last_e->src, exit_true_e, exit_false_e, - before_guard, rename_map); - - htab_delete (before_guard); - recompute_all_dominators (); - graphite_verify (); - - return translate_clast (region, context_loop, stmt->next, last_e, - rename_map, newivs, newivs_index, - bb_pbb_mapping); - } + exit_edge = create_empty_if_region_on_edge (entry_edge, cond_expr); - if (CLAST_STMT_IS_A (stmt, stmt_block)) - { - next_e = translate_clast (region, context_loop, - ((struct clast_block *) stmt)->body, - next_e, rename_map, newivs, newivs_index, - bb_pbb_mapping); - recompute_all_dominators (); - graphite_verify (); - return translate_clast (region, context_loop, stmt->next, next_e, - rename_map, newivs, newivs_index, - bb_pbb_mapping); - } + return exit_edge; +} - gcc_unreachable (); + +/* Create the loop for a clast for statement. + + - REGION is the sese region we used to generate the scop. + - NEXT_E is the edge where new generated code should be attached. + - RENAME_MAP contains a set of tuples of new names associated to + the original variables names. + - BB_PBB_MAPPING is is a basic_block and it's related poly_bb_p mapping. + - PARAMS_INDEX connects the cloog parameters with the gimple parameters in + the sese region. */ +static edge +translate_clast_for_loop (sese region, loop_p context_loop, + struct clast_for *stmt, edge next_e, + htab_t rename_map, VEC (tree, heap) **newivs, + htab_t newivs_index, htab_t bb_pbb_mapping, + int level, htab_t params_index) +{ + struct loop *loop = graphite_create_new_loop (region, next_e, stmt, + context_loop, newivs, + newivs_index, params_index, + level); + edge last_e = single_exit (loop); + edge to_body = single_succ_edge (loop->header); + basic_block after = to_body->dest; + + /* Create a basic block for loop close phi nodes. */ + last_e = single_succ_edge (split_edge (last_e)); + + /* Translate the body of the loop. */ + next_e = translate_clast (region, loop, stmt->body, to_body, rename_map, + newivs, newivs_index, bb_pbb_mapping, level + 1, + params_index); + redirect_edge_succ_nodup (next_e, after); + set_immediate_dominator (CDI_DOMINATORS, next_e->dest, next_e->src); + + /* Remove from rename_map all the tuples containing variables + defined in loop's body. */ + insert_loop_close_phis (rename_map, loop); + + if (flag_loop_parallelize_all + && !dependency_in_loop_p (loop, bb_pbb_mapping, + get_scattering_level (level))) + loop->can_be_parallel = true; + + return last_e; } -/* Returns the first cloog name used in EXPR. */ +/* Translates a clast for statement STMT to gimple. First a guard is created + protecting the loop, if it is executed zero times. In this guard we create + the real loop structure. -static const char * -find_cloog_iv_in_expr (struct clast_expr *expr) + - REGION is the sese region we used to generate the scop. + - NEXT_E is the edge where new generated code should be attached. + - RENAME_MAP contains a set of tuples of new names associated to + the original variables names. + - BB_PBB_MAPPING is is a basic_block and it's related poly_bb_p mapping. + - PARAMS_INDEX connects the cloog parameters with the gimple parameters in + the sese region. */ +static edge +translate_clast_for (sese region, loop_p context_loop, struct clast_for *stmt, + edge next_e, htab_t rename_map, VEC (tree, heap) **newivs, + htab_t newivs_index, htab_t bb_pbb_mapping, int level, + htab_t params_index) { - struct clast_term *term = (struct clast_term *) expr; + edge last_e = graphite_create_new_loop_guard (region, next_e, stmt, *newivs, + newivs_index, params_index); - if (expr->type == expr_term - && !term->var) - return NULL; + edge true_e = get_true_edge_from_guard_bb (next_e->dest); + edge false_e = get_false_edge_from_guard_bb (next_e->dest); + edge exit_true_e = single_succ_edge (true_e->dest); + edge exit_false_e = single_succ_edge (false_e->dest); - if (expr->type == expr_term) - return term->var; + htab_t before_guard = htab_create (10, rename_map_elt_info, + eq_rename_map_elts, free); + htab_traverse (rename_map, copy_renames, before_guard); - if (expr->type == expr_red) - { - int i; - struct clast_reduction *red = (struct clast_reduction *) expr; + next_e = translate_clast_for_loop (region, context_loop, stmt, true_e, + rename_map, newivs, + newivs_index, bb_pbb_mapping, level, + params_index); - for (i = 0; i < red->n; i++) - { - const char *res = find_cloog_iv_in_expr ((red)->elts[i]); + insert_guard_phis (last_e->src, exit_true_e, exit_false_e, + before_guard, rename_map); - if (res) - return res; - } - } + htab_delete (before_guard); - return NULL; + return last_e; } -/* Build for a clast_user_stmt USER_STMT a map between the CLAST - induction variables and the corresponding GCC old induction - variables. This information is stored on each GRAPHITE_BB. */ +/* Translates a clast guard statement STMT to gimple. -static void -compute_cloog_iv_types_1 (poly_bb_p pbb, struct clast_user_stmt *user_stmt) + - REGION is the sese region we used to generate the scop. + - NEXT_E is the edge where new generated code should be attached. + - CONTEXT_LOOP is the loop in which the generated code will be placed + - RENAME_MAP contains a set of tuples of new names associated to + the original variables names. + - BB_PBB_MAPPING is is a basic_block and it's related poly_bb_p mapping. + - PARAMS_INDEX connects the cloog parameters with the gimple parameters in + the sese region. */ +static edge +translate_clast_guard (sese region, loop_p context_loop, + struct clast_guard *stmt, edge next_e, + htab_t rename_map, VEC (tree, heap) **newivs, + htab_t newivs_index, htab_t bb_pbb_mapping, int level, + htab_t params_index) { - gimple_bb_p gbb = PBB_BLACK_BOX (pbb); - struct clast_stmt *t; - int index = 0; + edge last_e = graphite_create_new_guard (region, next_e, stmt, *newivs, + newivs_index, params_index); - for (t = user_stmt->substitutions; t; t = t->next, index++) - { - PTR *slot; - struct ivtype_map_elt_s tmp; - struct clast_expr *expr = (struct clast_expr *) - ((struct clast_assignment *)t)->RHS; - - /* Create an entry (clast_var, type). */ - tmp.cloog_iv = find_cloog_iv_in_expr (expr); - if (!tmp.cloog_iv) - continue; + edge true_e = get_true_edge_from_guard_bb (next_e->dest); + edge false_e = get_false_edge_from_guard_bb (next_e->dest); + edge exit_true_e = single_succ_edge (true_e->dest); + edge exit_false_e = single_succ_edge (false_e->dest); - slot = htab_find_slot (GBB_CLOOG_IV_TYPES (gbb), &tmp, INSERT); + htab_t before_guard = htab_create (10, rename_map_elt_info, + eq_rename_map_elts, free); + htab_traverse (rename_map, copy_renames, before_guard); - if (!*slot) - { - tree oldiv = pbb_to_depth_to_oldiv (pbb, index); - tree type = oldiv ? TREE_TYPE (oldiv) : integer_type_node; - *slot = new_ivtype_map_elt (tmp.cloog_iv, type); - } - } + next_e = translate_clast (region, context_loop, stmt->then, true_e, + rename_map, newivs, newivs_index, bb_pbb_mapping, + level, params_index); + + insert_guard_phis (last_e->src, exit_true_e, exit_false_e, + before_guard, rename_map); + + htab_delete (before_guard); + + return last_e; } -/* Walk the CLAST tree starting from STMT and build for each - clast_user_stmt a map between the CLAST induction variables and the - corresponding GCC old induction variables. This information is - stored on each GRAPHITE_BB. */ +/* Translates a CLAST statement STMT to GCC representation in the + context of a SESE. -static void -compute_cloog_iv_types (struct clast_stmt *stmt) + - NEXT_E is the edge where new generated code should be attached. + - CONTEXT_LOOP is the loop in which the generated code will be placed + - RENAME_MAP contains a set of tuples of new names associated to + the original variables names. + - BB_PBB_MAPPING is is a basic_block and it's related poly_bb_p mapping. */ +static edge +translate_clast (sese region, loop_p context_loop, struct clast_stmt *stmt, + edge next_e, htab_t rename_map, VEC (tree, heap) **newivs, + htab_t newivs_index, htab_t bb_pbb_mapping, int level, + htab_t params_index) { if (!stmt) - return; + return next_e; if (CLAST_STMT_IS_A (stmt, stmt_root)) - goto next; - - if (CLAST_STMT_IS_A (stmt, stmt_user)) - { - CloogStatement *cs = ((struct clast_user_stmt *) stmt)->statement; - poly_bb_p pbb = (poly_bb_p) cloog_statement_usr (cs); - gimple_bb_p gbb = PBB_BLACK_BOX (pbb); - - if (!GBB_CLOOG_IV_TYPES (gbb)) - GBB_CLOOG_IV_TYPES (gbb) = htab_create (10, ivtype_map_elt_info, - eq_ivtype_map_elts, free); - - compute_cloog_iv_types_1 (pbb, (struct clast_user_stmt *) stmt); - goto next; - } - - if (CLAST_STMT_IS_A (stmt, stmt_for)) - { - struct clast_stmt *s = ((struct clast_for *) stmt)->body; - compute_cloog_iv_types (s); - goto next; - } - - if (CLAST_STMT_IS_A (stmt, stmt_guard)) - { - struct clast_stmt *s = ((struct clast_guard *) stmt)->then; - compute_cloog_iv_types (s); - goto next; - } - - if (CLAST_STMT_IS_A (stmt, stmt_block)) - { - struct clast_stmt *s = ((struct clast_block *) stmt)->body; - compute_cloog_iv_types (s); - goto next; - } + ; /* Do nothing. */ + + else if (CLAST_STMT_IS_A (stmt, stmt_user)) + next_e = translate_clast_user (region, (struct clast_user_stmt *) stmt, + next_e, rename_map, newivs, newivs_index, + bb_pbb_mapping, params_index); + + else if (CLAST_STMT_IS_A (stmt, stmt_for)) + next_e = translate_clast_for (region, context_loop, + (struct clast_for *) stmt, next_e, + rename_map, newivs, newivs_index, + bb_pbb_mapping, level, params_index); + + else if (CLAST_STMT_IS_A (stmt, stmt_guard)) + next_e = translate_clast_guard (region, context_loop, + (struct clast_guard *) stmt, next_e, + rename_map, newivs, newivs_index, + bb_pbb_mapping, level, params_index); + + else if (CLAST_STMT_IS_A (stmt, stmt_block)) + next_e = translate_clast (region, context_loop, + ((struct clast_block *) stmt)->body, + next_e, rename_map, newivs, newivs_index, + bb_pbb_mapping, level, params_index); + else + gcc_unreachable(); - gcc_unreachable (); + recompute_all_dominators (); + graphite_verify (); - next: - compute_cloog_iv_types (stmt->next); + return translate_clast (region, context_loop, stmt->next, next_e, + rename_map, newivs, newivs_index, + bb_pbb_mapping, level, params_index); } /* Free the SCATTERING domain list. */ @@ -855,14 +1266,30 @@ initialize_cloog_names (scop_p scop, CloogProgram *prog) int i; int nb_iterators = scop_max_loop_depth (scop); int nb_scattering = cloog_program_nb_scattdims (prog); + int nb_parameters = VEC_length (tree, SESE_PARAMS (region)); char **iterators = XNEWVEC (char *, nb_iterators * 2); char **scattering = XNEWVEC (char *, nb_scattering); + char **parameters= XNEWVEC (char *, nb_parameters); cloog_program_set_names (prog, cloog_names_malloc ()); - cloog_names_set_nb_parameters (cloog_program_names (prog), - VEC_length (tree, SESE_PARAMS (region))); - cloog_names_set_parameters (cloog_program_names (prog), - SESE_PARAMS_NAMES (region)); + + for (i = 0; i < nb_parameters; i++) + { + tree param = VEC_index (tree, SESE_PARAMS(region), i); + const char *name = get_name (param); + int len; + + if (!name) + name = "T"; + + len = strlen (name); + len += 17; + parameters[i] = XNEWVEC (char, len + 1); + snprintf (parameters[i], len, "%s_%d", name, SSA_NAME_VERSION (param)); + } + + cloog_names_set_nb_parameters (cloog_program_names (prog), nb_parameters); + cloog_names_set_parameters (cloog_program_names (prog), parameters); for (i = 0; i < nb_iterators; i++) { @@ -921,7 +1348,7 @@ build_cloog_prog (scop_p scop, CloogProgram *prog) continue; /* Build the new statement and its block. */ - stmt = cloog_statement_alloc (GBB_BB (PBB_BLACK_BOX (pbb))->index); + stmt = cloog_statement_alloc (pbb_index (pbb)); block = cloog_block_alloc (stmt, 0, NULL, pbb_dim_iter_domain (pbb)); cloog_statement_set_usr (stmt, pbb); @@ -1109,41 +1536,18 @@ debug_generated_program (scop_p scop) print_generated_program (stderr, scop); } -/* A LOOP is in normal form for Graphite when it contains only one - scalar phi node that defines the main induction variable of the - loop, only one increment of the IV, and only one exit condition. */ - -static void -graphite_loop_normal_form (loop_p loop) -{ - struct tree_niter_desc niter; - tree nit; - gimple_seq stmts; - edge exit = single_dom_exit (loop); - - bool known_niter = number_of_iterations_exit (loop, exit, &niter, false); - - /* At this point we should know the number of iterations, */ - gcc_assert (known_niter); - - nit = force_gimple_operand (unshare_expr (niter.niter), &stmts, true, - NULL_TREE); - if (stmts) - gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts); - - loop->aux = canonicalize_loop_ivs (loop, &nit); -} - -/* Converts REGION to loop normal form: one induction variable per loop. */ +/* Add CLooG names to parameter index. The index is used to translate + back from CLooG names to GCC trees. */ static void -build_graphite_loop_normal_form (sese region) -{ +create_params_index (htab_t index_table, CloogProgram *prog) { + CloogNames* names = cloog_program_names (prog); + int nb_parameters = cloog_names_nb_parameters (names); + char **parameters = cloog_names_parameters (names); int i; - loop_p loop; - for (i = 0; VEC_iterate (loop_p, SESE_LOOP_NEST (region), i, loop); i++) - graphite_loop_normal_form (loop); + for (i = 0; i < nb_parameters; i++) + save_clast_name_index (index_table, parameters[i], i); } /* GIMPLE Loop Generator: generates loops from STMT in GIMPLE form for @@ -1152,15 +1556,20 @@ build_graphite_loop_normal_form (sese region) */ bool -gloog (scop_p scop, htab_t bb_pbb_mapping) +gloog (scop_p scop, VEC (scop_p, heap) *scops, htab_t bb_pbb_mapping) { - edge new_scop_exit_edge = NULL; VEC (tree, heap) *newivs = VEC_alloc (tree, heap, 10); loop_p context_loop; sese region = SCOP_REGION (scop); ifsese if_region = NULL; - htab_t rename_map, newivs_index; - cloog_prog_clast pc = scop_to_clast (scop); + htab_t rename_map, newivs_index, params_index; + cloog_prog_clast pc; + int i; + + timevar_push (TV_GRAPHITE_CODE_GEN); + gloog_error = false; + + pc = scop_to_clast (scop); if (dump_file && (dump_flags & TDF_DETAILS)) { @@ -1169,7 +1578,6 @@ gloog (scop_p scop, htab_t bb_pbb_mapping) fprintf (dump_file, "\n"); } - build_graphite_loop_normal_form (region); recompute_all_dominators (); graphite_verify (); @@ -1178,140 +1586,66 @@ gloog (scop_p scop, htab_t bb_pbb_mapping) if_region->region->exit->src, if_region->false_region->exit, if_region->true_region->exit); - recompute_all_dominators (); graphite_verify (); - context_loop = SESE_ENTRY (region)->src->loop_father; - compute_cloog_iv_types (pc.stmt); + context_loop = SESE_ENTRY (region)->src->loop_father; rename_map = htab_create (10, rename_map_elt_info, eq_rename_map_elts, free); newivs_index = htab_create (10, clast_name_index_elt_info, eq_clast_name_indexes, free); + params_index = htab_create (10, clast_name_index_elt_info, + eq_clast_name_indexes, free); - new_scop_exit_edge = translate_clast (region, context_loop, pc.stmt, - if_region->true_region->entry, - rename_map, &newivs, newivs_index, - bb_pbb_mapping); - sese_reset_aux_in_loops (region); + create_params_index (params_index, pc.prog); + + translate_clast (region, context_loop, pc.stmt, + if_region->true_region->entry, + rename_map, &newivs, newivs_index, + bb_pbb_mapping, 1, params_index); graphite_verify (); sese_adjust_liveout_phis (region, rename_map, if_region->region->exit->src, if_region->false_region->exit, if_region->true_region->exit); + scev_reset_htab (); + rename_nb_iterations (rename_map); + + for (i = 0; VEC_iterate (scop_p, scops, i, scop); i++) + rename_sese_parameters (rename_map, SCOP_REGION (scop)); + recompute_all_dominators (); graphite_verify (); + if (gloog_error) + set_ifsese_condition (if_region, integer_zero_node); + + free (if_region->true_region); + free (if_region->region); + free (if_region); + htab_delete (rename_map); htab_delete (newivs_index); + htab_delete (params_index); VEC_free (tree, heap, newivs); cloog_clast_free (pc.stmt); cloog_program_free (pc.prog); - return true; -} - - - -/* Find BB's related poly_bb_p in hash table BB_PBB_MAPPING. */ - -static poly_bb_p -find_pbb_via_hash (htab_t bb_pbb_mapping, basic_block bb) -{ - bb_pbb_def tmp; - PTR *slot; - - tmp.bb = bb; - slot = htab_find_slot (bb_pbb_mapping, &tmp, NO_INSERT); - - if (slot && *slot) - return ((bb_pbb_def *) *slot)->pbb; - - return NULL; -} - -/* Free loop->aux in newly created loops by translate_clast. */ - -void -free_aux_in_new_loops (void) -{ - loop_p loop; - loop_iterator li; - - FOR_EACH_LOOP (li, loop, 0) - { - if (!loop->aux) - continue; - free(loop->aux); - loop->aux = NULL; - } -} - -/* Check data dependency in LOOP. BB_PBB_MAPPING is a basic_block and - it's related poly_bb_p mapping. -*/ - -static bool -dependency_in_loop_p (loop_p loop, htab_t bb_pbb_mapping) -{ - unsigned i,j; - int level = 0; - basic_block *bbs = get_loop_body_in_dom_order (loop); - - level = *((int *)(loop->aux)); - - for (i = 0; i < loop->num_nodes; i++) - { - poly_bb_p pbb1 = find_pbb_via_hash (bb_pbb_mapping, bbs[i]); - - if (pbb1 == NULL) - continue; - - for (j = 0; j < loop->num_nodes; j++) - { - poly_bb_p pbb2 = find_pbb_via_hash (bb_pbb_mapping, bbs[j]); - - if (pbb2 == NULL) - continue; - - if (dependency_between_pbbs_p (pbb1, pbb2, level)) - { - free (bbs); - return true; - } - } - } - - free (bbs); + timevar_pop (TV_GRAPHITE_CODE_GEN); - return false; -} - -/* Mark loop as parallel if data dependency does not exist. - BB_PBB_MAPPING is a basic_block and it's related poly_bb_p mapping. -*/ - -void mark_loops_parallel (htab_t bb_pbb_mapping) -{ - loop_p loop; - loop_iterator li; - int num_no_dependency = 0; - - FOR_EACH_LOOP (li, loop, 0) + if (dump_file && (dump_flags & TDF_DETAILS)) { - if (!loop->aux) - continue; + loop_p loop; + loop_iterator li; + int num_no_dependency = 0; - if (!dependency_in_loop_p (loop, bb_pbb_mapping)) - { - loop->can_be_parallel = true; + FOR_EACH_LOOP (li, loop, 0) + if (loop->can_be_parallel) num_no_dependency++; - } - } - if (dump_file && (dump_flags & TDF_DETAILS)) - { fprintf (dump_file, "\n%d loops carried no dependency.\n", num_no_dependency); } + + return !gloog_error; } #endif