diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cc806091911..7983e984915 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,39 @@ +2008-10-15 Jan Sjodin + Harsha Jagasia + + PR tree-optimization/37485 + * graphite.c (gmp_cst_to_tree): Moved. + (iv_stack_entry_is_constant): New. + (iv_stack_entry_is_iv): New. + (loop_iv_stack_push): Renamed to loop_iv_stack_push_iv. + (loop_iv_stack_insert_constant): New. + (loop_iv_stack_pop): Use new datatpype. + (loop_iv_stack_get_iv): Same. + (loop_iv_stack_get_iv_from_name): Same. + (loop_iv_stack_debug): Renamed to debug_loop_iv_stack. + (loop_iv_stack_patch_for_consts): New. + (loop_iv_stack_remove_constants): New. + (graphite_create_new_loop): Use loop_iv_stack_push_iv. + (translate_clast): Call loop_iv_stack_patch_for_consts and + loop_iv_stack_remove_constants. + (gloog): Use new datatype. Redirect construction edge to end + block to avoid accidental deletion. + * graphite.h (enum iv_stack_entry_kind): New. Tag for data in + iv stack entry. + (union iv_stack_entry_data): New. Data in iv stack entry. + (struct iv_stack_entry): New. Datatype for iv stack entries. + +2008-10-15 Sebastian Pop + + * tree-data-ref.c (stmt_simple_memref_p): Fix memleak. + * graphite.c (free_scop): Same. + (build_scops): Same. + (free_scattering): New. + (build_cloog_prog): Call free_scattering. + (patch_phis_for_virtual_defs): Fix memleak. + (graphite_trans_bb_strip_mine): Same. + (limit_scops): Same. + 2008-10-15 Sebastian Pop Harsha Jagasia diff --git a/gcc/graphite.c b/gcc/graphite.c index c31c305cf99..18174eecd91 100644 --- a/gcc/graphite.c +++ b/gcc/graphite.c @@ -60,6 +60,14 @@ along with GCC; see the file COPYING3. If not see static VEC (scop_p, heap) *current_scops; +/* Converts a GMP constant V to a tree and returns it. */ + +static tree +gmp_cst_to_tree (Value v) +{ + return build_int_cst (integer_type_node, value_get_si (v)); +} + /* Debug the list of old induction variables for this SCOP. */ void @@ -95,24 +103,62 @@ debug_loop_vec (graphite_bb_p gb) fprintf (stderr, "\n"); } +/* Returns true if stack ENTRY is a constant. */ + +static bool +iv_stack_entry_is_constant (iv_stack_entry *entry) +{ + return entry->kind == iv_stack_entry_const; +} + +/* Returns true if stack ENTRY is an induction variable. */ + +static bool +iv_stack_entry_is_iv (iv_stack_entry *entry) +{ + return entry->kind == iv_stack_entry_iv; +} + /* Push (IV, NAME) on STACK. */ static void -loop_iv_stack_push (loop_iv_stack stack, tree iv, const char *name) +loop_iv_stack_push_iv (loop_iv_stack stack, tree iv, const char *name) { + iv_stack_entry *entry = XNEW (iv_stack_entry); name_tree named_iv = XNEW (struct name_tree); named_iv->t = iv; named_iv->name = name; - VEC_safe_push (name_tree, heap, *stack, named_iv); + + entry->kind = iv_stack_entry_iv; + entry->data.iv = named_iv; + + VEC_safe_push (iv_stack_entry_p, heap, *stack, entry); } -/* Pops an element out of STACK. */ +/* Inserts a CONSTANT in STACK at INDEX. */ + +static void +loop_iv_stack_insert_constant (loop_iv_stack stack, int index, + tree constant) +{ + iv_stack_entry *entry = XNEW (iv_stack_entry); + + entry->kind = iv_stack_entry_const; + entry->data.constant = constant; + + VEC_safe_insert (iv_stack_entry_p, heap, *stack, index, entry); +} + +/* Pops and frees an element out of STACK. */ static void loop_iv_stack_pop (loop_iv_stack stack) { - VEC_pop (name_tree, *stack); + iv_stack_entry_p entry = VEC_pop (iv_stack_entry_p, *stack); + + free (entry->data.iv); + free (entry); } /* Get the IV at INDEX in STACK. */ @@ -120,9 +166,14 @@ loop_iv_stack_pop (loop_iv_stack stack) static tree loop_iv_stack_get_iv (loop_iv_stack stack, int index) { - name_tree named_iv = VEC_index (name_tree, *stack, index); + iv_stack_entry_p entry = VEC_index (iv_stack_entry_p, *stack, index); - return named_iv->t; + tree result = NULL; + + if (entry->kind != iv_stack_entry_const) + result = entry->data.iv->t; + + return result; } /* Get the IV from its NAME in STACK. */ @@ -131,11 +182,14 @@ static tree loop_iv_stack_get_iv_from_name (loop_iv_stack stack, const char* name) { int i; - name_tree iv; + iv_stack_entry_p entry; - for (i = 0; VEC_iterate (name_tree, *stack, i, iv); i++) - if (!strcmp (name, iv->name)) - return iv->t; + for (i = 0; VEC_iterate (iv_stack_entry_p, *stack, i, entry); i++) + { + name_tree iv = entry->data.iv; + if (!strcmp (name, iv->name)) + return iv->t; + } return NULL; } @@ -143,27 +197,102 @@ loop_iv_stack_get_iv_from_name (loop_iv_stack stack, const char* name) /* Prints on stderr the contents of STACK. */ void -loop_iv_stack_debug (loop_iv_stack stack) +debug_loop_iv_stack (loop_iv_stack stack) { int i; - name_tree iv; + iv_stack_entry_p entry; bool first = true; fprintf (stderr, "("); - for (i = 0; VEC_iterate (name_tree, *stack, i, iv); i++) + for (i = 0; VEC_iterate (iv_stack_entry_p, *stack, i, entry); i++) { if (first) first = false; else fprintf (stderr, " "); - fprintf (stderr, "%s:", iv->name); - print_generic_expr (stderr, iv->t, 0); + + if (iv_stack_entry_is_iv (entry)) + { + name_tree iv = entry->data.iv; + fprintf (stderr, "%s:", iv->name); + print_generic_expr (stderr, iv->t, 0); + } + else + { + tree constant = entry->data.constant; + print_generic_expr (stderr, constant, 0); + fprintf (stderr, ":"); + print_generic_expr (stderr, constant, 0); + } } fprintf (stderr, ")\n"); } +/* Frees STACK. */ + +static void +free_loop_iv_stack (loop_iv_stack stack) +{ + int i; + iv_stack_entry_p entry; + + for (i = 0; VEC_iterate (iv_stack_entry_p, *stack, i, entry); i++) + { + free (entry->data.iv); + free (entry); + } + + VEC_free (iv_stack_entry_p, heap, *stack); +} + +/* Inserts constants derived from the USER_STMT argument list into the + STACK. This is needed to map old ivs to constants when loops have + been eliminated. */ + +static void +loop_iv_stack_patch_for_consts (loop_iv_stack stack, + struct clast_user_stmt *user_stmt) +{ + struct clast_stmt *t; + int index = 0; + for (t = user_stmt->substitutions; t; t = t->next) + { + struct clast_term *term = (struct clast_term*) + ((struct clast_assignment *)t)->RHS; + + /* FIXME: What should be done with expr_bin, expr_red? */ + if (((struct clast_assignment *)t)->RHS->type == expr_term + && !term->var) + { + tree value = gmp_cst_to_tree (term->val); + loop_iv_stack_insert_constant (stack, index, value); + } + index = index + 1; + } +} + +/* Removes all constants in the iv STACK. */ + +static void +loop_iv_stack_remove_constants (loop_iv_stack stack) +{ + int i; + iv_stack_entry *entry; + + for (i = 0; VEC_iterate (iv_stack_entry_p, *stack, i, entry);) + { + if (iv_stack_entry_is_constant (entry)) + { + free (VEC_index (iv_stack_entry_p, *stack, i)); + VEC_ordered_remove (iv_stack_entry_p, *stack, i); + } + else + i++; + } +} + /* In SCOP, get the induction variable from NAME. OLD is the original loop that contained the definition of NAME. */ @@ -939,6 +1068,7 @@ free_scop (scop_p scop) int i; name_tree p; struct graphite_bb *gb; + name_tree iv; for (i = 0; VEC_iterate (graphite_bb_p, SCOP_BBS (scop), i, gb); i++) free_graphite_bb (gb); @@ -947,6 +1077,9 @@ free_scop (scop_p scop) BITMAP_FREE (SCOP_BBS_B (scop)); BITMAP_FREE (SCOP_LOOPS (scop)); VEC_free (loop_p, heap, SCOP_LOOP_NEST (scop)); + + for (i = 0; VEC_iterate (name_tree, SCOP_OLDIVS (scop), i, iv); i++) + free (iv); VEC_free (name_tree, heap, SCOP_OLDIVS (scop)); for (i = 0; VEC_iterate (name_tree, SCOP_PARAMS (scop), i, p); i++) @@ -1688,6 +1821,7 @@ build_scops (void) build_scops_1 (single_succ (ENTRY_BLOCK_PTR), &tmp_scops, loop); create_sese_edges (tmp_scops); build_graphite_scops (tmp_scops); + VEC_free (sd_region, heap, tmp_scops); } /* Gather the basic blocks belonging to the SCOP. */ @@ -2433,7 +2567,7 @@ build_loop_iteration_domains (scop_p scop, struct loop *loop, value_assign (cstr->p[i][j], outer_cstr->p[i][j]); /* Leave an empty column in CSTR for the current loop, and then - copy the parameter columns. */ + copy the parameter columns. */ for (j = loop_col; j < outer_cstr->NbColumns; j++) value_assign (cstr->p[i][j + 1], outer_cstr->p[i][j]); } @@ -2861,10 +2995,10 @@ build_scop_iteration_domain (scop_p scop) -first column: eq/ineq boolean -last column: a constant -scop_nb_params columns for the parameters used in the scop. */ - outer_cstr = cloog_matrix_alloc (0, scop_nb_params (scop) + 2); - build_loop_iteration_domains (scop, loop, outer_cstr, 0); - cloog_matrix_free (outer_cstr); - } + outer_cstr = cloog_matrix_alloc (0, scop_nb_params (scop) + 2); + build_loop_iteration_domains (scop, loop, outer_cstr, 0); + cloog_matrix_free (outer_cstr); + } return (i != 0); } @@ -2988,14 +3122,6 @@ build_scop_data_accesses (scop_p scop) } } -/* Converts a GMP constant value to a tree and returns it. */ - -static tree -gmp_cst_to_tree (Value v) -{ - return build_int_cst (integer_type_node, value_get_si (v)); -} - /* Returns the tree variable from the name NAME that was given in Cloog representation. All the parameters are stored in PARAMS, and all the loop induction variables are stored in IVSTACK. @@ -3250,7 +3376,7 @@ graphite_create_new_loop (scop_p scop, edge entry_edge, &iv_before, outer ? outer : entry_edge->src->loop_father); - loop_iv_stack_push (ivstack, iv_before, stmt->iterator); + loop_iv_stack_push_iv (ivstack, iv_before, stmt->iterator); return loop; } @@ -3347,9 +3473,10 @@ expand_scalar_variables_expr (tree type, tree op0, enum tree_code code, tree op1, graphite_bb_p gbb, scop_p scop, loop_p old_loop_father, loop_iv_stack ivstack) { - if (TREE_CODE_CLASS (code) == tcc_constant - && code == INTEGER_CST) - return op0; + if ((TREE_CODE_CLASS (code) == tcc_constant + && code == INTEGER_CST) + || TREE_CODE_CLASS (code) == tcc_reference) + return op0; if (TREE_CODE_CLASS (code) == tcc_unary) { @@ -3596,8 +3723,11 @@ translate_clast (scop_p scop, struct loop *context_loop, mark_virtual_ops_in_bb (bb); next_e = make_edge (bb, context_loop ? context_loop->latch : EXIT_BLOCK_PTR, - EDGE_FALLTHRU);; + EDGE_FALLTHRU); + loop_iv_stack_patch_for_consts (ivstack, + (struct clast_user_stmt *) stmt); graphite_rename_ivs (gbb, scop, old_loop_father, ivstack); + loop_iv_stack_remove_constants (ivstack); return translate_clast (scop, context_loop, stmt->next, next_e, ivstack); } @@ -3643,6 +3773,22 @@ translate_clast (scop_p scop, struct loop *context_loop, gcc_unreachable (); } +/* Free the SCATTERING domain list. */ + +static void +free_scattering (CloogDomainList *scattering) +{ + while (scattering) + { + CloogDomain *dom = cloog_domain (scattering); + CloogDomainList *next = cloog_next_domain (scattering); + + cloog_domain_free (dom); + free (scattering); + scattering = next; + } +} + /* Build cloog program for SCoP. */ static void @@ -3725,6 +3871,7 @@ build_cloog_prog (scop_p scop) /* Apply scattering. */ cloog_program_scatter (prog, scattering); + free_scattering (scattering); /* Iterators corresponding to scalar dimensions have to be extracted. */ cloog_names_scalarize (cloog_program_names (prog), nbs, @@ -3806,7 +3953,6 @@ debug_clast_stmt (struct clast_stmt *stmt) static struct clast_stmt * find_transform (scop_p scop) { - CloogProgram *prog; struct clast_stmt *stmt; CloogOptions *options = set_cloog_options (); @@ -3820,14 +3966,14 @@ find_transform (scop_p scop) fprintf (dump_file, "]\n"); } - prog = cloog_program_generate (SCOP_PROG (scop), options); - stmt = cloog_clast_create (prog, options); + SCOP_PROG (scop) = cloog_program_generate (SCOP_PROG (scop), options); + stmt = cloog_clast_create (SCOP_PROG (scop), options); if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "Cloog Output[\n"); pprint (dump_file, stmt, 0, options); - cloog_program_dump_cloog (dump_file, prog); + cloog_program_dump_cloog (dump_file, SCOP_PROG (scop)); fprintf (dump_file, "]\n"); } @@ -3964,6 +4110,8 @@ patch_phis_for_virtual_defs (void) gsi = gsi_for_stmt (phi); remove_phi_node (&gsi, false); } + + VEC_free (gimple, heap, virtual_phis); } /* Mark the original loops of SCOP for removal, replacing their header @@ -4132,9 +4280,10 @@ gloog (scop_p scop, struct clast_stmt *stmt) { edge new_scop_exit_edge = NULL; basic_block scop_exit = SCOP_EXIT (scop); - VEC (tree, heap)* phi_args = + VEC (tree, heap) *phi_args = collect_scop_exit_phi_args (SESE_EXIT (SCOP_REGION (scop))); - VEC (name_tree, heap) *ivstack = VEC_alloc (name_tree, heap, 10); + VEC (iv_stack_entry_p, heap) *ivstack = + VEC_alloc (iv_stack_entry_p, heap, 10); edge construction_edge = SESE_ENTRY (SCOP_REGION (scop)); basic_block old_scop_exit_idom = get_immediate_dominator (CDI_DOMINATORS, scop_exit); @@ -4145,10 +4294,13 @@ gloog (scop_p scop, struct clast_stmt *stmt) return; } + redirect_edge_succ_nodup (construction_edge, EXIT_BLOCK_PTR); new_scop_exit_edge = translate_clast (scop, construction_edge->src->loop_father, stmt, construction_edge, &ivstack); + free_loop_iv_stack (&ivstack); redirect_edge_succ (new_scop_exit_edge, scop_exit); + if (!old_scop_exit_idom || !dominated_by_p (CDI_DOMINATORS, SCOP_ENTRY (scop), old_scop_exit_idom) @@ -4165,6 +4317,7 @@ gloog (scop_p scop, struct clast_stmt *stmt) delete_unreachable_blocks (); patch_phis_for_virtual_defs (); patch_scop_exit_phi_args (new_scop_exit_edge, phi_args); + VEC_free (tree, heap, phi_args); mark_old_loops (scop); remove_dead_loops (); rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa); @@ -4416,7 +4569,6 @@ static void get_lower_bound (CloogMatrix *domain, int loop, Value lower_bound_result) { int lower_bound_row = get_lower_bound_row (domain, loop); - value_init (lower_bound_result); value_assign (lower_bound_result, domain->p[lower_bound_row][const_column_index(domain)]); } @@ -4427,7 +4579,6 @@ static void get_upper_bound (CloogMatrix *domain, int loop, Value upper_bound_result) { int upper_bound_row = get_upper_bound_row (domain, loop); - value_init (upper_bound_result); value_assign (upper_bound_result, domain->p[upper_bound_row][const_column_index(domain)]); } @@ -4450,7 +4601,6 @@ graphite_trans_bb_strip_mine (graphite_bb_p gb, int loop_depth, int stride) Value old_lower_bound; Value old_upper_bound; - gcc_assert (loop_depth <= gbb_nb_loops (gb) - 1); VEC_safe_insert (loop_p, heap, GBB_LOOPS (gb), loop_depth, NULL); @@ -4470,13 +4620,9 @@ graphite_trans_bb_strip_mine (graphite_bb_p gb, int loop_depth, int stride) for (row = 0; row < domain->NbRows; row++) for (col = 0; col < domain->NbColumns; col++) if (col <= loop_depth) - { - value_assign (new_domain->p[row][col], domain->p[row][col]); - } + value_assign (new_domain->p[row][col], domain->p[row][col]); else - { - value_assign (new_domain->p[row][col + 1], domain->p[row][col]); - } + value_assign (new_domain->p[row][col + 1], domain->p[row][col]); /* @@ -4495,7 +4641,8 @@ graphite_trans_bb_strip_mine (graphite_bb_p gb, int loop_depth, int stride) row = domain->NbRows; /* Add outer loop. */ - + value_init (old_lower_bound); + value_init (old_upper_bound); get_lower_bound (new_domain, col_loop_old, old_lower_bound); get_upper_bound (new_domain, col_loop_old, old_upper_bound); @@ -4504,6 +4651,7 @@ graphite_trans_bb_strip_mine (graphite_bb_p gb, int loop_depth, int stride) value_set_si (new_domain->p[row][col_loop_strip], 1); value_assign (new_domain->p[row][const_column_index (new_domain)], old_lower_bound); + value_clear (old_lower_bound); row++; @@ -4524,12 +4672,10 @@ graphite_trans_bb_strip_mine (graphite_bb_p gb, int loop_depth, int stride) Value strip_size_value; value_init (new_upper_bound); - value_init (strip_size_value); value_set_si (strip_size_value, (int) stride); - - value_pdivision(new_upper_bound,old_upper_bound,strip_size_value); + value_pdivision (new_upper_bound, old_upper_bound, strip_size_value); value_add_int (new_upper_bound, new_upper_bound, 1); /* Set Upper Bound */ @@ -4537,6 +4683,10 @@ graphite_trans_bb_strip_mine (graphite_bb_p gb, int loop_depth, int stride) value_set_si (new_domain->p[row][col_loop_strip], -1); value_assign (new_domain->p[row][const_column_index (new_domain)], new_upper_bound); + + value_clear (strip_size_value); + value_clear (old_upper_bound); + value_clear (new_upper_bound); row++; } /* @@ -4983,6 +5133,7 @@ limit_scops (void) create_sese_edges (tmp_scops); build_graphite_scops (tmp_scops); + VEC_free (sd_region, heap, tmp_scops); } /* Perform a set of linear transforms on the loops of the current diff --git a/gcc/graphite.h b/gcc/graphite.h index 1a3cf6ccc65..2e2904a6abf 100644 --- a/gcc/graphite.h +++ b/gcc/graphite.h @@ -260,7 +260,7 @@ typedef struct name_tree { tree t; const char *name; - struct loop* loop; + struct loop *loop; } *name_tree; DEF_VEC_P(name_tree); @@ -340,8 +340,34 @@ extern void debug_clast_stmt (struct clast_stmt *); extern void debug_loop_vec (graphite_bb_p gb); extern void debug_oldivs (scop_p); -typedef VEC(name_tree, heap) **loop_iv_stack; -extern void loop_iv_stack_debug (loop_iv_stack); +/* Describes the type of an iv stack entry. */ +typedef enum { + iv_stack_entry_unknown = 0, + iv_stack_entry_iv, + iv_stack_entry_const +} iv_stack_entry_kind; + +/* Data contained in an iv stack entry. */ +typedef union iv_stack_entry_data_union +{ + name_tree iv; + tree constant; +} iv_stack_entry_data; + +/* Datatype for loop iv stack entry. */ +typedef struct iv_stack_entry_struct +{ + iv_stack_entry_kind kind; + iv_stack_entry_data data; +} iv_stack_entry; + +typedef iv_stack_entry *iv_stack_entry_p; + +DEF_VEC_P(iv_stack_entry_p); +DEF_VEC_ALLOC_P(iv_stack_entry_p,heap); + +typedef VEC(iv_stack_entry_p, heap) **loop_iv_stack; +extern void debug_loop_iv_stack (loop_iv_stack); /* Return the number of gimple loops contained in SCOP. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 91966c4a288..2647c955108 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2008-10-15 Jan Sjodin + Harsha Jagasia + + PR tree-optimization/37485 + * gcc.dg/graphite/pr37485.c: New. + 2008-10-15 Sebastian Pop Harsha Jagasia diff --git a/gcc/testsuite/gcc.dg/graphite/pr37485.c b/gcc/testsuite/gcc.dg/graphite/pr37485.c new file mode 100644 index 00000000000..67661910ba2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/graphite/pr37485.c @@ -0,0 +1,31 @@ +/* { dg-options "-O2 -floop-block -fdump-tree-graphite-all" } */ + +typedef unsigned char UChar; +typedef int Int32; +typedef unsigned int UInt32; + +void fallbackSort ( UInt32* fmap, + UInt32* eclass, + Int32 nblock, + Int32 verb ) +{ + Int32 ftab[257]; + Int32 ftabCopy[256]; + Int32 H, i, j, k, l, r, cc, cc1; + Int32 nNotDone; + Int32 nBhtab; + UChar* eclass8 = (UChar*)eclass; + + if (verb >= 4) + VPrintf0 ( " bucket sorting ...\n" ); + for (i = 0; i < 257; i++) ftab[i] = 0; + for (i = 0; i < nblock; i++) ftab[eclass8[i]]++; + for (i = 0; i < 256; i++) ftabCopy[i] = ftab[i]; + for (i = 1; i < 257; i++) ftab[i] += ftab[i-1]; + + for (i = 0; i < nblock; i++) { + j = eclass8[i] + ftab [i]; + } + AssertH ( j < 256, 1005 ); +} +/* { dg-final { scan-tree-dump-times "Loop blocked" 1 "graphite" { xfail *-*-* }} } */ diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c index 5a52d266e9b..94124141a25 100644 --- a/gcc/tree-data-ref.c +++ b/gcc/tree-data-ref.c @@ -3311,13 +3311,14 @@ bool stmt_simple_memref_p (struct loop *loop, gimple stmt, tree op) { data_reference_p dr; + bool res = true; dr = create_data_ref (loop, op, stmt, true); if (!access_functions_are_affine_or_constant_p (dr, loop)) - return false; + res = false; free_data_ref (dr); - return true; + return res; } /* Initializes an equation for an OMEGA problem using the information