Commit 65b016eb by Aditya Kumar Committed by Sebastian Pop

Preserve the original program while using graphite.

Earlier, graphite used to translate portions of the original program after
scop-detection in order to represent the SCoP into polyhedral model.  This was
required because each basic block was represented as independent basic block in
the polyhedral model. So all the cross-basic-block dependencies were translated
out-of-ssa.

With this patch those dependencies are also exposed to the ISL, so there is no
need to modify the original structure of the program.

After this patch we should be able to enable graphite at some default
optimization level.

Highlights:
Remove cross bb scalar to array translation
For reductions, add support for more than just INT_CST
Early bailout on codegen.
Verify loop-closed ssa structure during copy of renames
The uses of exprs should come from bb which dominates the bb
Collect the init value of close phi in loop-guard
Do not follow vuses for close-phi, postpone loop-close phi until the
    corresponding loop-phi is processed
Bail out if no bb found to place cond/loop -phis
Move insertion of liveouts at the end of codegen
Insert loop-phis in the loop-header.

This patch passes regtest and bootstrap with BOOT_CFLAGS='-O2 -fgraphite-identity -floop-nest-optimize'

2015-11-11  Aditya Kumar  <aditya.k7@samsung.com>
      Sebastian Pop  <s.pop@samsung.com>

	* graphite-isl-ast-to-gimple.c (class translate_isl_ast_to_gimple):
	  New member codegen_error
	(translate_isl_ast_for_loop): Remove call to single_succ_edge and early return.
	(translate_isl_ast_node_user): Early return in case of error.
	(translate_isl_ast_to_gimple::translate_isl_ast): Same.
	(translate_isl_ast_to_gimple::translate_pending_phi_nodes): New.
	(add_parameters_to_ivs_params): Remove macro.
	(graphite_regenerate_ast_isl): Add if_region pointer to region.
	* graphite-poly.c (new_poly_dr): Remove macro.
	(print_pdr): Same.
	(new_gimple_poly_bb): Same.
	(free_gimple_poly_bb): Same.
	(print_scop_params): Same.
	* graphite-poly.h (struct poly_dr): Same.
	(struct poly_bb): Add new_bb.
	(gbb_from_bb): Remove dead code.
	(pbb_from_bb): Same.
	* graphite-scop-detection.c (parameter_index_in_region_1): Same.
	(parameter_index_in_region): Same.
	(find_scop_parameters): Same.
	(build_cross_bb_scalars_def): New.
	(build_cross_bb_scalars_use): New.
	(graphite_find_cross_bb_scalar_vars): New
	(try_generate_gimple_bb): Reads and Writes.
	(build_alias_set): Move.
	(gather_bbs::before_dom_children): Gather bbs visited.
	(build_scops): call build_alias_set.
	* graphite-sese-to-poly.c (phi_arg_in_outermost_loop): Delete.
	(remove_simple_copy_phi): Delete.
	(remove_invariant_phi): Delete.
	(simple_copy_phi_p): Delete.
	(reduction_phi_p): Delete.
	(isl_id_for_dr): Remove unused param.
	(parameter_index_in_region_1): Remove macro usage.
	(set_scop_parameter_dim): Same.
	(add_param_constraints): Same.
	(add_conditions_to_constraints): Same
	(build_scop_iteration_domain): Same.
	(pdr_add_alias_set): Comment.
	(add_scalar_version_numbers): New.
	(build_poly_dr): ISL id.
	(build_scop_drs): Move.
	(build_poly_sr_1): Same.
	(insert_stmts): Remove.
	(build_poly_sr): New.
	(new_pbb_from_pbb): Delete.
	(insert_out_of_ssa_copy_on_edge): Delete.
	(create_zero_dim_array): Delete.
	(scalar_close_phi_node_p): Delete.
	(propagate_expr_outside_region): Delete.
	(rewrite_close_phi_out_of_ssa): Delete.
	(rewrite_phi_out_of_ssa): Delete.
	(rewrite_degenerate_phi): Delete.
	(rewrite_reductions_out_of_ssa): Delete.
	(rewrite_cross_bb_scalar_dependence): Delete.
	(handle_scalar_deps_crossing_scop_limits):
	(rewrite_cross_bb_scalar_deps): Delete.
	(build_poly_scop): Remove calls to out-of-ssa functions.
	* graphite.c (graphite_transform_loops): Early return in case of codegen error.
	* sese.c (debug_rename_map_1): Delete.
	(debug_rename_map): Delete.
	(sese_record_loop): Remove macro.
	(build_sese_loop_nests): Same.
	(new_sese_info): Same.
	(free_sese_info): Same.
	(sese_insert_phis_for_liveouts):
	(is_loop_closed_ssa_use): New.
	(number_of_phi_nodes): New.
	(bb_contains_loop_close_phi_nodes): New.
	(bb_contains_loop_phi_nodes): New.
	(phi_uses_name): New.
	(is_valid_rename):
	(get_rename): Add old_bb and loop_phi for more precise matching of
	exprs.
	(set_rename): Pass region.
	(later_of_the_two): New.
	(gsi_insert_earliest): New.
	(collect_all_ssa_names): New.
	(substitute_ssa_name): New.
	(rename_all_uses): New.
	(get_rename_from_scev): New.
	(rename_uses): Pass old_bb for more precise matching of exprs.
	(get_def_bb_for_const): New.
	(get_new_name): New.
	(get_loc): New.
	(get_edges): New.
	(copy_loop_phi_args): New.
	(copy_loop_phi_nodes): New.
	(get_loop_init_value): New.
	(find_init_value): New.
	(find_init_value_close_phi): New.
	(copy_loop_close_phi_args): New.
	(copy_loop_close_phi_nodes): New.
	(add_phi_arg_for_new_expr): New.
	(copy_cond_phi_args): New.
	(copy_cond_phi_nodes): New.
	(copy_phi_nodes): New.
	(should_copy_to_new_region): New.
	(set_rename_for_each_def): New.
	(graphite_copy_stmts_from_block): Early return in case of error.
	(copy_bb_and_scalar_dependences): Same.
	* sese.h (vec_find): New.
	(SESE_PARAMS): Delete.
	(SESE_LOOPS): Delete.
	(SESE_LOOP_NEST): Delete.
	(sese_contains_loop): Remove macro usage.
	(sese_nb_params): Same.
	(struct gimple_poly_bb): Added read_scalar_refs, write_scalar_refs.

Co-Authored-By: Sebastian Pop <s.pop@samsung.com>

From-SVN: r230200
parent f891c4f0
2015-11-11 Aditya Kumar <aditya.k7@samsung.com>
Sebastian Pop <s.pop@samsung.com>
* graphite-isl-ast-to-gimple.c (class translate_isl_ast_to_gimple):
New member codegen_error
(translate_isl_ast_for_loop): Remove call to single_succ_edge and
early return.
(translate_isl_ast_node_user): Early return in case of error.
(translate_isl_ast_to_gimple::translate_isl_ast): Same.
(translate_isl_ast_to_gimple::translate_pending_phi_nodes): New.
(add_parameters_to_ivs_params): Remove macro.
(graphite_regenerate_ast_isl): Add if_region pointer to region.
* graphite-poly.c (new_poly_dr): Remove macro.
(print_pdr): Same.
(new_gimple_poly_bb): Same.
(free_gimple_poly_bb): Same.
(print_scop_params): Same.
* graphite-poly.h (struct poly_dr): Same.
(struct poly_bb): Add new_bb.
(gbb_from_bb): Remove dead code.
(pbb_from_bb): Same.
* graphite-scop-detection.c (parameter_index_in_region_1): Same.
(parameter_index_in_region): Same.
(find_scop_parameters): Same.
(build_cross_bb_scalars_def): New.
(build_cross_bb_scalars_use): New.
(graphite_find_cross_bb_scalar_vars): New
(try_generate_gimple_bb): Reads and Writes.
(build_alias_set): Move.
(gather_bbs::before_dom_children): Gather bbs visited.
(build_scops): call build_alias_set.
* graphite-sese-to-poly.c (phi_arg_in_outermost_loop): Delete.
(remove_simple_copy_phi): Delete.
(remove_invariant_phi): Delete.
(simple_copy_phi_p): Delete.
(reduction_phi_p): Delete.
(isl_id_for_dr): Remove unused param.
(parameter_index_in_region_1): Remove macro usage.
(set_scop_parameter_dim): Same.
(add_param_constraints): Same.
(add_conditions_to_constraints): Same
(build_scop_iteration_domain): Same.
(pdr_add_alias_set): Comment.
(add_scalar_version_numbers): New.
(build_poly_dr): ISL id.
(build_scop_drs): Move.
(build_poly_sr_1): Same.
(insert_stmts): Remove.
(build_poly_sr): New.
(new_pbb_from_pbb): Delete.
(insert_out_of_ssa_copy_on_edge): Delete.
(create_zero_dim_array): Delete.
(scalar_close_phi_node_p): Delete.
(propagate_expr_outside_region): Delete.
(rewrite_close_phi_out_of_ssa): Delete.
(rewrite_phi_out_of_ssa): Delete.
(rewrite_degenerate_phi): Delete.
(rewrite_reductions_out_of_ssa): Delete.
(rewrite_cross_bb_scalar_dependence): Delete.
(handle_scalar_deps_crossing_scop_limits):
(rewrite_cross_bb_scalar_deps): Delete.
(build_poly_scop): Remove calls to out-of-ssa functions.
* graphite.c (graphite_transform_loops): Early return in case of
codegen error.
* sese.c (debug_rename_map_1): Delete.
(debug_rename_map): Delete.
(sese_record_loop): Remove macro.
(build_sese_loop_nests): Same.
(new_sese_info): Same.
(free_sese_info): Same.
(sese_insert_phis_for_liveouts):
(is_loop_closed_ssa_use): New.
(number_of_phi_nodes): New.
(bb_contains_loop_close_phi_nodes): New.
(bb_contains_loop_phi_nodes): New.
(phi_uses_name): New.
(is_valid_rename):
(get_rename): Add old_bb and loop_phi for more precise matching of
exprs.
(set_rename): Pass region.
(later_of_the_two): New.
(gsi_insert_earliest): New.
(collect_all_ssa_names): New.
(substitute_ssa_name): New.
(rename_all_uses): New.
(get_rename_from_scev): New.
(rename_uses): Pass old_bb for more precise matching of exprs.
(get_def_bb_for_const): New.
(get_new_name): New.
(get_loc): New.
(get_edges): New.
(copy_loop_phi_args): New.
(copy_loop_phi_nodes): New.
(get_loop_init_value): New.
(find_init_value): New.
(find_init_value_close_phi): New.
(copy_loop_close_phi_args): New.
(copy_loop_close_phi_nodes): New.
(add_phi_arg_for_new_expr): New.
(copy_cond_phi_args): New.
(copy_cond_phi_nodes): New.
(copy_phi_nodes): New.
(should_copy_to_new_region): New.
(set_rename_for_each_def): New.
(graphite_copy_stmts_from_block): Early return in case of error.
(copy_bb_and_scalar_dependences): Same.
* sese.h (vec_find): New.
(SESE_PARAMS): Delete.
(SESE_LOOPS): Delete.
(SESE_LOOP_NEST): Delete.
(sese_contains_loop): Remove macro usage.
(sese_nb_params): Same.
(struct gimple_poly_bb): Added read_scalar_refs, write_scalar_refs.
2015-11-11 Abderrazek Zaafrani <a.zaafrani@samsung.com>
* graphite-sese-to-poly.c (build_scop_original_schedule): Call
......@@ -63,11 +63,7 @@ extern "C" {
#include <map>
#include "graphite-isl-ast-to-gimple.h"
#include "tree-cfg.h"
/* This flag is set when an error occurred during the translation of
ISL AST to Gimple. */
static bool graphite_regenerate_error;
#include "gimple-pretty-print.h"
/* We always try to use signed 128 bit types, but fall back to smaller types
in case a platform does not provide types of these sizes. In the future we
......@@ -132,7 +128,7 @@ class translate_isl_ast_to_gimple
{
public:
translate_isl_ast_to_gimple (sese_info_p r)
: region (r)
: region (r), codegen_error (false)
{ }
/* Translates an ISL AST node NODE to GCC representation in the
......@@ -261,8 +257,17 @@ class translate_isl_ast_to_gimple
void build_iv_mapping (vec<tree> iv_map, gimple_poly_bb_p gbb,
__isl_keep isl_ast_expr *user_expr, ivs_params &ip,
sese_l &region);
void translate_pending_phi_nodes (void);
bool codegen_error_p () { return codegen_error; }
private:
sese_info_p region;
/* This flag is set when an error occurred during the translation of ISL AST
to Gimple. */
bool codegen_error;
};
/* Return the tree variable that corresponds to the given isl ast identifier
......@@ -575,13 +580,15 @@ translate_isl_ast_for_loop (loop_p context_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. */
isl_ast_node *for_body = isl_ast_node_for_get_body (node_for);
next_e = translate_isl_ast (loop, for_body, to_body, ip);
isl_ast_node_free (for_body);
/* Early return if we failed to translate loop body. */
if (!next_e || codegen_error)
return NULL;
redirect_edge_succ_nodup (next_e, after);
set_immediate_dominator (CDI_DOMINATORS, next_e->dest, next_e->src);
......@@ -770,14 +777,17 @@ translate_isl_ast_node_user (__isl_keep isl_ast_node *node,
edge next_e, ivs_params &ip)
{
gcc_assert (isl_ast_node_get_type (node) == isl_ast_node_user);
isl_ast_expr *user_expr = isl_ast_node_user_get_expr (node);
isl_ast_expr *name_expr = isl_ast_expr_get_op_arg (user_expr, 0);
gcc_assert (isl_ast_expr_get_type (name_expr) == isl_ast_expr_id);
isl_id *name_id = isl_ast_expr_get_id (name_expr);
poly_bb_p pbb = (poly_bb_p) isl_id_get_user (name_id);
gcc_assert (pbb);
gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
vec<tree> iv_map;
isl_ast_expr_free (name_expr);
isl_id_free (name_id);
......@@ -785,6 +795,7 @@ translate_isl_ast_node_user (__isl_keep isl_ast_node *node,
"The entry block should not even appear within a scop");
int nb_loops = number_of_loops (cfun);
vec<tree> iv_map;
iv_map.create (nb_loops);
iv_map.safe_grow_cleared (nb_loops);
......@@ -793,23 +804,35 @@ translate_isl_ast_node_user (__isl_keep isl_ast_node *node,
if (dump_file)
{
fprintf (dump_file, "[codegen] copying");
fprintf (dump_file, "[codegen] copying from basic block\n");
print_loops_bb (dump_file, GBB_BB (gbb), 0, 3);
fprintf (dump_file, "\n[codegen] to new basic block\n");
print_loops_bb (dump_file, next_e->src, 0, 3);
}
next_e = copy_bb_and_scalar_dependences (GBB_BB (gbb),
pbb->scop->scop_info, next_e,
iv_map,
&graphite_regenerate_error);
&codegen_error);
if (codegen_error)
return NULL;
if (dump_file)
{
fprintf (dump_file, "[codegen] to");
fprintf (dump_file, "\n[codegen] (after copy) new basic block\n");
print_loops_bb (dump_file, next_e->src, 0, 3);
}
iv_map.release ();
mark_virtual_operands_for_renaming (cfun);
update_ssa (TODO_update_ssa);
if (dump_file)
{
fprintf (dump_file, "\n[codegen] (after update SSA) new basic block\n");
print_loops_bb (dump_file, next_e->src, 0, 3);
}
return next_e;
}
......@@ -881,6 +904,9 @@ translate_isl_ast_to_gimple::translate_isl_ast (loop_p context_loop,
__isl_keep isl_ast_node *node,
edge next_e, ivs_params &ip)
{
if (codegen_error)
return NULL;
switch (isl_ast_node_get_type (node))
{
case isl_ast_node_error:
......@@ -906,6 +932,47 @@ translate_isl_ast_to_gimple::translate_isl_ast (loop_p context_loop,
}
}
/* Patch the missing arguments of the phi nodes. */
void
translate_isl_ast_to_gimple::translate_pending_phi_nodes ()
{
int i;
phi_rename *rename;
FOR_EACH_VEC_ELT (region->incomplete_phis, i, rename)
{
gphi *old_phi = rename->first;
gphi *new_phi = rename->second;
basic_block old_bb = gimple_bb (old_phi);
basic_block new_bb = gimple_bb (new_phi);
/* First edge is the init edge and second is the back edge. */
init_back_edge_pair_t ibp_old_bb = get_edges (old_bb);
init_back_edge_pair_t ibp_new_bb = get_edges (new_bb);
if (dump_file)
{
fprintf (dump_file, "\n[codegen] translating pending old-phi: ");
print_gimple_stmt (dump_file, old_phi, 0, 0);
}
auto_vec <tree, 1> iv_map;
if (bb_contains_loop_phi_nodes (new_bb))
copy_loop_phi_args (old_phi, ibp_old_bb, new_phi,
ibp_new_bb, region, false);
else if (bb_contains_loop_close_phi_nodes (new_bb))
copy_loop_close_phi_args (old_bb, new_bb, region, false);
else if (!copy_cond_phi_args (old_phi, new_phi, iv_map, region, false))
gcc_unreachable ();
if (dump_file)
{
fprintf (dump_file, "[codegen] to new-phi: ");
print_gimple_stmt (dump_file, new_phi, 0, 0);
}
}
}
/* Prints NODE to FILE. */
void
......@@ -926,13 +993,13 @@ add_parameters_to_ivs_params (scop_p scop, ivs_params &ip)
{
sese_info_p region = scop->scop_info;
unsigned nb_parameters = isl_set_dim (scop->param_context, isl_dim_param);
gcc_assert (nb_parameters == SESE_PARAMS (region).length ());
gcc_assert (nb_parameters == region->params.length ());
unsigned i;
for (i = 0; i < nb_parameters; i++)
{
isl_id *tmp_id = isl_set_get_dim_id (scop->param_context,
isl_dim_param, i);
ip[tmp_id] = SESE_PARAMS (region)[i];
ip[tmp_id] = region->params[i];
}
}
......@@ -1101,7 +1168,6 @@ graphite_regenerate_ast_isl (scop_p scop)
ivs_params ip;
timevar_push (TV_GRAPHITE_CODE_GEN);
graphite_regenerate_error = false;
root_node = scop_to_isl_ast (scop, ip);
if (dump_file && (dump_flags & TDF_DETAILS))
......@@ -1115,30 +1181,47 @@ graphite_regenerate_ast_isl (scop_p scop)
graphite_verify ();
if_region = move_sese_in_condition (region);
sese_insert_phis_for_liveouts (region,
if_region->region->region.exit->src,
if_region->false_region->region.exit,
if_region->true_region->region.exit);
region->if_region = if_region;
recompute_all_dominators ();
graphite_verify ();
context_loop = region->region.entry->src->loop_father;
translate_isl_ast_to_gimple t(region);
edge e = single_succ_edge (if_region->true_region->region.entry->dest);
split_edge (e);
t.translate_isl_ast (context_loop, root_node, e, ip);
basic_block bb = split_edge (e);
/* Update the true_region exit edge. */
region->if_region->true_region->region.exit = single_succ_edge (bb);
t.translate_isl_ast (context_loop, root_node, e, ip);
if (t.codegen_error_p ())
{
if (dump_file)
fprintf (dump_file, "\n[codegen] unsuccessful, "
"reverting back to the original code.");
set_ifsese_condition (if_region, integer_zero_node);
}
else
{
t.translate_pending_phi_nodes ();
if (!t.codegen_error_p ())
{
sese_insert_phis_for_liveouts (region,
if_region->region->region.exit->src,
if_region->false_region->region.exit,
if_region->true_region->region.exit);
mark_virtual_operands_for_renaming (cfun);
update_ssa (TODO_update_ssa);
graphite_verify ();
scev_reset ();
recompute_all_dominators ();
graphite_verify ();
if (graphite_regenerate_error)
set_ifsese_condition (if_region, integer_zero_node);
}
else if (dump_file)
fprintf (dump_file, "\n[codegen] unsuccessful in translating "
"pending phis, reverting back to the original code.");
}
free (if_region->true_region);
free (if_region->region);
......@@ -1161,6 +1244,6 @@ graphite_regenerate_ast_isl (scop_p scop)
num_no_dependency);
}
return !graphite_regenerate_error;
return !t.codegen_error_p ();
}
#endif /* HAVE_isl */
......@@ -132,21 +132,19 @@ apply_poly_transforms (scop_p scop)
NB_SUBSCRIPTS. */
void
new_poly_dr (poly_bb_p pbb, enum poly_dr_type type, data_reference_p cdr,
graphite_dim_t nb_subscripts,
new_poly_dr (poly_bb_p pbb, gimple *stmt, enum poly_dr_type type,
isl_map *acc, isl_set *subscript_sizes)
{
static int id = 0;
poly_dr_p pdr = XNEW (struct poly_dr);
pdr->stmt = stmt;
PDR_ID (pdr) = id++;
PDR_NB_REFS (pdr) = 1;
PDR_PBB (pdr) = pbb;
pdr->accesses = acc;
pdr->subscript_sizes = subscript_sizes;
PDR_TYPE (pdr) = type;
PDR_CDR (pdr) = cdr;
PDR_NB_SUBSCRIPTS (pdr) = nb_subscripts;
PBB_DRS (pbb).safe_push (pdr);
}
......@@ -226,6 +224,8 @@ print_pdr (FILE *file, poly_dr_p pdr)
gcc_unreachable ();
}
fprintf (file, "in gimple stmt: ");
print_gimple_stmt (file, pdr->stmt, 0, 0);
fprintf (file, "data accesses: ");
print_isl_map (file, pdr->accesses);
fprintf (file, "subscript sizes: ");
......@@ -244,14 +244,14 @@ debug_pdr (poly_dr_p pdr)
/* Store the GRAPHITE representation of BB. */
gimple_poly_bb_p
new_gimple_poly_bb (basic_block bb, vec<data_reference_p> drs)
new_gimple_poly_bb (basic_block bb, vec<data_reference_p> drs,
vec<scalar_use> reads, vec<tree> writes)
{
gimple_poly_bb_p gbb;
gbb = XNEW (struct gimple_poly_bb);
bb->aux = gbb;
gimple_poly_bb_p gbb = XNEW (struct gimple_poly_bb);
GBB_BB (gbb) = bb;
GBB_DATA_REFS (gbb) = drs;
gbb->read_scalar_refs = reads;
gbb->write_scalar_refs = writes;
GBB_CONDITIONS (gbb).create (0);
GBB_CONDITION_CASES (gbb).create (0);
......@@ -264,10 +264,10 @@ void
free_gimple_poly_bb (gimple_poly_bb_p gbb)
{
free_data_refs (GBB_DATA_REFS (gbb));
GBB_CONDITIONS (gbb).release ();
GBB_CONDITION_CASES (gbb).release ();
GBB_BB (gbb)->aux = 0;
gbb->read_scalar_refs.release ();
gbb->write_scalar_refs.release ();
XDELETE (gbb);
}
......@@ -477,13 +477,13 @@ print_pbb (FILE *file, poly_bb_p pbb)
void
print_scop_params (FILE *file, scop_p scop)
{
if (SESE_PARAMS (scop->scop_info).is_empty ())
if (scop->scop_info->params.is_empty ())
return;
int i;
tree t;
fprintf (file, "parameters (");
FOR_EACH_VEC_ELT (SESE_PARAMS (scop->scop_info), i, t)
FOR_EACH_VEC_ELT (scop->scop_info->params, i, t)
{
print_generic_expr (file, t, 0);
fprintf (file, ", ");
......
......@@ -58,8 +58,8 @@ struct poly_dr
/* The number of data refs identical to this one in the PBB. */
int nb_refs;
/* A pointer to compiler's data reference description. */
data_reference_p compiler_dr;
/* A pointer to the gimple stmt containing this reference. */
gimple *stmt;
/* A pointer to the PBB that contains this data reference. */
poly_bb_p pbb;
......@@ -181,21 +181,16 @@ struct poly_dr
In the example, the vector "R C O I L P" is "7 7 3 2 0 1". */
isl_map *accesses;
isl_set *subscript_sizes;
/* The number of subscripts. */
graphite_dim_t nb_subscripts;
};
#define PDR_ID(PDR) (PDR->id)
#define PDR_NB_REFS(PDR) (PDR->nb_refs)
#define PDR_CDR(PDR) (PDR->compiler_dr)
#define PDR_PBB(PDR) (PDR->pbb)
#define PDR_TYPE(PDR) (PDR->type)
#define PDR_ACCESSES(PDR) (NULL)
#define PDR_NB_SUBSCRIPTS(PDR) (PDR->nb_subscripts)
void new_poly_dr (poly_bb_p, enum poly_dr_type, data_reference_p,
graphite_dim_t, isl_map *, isl_set *);
void new_poly_dr (poly_bb_p, gimple *, enum poly_dr_type,
isl_map *, isl_set *);
void free_poly_dr (poly_dr_p);
void debug_pdr (poly_dr_p);
void print_pdr (FILE *, poly_dr_p);
......@@ -270,6 +265,9 @@ struct poly_bb
/* True when this PBB contains only a reduction statement. */
bool is_reduction;
/* The last basic block generated for this pbb. */
basic_block new_bb;
};
#define PBB_BLACK_BOX(PBB) ((gimple_poly_bb_p) PBB->black_box)
......@@ -314,22 +312,6 @@ extern bool optimize_isl (scop_p);
extern void pbb_number_of_iterations_at_time (poly_bb_p, graphite_dim_t, mpz_t);
extern void debug_gmp_value (mpz_t);
/* Returns a gimple_bb from BB. */
static inline gimple_poly_bb_p
gbb_from_bb (basic_block bb)
{
return (gimple_poly_bb_p) bb->aux;
}
/* The poly_bb of the BB. */
static inline poly_bb_p
pbb_from_bb (basic_block bb)
{
return GBB_PBB (gbb_from_bb (bb));
}
/* The basic block of the PBB. */
static inline basic_block
......@@ -446,7 +428,8 @@ struct scop
extern scop_p new_scop (edge, edge);
extern void free_scop (scop_p);
extern gimple_poly_bb_p new_gimple_poly_bb (basic_block, vec<data_reference_p>);
extern gimple_poly_bb_p new_gimple_poly_bb (basic_block, vec<data_reference_p>,
vec<scalar_use>, vec<tree>);
extern void free_gimple_poly_bb (gimple_poly_bb_p);
extern void print_generated_program (FILE *, scop_p);
extern void debug_generated_program (scop_p);
......
......@@ -1507,7 +1507,7 @@ parameter_index_in_region_1 (tree name, sese_info_p region)
gcc_assert (TREE_CODE (name) == SSA_NAME);
FOR_EACH_VEC_ELT (SESE_PARAMS (region), i, p)
FOR_EACH_VEC_ELT (region->params, i, p)
if (p == name)
return i;
......@@ -1536,8 +1536,8 @@ parameter_index_in_region (tree name, sese_info_p region)
if (i != -1)
return i;
i = SESE_PARAMS (region).length ();
SESE_PARAMS (region).safe_push (name);
i = region->params.length ();
region->params.safe_push (name);
return i;
}
......@@ -1635,7 +1635,7 @@ find_scop_parameters (scop_p scop)
struct loop *loop;
/* Find the parameters used in the loop bounds. */
FOR_EACH_VEC_ELT (SESE_LOOP_NEST (region), i, loop)
FOR_EACH_VEC_ELT (region->loop_nest, i, loop)
{
tree nb_iters = number_of_latch_executions (loop);
......@@ -1655,6 +1655,94 @@ find_scop_parameters (scop_p scop)
scop_set_nb_params (scop, nbp);
}
/* Record DEF if it is used in other bbs different than DEF_BB in the SCOP. */
static void
build_cross_bb_scalars_def (scop_p scop, tree def, basic_block def_bb,
vec<tree> *writes)
{
gcc_assert (def);
if (!is_gimple_reg (def))
return;
/* Do not gather scalar variables that can be analyzed by SCEV as they can be
generated out of the induction variables. */
if (scev_analyzable_p (def, scop->scop_info->region))
return;
gimple *use_stmt;
imm_use_iterator imm_iter;
FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, def)
if (def_bb != gimple_bb (use_stmt) && !is_gimple_debug (use_stmt))
{
writes->safe_push (def);
DEBUG_PRINT (dp << "Adding scalar write:\n";
print_generic_expr (dump_file, def, 0);
dp << "From stmt:\n";
print_gimple_stmt (dump_file,
SSA_NAME_DEF_STMT (def), 0, 0));
/* This is required by the FOR_EACH_IMM_USE_STMT when we want to break
before all the uses have been visited. */
BREAK_FROM_IMM_USE_STMT (imm_iter);
}
}
/* Record DEF if it is used in other bbs different than DEF_BB in the SCOP. */
static void
build_cross_bb_scalars_use (scop_p scop, tree use, gimple *use_stmt,
vec<scalar_use> *reads)
{
gcc_assert (use);
if (!is_gimple_reg (use))
return;
/* Do not gather scalar variables that can be analyzed by SCEV as they can be
generated out of the induction variables. */
if (scev_analyzable_p (use, scop->scop_info->region))
return;
gimple *def_stmt = SSA_NAME_DEF_STMT (use);
if (gimple_bb (def_stmt) != gimple_bb (use_stmt))
{
DEBUG_PRINT (dp << "Adding scalar read:\n";
print_generic_expr (dump_file, use, 0);
dp << "From stmt:\n";
print_gimple_stmt (dump_file, use_stmt, 0, 0));
reads->safe_push (std::make_pair (use_stmt, use));
}
}
/* Record all scalar variables that are defined and used in different BBs of the
SCOP. */
static void
graphite_find_cross_bb_scalar_vars (scop_p scop, gimple *stmt,
vec<scalar_use> *reads, vec<tree> *writes)
{
tree def;
if (gimple_code (stmt) == GIMPLE_ASSIGN)
def = gimple_assign_lhs (stmt);
else if (gimple_code (stmt) == GIMPLE_CALL)
def = gimple_call_lhs (stmt);
else if (gimple_code (stmt) == GIMPLE_PHI)
def = gimple_phi_result (stmt);
else
return;
build_cross_bb_scalars_def (scop, def, gimple_bb (stmt), writes);
ssa_op_iter iter;
use_operand_p use_p;
FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
{
tree use = USE_FROM_PTR (use_p);
build_cross_bb_scalars_use (scop, use, stmt, reads);
}
}
/* Generates a polyhedral black box only if the bb contains interesting
information. */
......@@ -1662,7 +1750,12 @@ static gimple_poly_bb_p
try_generate_gimple_bb (scop_p scop, basic_block bb)
{
vec<data_reference_p> drs;
drs.create (5);
drs.create (3);
vec<tree> writes;
writes.create (3);
vec<scalar_use> reads;
reads.create (3);
sese_l region = scop->scop_info->region;
loop_p nest = outermost_loop_in_sese (region, bb);
......@@ -1670,17 +1763,58 @@ try_generate_gimple_bb (scop_p scop, basic_block bb)
if (!loop_in_sese_p (loop, region))
loop = nest;
gimple_stmt_iterator gsi;
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
gsi_next (&gsi))
{
gimple *stmt = gsi_stmt (gsi);
if (is_gimple_debug (stmt))
continue;
graphite_find_data_references_in_stmt (nest, loop, stmt, &drs);
graphite_find_cross_bb_scalar_vars (scop, stmt, &reads, &writes);
}
return new_gimple_poly_bb (bb, drs);
for (gphi_iterator psi = gsi_start_phis (bb); !gsi_end_p (psi);
gsi_next (&psi))
if (!virtual_operand_p (gimple_phi_result (psi.phi ())))
graphite_find_cross_bb_scalar_vars (scop, psi.phi (), &reads, &writes);
if (drs.is_empty () && writes.is_empty () && reads.is_empty ())
return NULL;
return new_gimple_poly_bb (bb, drs, reads, writes);
}
/* Compute alias-sets for all data references in DRS. */
static void
build_alias_set (scop_p scop)
{
int num_vertices = scop->drs.length ();
struct graph *g = new_graph (num_vertices);
dr_info *dr1, *dr2;
int i, j;
int *all_vertices;
FOR_EACH_VEC_ELT (scop->drs, i, dr1)
for (j = i+1; scop->drs.iterate (j, &dr2); j++)
if (dr_may_alias_p (dr1->dr, dr2->dr, true))
{
add_edge (g, i, j);
add_edge (g, j, i);
}
all_vertices = XNEWVEC (int, num_vertices);
for (i = 0; i < num_vertices; i++)
all_vertices[i] = i;
graphds_dfs (g, all_vertices, num_vertices, NULL, true, NULL);
free (all_vertices);
for (i = 0; i < g->n_vertices; i++)
scop->drs[i].alias_set = g->vertices[i].component + 1;
free_graph (g);
}
/* Gather BBs and conditions for a SCOP. */
......@@ -1728,11 +1862,19 @@ gather_bbs::before_dom_children (basic_block bb)
scop->scop_info->bbs.safe_push (bb);
gimple_poly_bb_p gbb = try_generate_gimple_bb (scop, bb);
if (!gbb)
return;
GBB_CONDITIONS (gbb) = conditions.copy ();
GBB_CONDITION_CASES (gbb) = cases.copy ();
poly_bb_p pbb = new_poly_bb (scop, gbb);
scop->pbbs.safe_push (pbb);
int i;
data_reference_p dr;
FOR_EACH_VEC_ELT (gbb->data_refs, i, dr)
scop->drs.safe_push (dr_info (dr, pbb));
}
/* Call-back for dom_walk executed after visiting the dominated
......@@ -1776,6 +1918,8 @@ build_scops (vec<scop_p> *scops)
/* Record all basic blocks and their conditions in REGION. */
gather_bbs (CDI_DOMINATORS, scop).walk (cfun->cfg->x_entry_block_ptr);
build_alias_set (scop);
/* Do not optimize a scop containing only PBBs that do not belong
to any loops. */
if (sb.nb_pbbs_in_loops (scop) == 0)
......@@ -1807,7 +1951,6 @@ build_scops (vec<scop_p> *scops)
<< scop_nb_params (scop)
<< " larger than --param graphite-max-nb-scop-params="
<< max_dim << ".\n");
free_scop (scop);
continue;
}
......
......@@ -333,12 +333,16 @@ graphite_transform_loops (void)
if (dump_file && dump_flags)
print_scop (dump_file, scop);
if (scop->poly_scop_p
&& apply_poly_transforms (scop)
&& graphite_regenerate_ast_isl (scop))
&& apply_poly_transforms (scop))
{
need_cfg_cleanup_p = true;
/* When code generation is not successful, do not continue
generating code for the next scops: the IR has to be cleaned up
and could be in an inconsistent state. */
if (!graphite_regenerate_ast_isl (scop))
break;
}
}
free_scops (scops);
......
......@@ -22,6 +22,14 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_SESE_H
#define GCC_SESE_H
typedef hash_map<basic_block, vec<basic_block> > bb_map_t;
typedef hash_map<tree, vec<tree> > rename_map_t;
typedef struct ifsese_s *ifsese;
/* First phi is the new codegenerated phi second one is original phi. */
typedef std::pair <gphi *, gphi *> phi_rename;
/* First edge is the init edge and second is the back edge w.r.t. a loop. */
typedef std::pair<edge, edge> init_back_edge_pair_t;
/* A Single Entry, Single Exit region is a part of the CFG delimited
by two edges. */
struct sese_l
......@@ -50,6 +58,20 @@ get_exit_bb (sese_l &s)
return s.exit->src;
}
/* Returns the index of V where ELEM can be found. -1 Otherwise. */
template<typename T>
int
vec_find (const vec<T> &v, const T &elem)
{
int i;
T t;
FOR_EACH_VEC_ELT (v, i, t)
if (elem == t)
return i;
return -1;
}
/* A helper structure for bookkeeping information about a scop in graphite. */
typedef struct sese_info_t
{
......@@ -59,17 +81,29 @@ typedef struct sese_info_t
/* Parameters used within the SCOP. */
vec<tree> params;
/* Maps an old name to one or more new names. When there are several new
names, one has to select the definition corresponding to the immediate
dominator. */
rename_map_t *rename_map;
/* Loops completely contained in this SESE. */
bitmap loops;
vec<loop_p> loop_nest;
/* Basic blocks contained in this SESE. */
vec<basic_block> bbs;
} *sese_info_p;
#define SESE_PARAMS(S) (S->params)
#define SESE_LOOPS(S) (S->loops)
#define SESE_LOOP_NEST(S) (S->loop_nest)
/* Copied basic blocks indexed by the original bb. */
bb_map_t *copied_bb_map;
/* A vector of phi nodes to be updated when all arguments are available. The
pair contains first the old_phi and second the new_phi. */
vec<phi_rename> incomplete_phis;
/* The condition region generated for this sese. */
ifsese if_region;
} *sese_info_p;
extern sese_info_p new_sese_info (edge, edge);
extern void free_sese_info (sese_info_p);
......@@ -80,13 +114,23 @@ extern edge copy_bb_and_scalar_dependences (basic_block, sese_info_p, edge,
extern struct loop *outermost_loop_in_sese (sese_l &, basic_block);
extern tree scalar_evolution_in_region (sese_l &, loop_p, tree);
extern bool invariant_in_sese_p_rec (tree, sese_l &, bool *);
extern bool bb_contains_loop_phi_nodes (basic_block);
extern bool bb_contains_loop_close_phi_nodes (basic_block);
extern std::pair<edge, edge> get_edges (basic_block bb);
extern void copy_loop_phi_args (gphi *, init_back_edge_pair_t &,
gphi *, init_back_edge_pair_t &,
sese_info_p, bool);
extern bool copy_loop_close_phi_args (basic_block, basic_block,
sese_info_p, bool);
extern bool copy_cond_phi_args (gphi *, gphi *, vec<tree>,
sese_info_p, bool);
/* Check that SESE contains LOOP. */
static inline bool
sese_contains_loop (sese_info_p sese, struct loop *loop)
{
return bitmap_bit_p (SESE_LOOPS (sese), loop->num);
return bitmap_bit_p (sese->loops, loop->num);
}
/* The number of parameters in REGION. */
......@@ -94,7 +138,7 @@ sese_contains_loop (sese_info_p sese, struct loop *loop)
static inline unsigned
sese_nb_params (sese_info_p region)
{
return SESE_PARAMS (region).length ();
return region->params.length ();
}
/* Checks whether BB is contained in the region delimited by ENTRY and
......@@ -239,6 +283,8 @@ recompute_all_dominators (void)
calculate_dominance_info (CDI_POST_DOMINATORS);
}
typedef std::pair <gimple *, tree> scalar_use;
typedef struct gimple_poly_bb
{
basic_block bb;
......@@ -267,6 +313,8 @@ typedef struct gimple_poly_bb
vec<gimple *> conditions;
vec<gimple *> condition_cases;
vec<data_reference_p> data_refs;
vec<scalar_use> read_scalar_refs;
vec<tree> write_scalar_refs;
} *gimple_poly_bb_p;
#define GBB_BB(GBB) (GBB)->bb
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment