Commit a68f286c by Richard Biener Committed by Richard Biener

re PR tree-optimization/82451 ([GRAPHITE] codegen error in get_rename_from_scev)

2017-10-13  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/82451
	Revert
	2017-10-02  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/82355
	* graphite-isl-ast-to-gimple.c (build_iv_mapping): Also build
	a mapping for the enclosing loop but avoid generating one for
	the loop tree root.
	(copy_bb_and_scalar_dependences): Remove premature codegen
	error on PHIs in blocks duplicated into multiple places.
	* graphite-scop-detection.c
	(scop_detection::stmt_has_simple_data_refs_p): For a loop not
	in the region use it as loop and nest to analyze the DR in.
	(try_generate_gimple_bb): Likewise.
	* graphite-sese-to-poly.c (extract_affine_chrec): Adjust.
	(add_loop_constraints): For blocks in a loop not in the region
	create a dimension with a single iteration.
	* sese.h (gbb_loop_at_index): Remove assert.

	* cfgloop.c (loop_preheader_edge): For the loop tree root
	return the single successor of the entry block.
	* graphite-isl-ast-to-gimple.c (graphite_regenerate_ast_isl):
	Reset the SCEV hashtable and niters.
	* graphite-scop-detection.c
	(scop_detection::graphite_can_represent_scev): Add SCOP parameter,
	assert that we only have POLYNOMIAL_CHREC that vary in loops
	contained in the region.
	(scop_detection::graphite_can_represent_expr): Adjust.
	(scop_detection::stmt_has_simple_data_refs_p): For loops
	not in the region set loop to NULL.  The nest is now the
	entry edge to the region.
	(try_generate_gimple_bb): Likewise.
	* sese.c (scalar_evolution_in_region): Adjust for
	instantiate_scev change.
	* tree-data-ref.h (graphite_find_data_references_in_stmt):
	Make nest parameter the edge into the region.
	(create_data_ref): Likewise.
	* tree-data-ref.c (dr_analyze_indices): Make nest parameter an
	entry edge into a region and adjust instantiate_scev calls.
	(create_data_ref): Likewise.
	(graphite_find_data_references_in_stmt): Likewise.
	(find_data_references_in_stmt): Pass the loop preheader edge
	from the nest argument.
	* tree-scalar-evolution.h (instantiate_scev): Make instantiate_below
	parameter the edge into the region.
	(instantiate_parameters): Use the loop preheader edge as entry.
	* tree-scalar-evolution.c (analyze_scalar_evolution): Handle
	NULL loop.
	(get_instantiated_value_entry): Make instantiate_below parameter
	the edge into the region.
	(instantiate_scev_name): Likewise.  Adjust dominance checks,
	when we cannot use loop-based instantiation instantiate by
	walking use-def chains.
	(instantiate_scev_poly): Adjust.
	(instantiate_scev_binary): Likewise.
	(instantiate_scev_convert): Likewise.
	(instantiate_scev_not): Likewise.
	(instantiate_array_ref): Remove.
	(instantiate_scev_3): Likewise.
	(instantiate_scev_2): Likewise.
	(instantiate_scev_1): Likewise.
	(instantiate_scev_r): Do not blindly handle N-operand trees.
	Do not instantiate array-refs.  Handle all constants and invariants.
	(instantiate_scev): Make instantiate_below parameter
	the edge into the region.
	(resolve_mixers): Use the loop preheader edge for the region
	parameter to instantiate_scev_r.
	* tree-ssa-loop-prefetch.c (determine_loop_nest_reuse): Adjust.

	* gcc.dg/graphite/pr82451.c: New testcase.
	* gfortran.dg/graphite/id-27.f90: Likewise.
	* gfortran.dg/graphite/pr82451.f: Likewise.

From-SVN: r253707
parent 1163f058
2017-10-13 Richard Biener <rguenther@suse.de> 2017-10-13 Richard Biener <rguenther@suse.de>
PR tree-optimization/82451
Revert
2017-10-02 Richard Biener <rguenther@suse.de>
PR tree-optimization/82355
* graphite-isl-ast-to-gimple.c (build_iv_mapping): Also build
a mapping for the enclosing loop but avoid generating one for
the loop tree root.
(copy_bb_and_scalar_dependences): Remove premature codegen
error on PHIs in blocks duplicated into multiple places.
* graphite-scop-detection.c
(scop_detection::stmt_has_simple_data_refs_p): For a loop not
in the region use it as loop and nest to analyze the DR in.
(try_generate_gimple_bb): Likewise.
* graphite-sese-to-poly.c (extract_affine_chrec): Adjust.
(add_loop_constraints): For blocks in a loop not in the region
create a dimension with a single iteration.
* sese.h (gbb_loop_at_index): Remove assert.
* cfgloop.c (loop_preheader_edge): For the loop tree root
return the single successor of the entry block.
* graphite-isl-ast-to-gimple.c (graphite_regenerate_ast_isl):
Reset the SCEV hashtable and niters.
* graphite-scop-detection.c
(scop_detection::graphite_can_represent_scev): Add SCOP parameter,
assert that we only have POLYNOMIAL_CHREC that vary in loops
contained in the region.
(scop_detection::graphite_can_represent_expr): Adjust.
(scop_detection::stmt_has_simple_data_refs_p): For loops
not in the region set loop to NULL. The nest is now the
entry edge to the region.
(try_generate_gimple_bb): Likewise.
* sese.c (scalar_evolution_in_region): Adjust for
instantiate_scev change.
* tree-data-ref.h (graphite_find_data_references_in_stmt):
Make nest parameter the edge into the region.
(create_data_ref): Likewise.
* tree-data-ref.c (dr_analyze_indices): Make nest parameter an
entry edge into a region and adjust instantiate_scev calls.
(create_data_ref): Likewise.
(graphite_find_data_references_in_stmt): Likewise.
(find_data_references_in_stmt): Pass the loop preheader edge
from the nest argument.
* tree-scalar-evolution.h (instantiate_scev): Make instantiate_below
parameter the edge into the region.
(instantiate_parameters): Use the loop preheader edge as entry.
* tree-scalar-evolution.c (analyze_scalar_evolution): Handle
NULL loop.
(get_instantiated_value_entry): Make instantiate_below parameter
the edge into the region.
(instantiate_scev_name): Likewise. Adjust dominance checks,
when we cannot use loop-based instantiation instantiate by
walking use-def chains.
(instantiate_scev_poly): Adjust.
(instantiate_scev_binary): Likewise.
(instantiate_scev_convert): Likewise.
(instantiate_scev_not): Likewise.
(instantiate_array_ref): Remove.
(instantiate_scev_3): Likewise.
(instantiate_scev_2): Likewise.
(instantiate_scev_1): Likewise.
(instantiate_scev_r): Do not blindly handle N-operand trees.
Do not instantiate array-refs. Handle all constants and invariants.
(instantiate_scev): Make instantiate_below parameter
the edge into the region.
(resolve_mixers): Use the loop preheader edge for the region
parameter to instantiate_scev_r.
* tree-ssa-loop-prefetch.c (determine_loop_nest_reuse): Adjust.
2017-10-13 Richard Biener <rguenther@suse.de>
PR tree-optimization/82525 PR tree-optimization/82525
* graphite-isl-ast-to-gimple.c * graphite-isl-ast-to-gimple.c
(translate_isl_ast_to_gimple::widest_int_from_isl_expr_int): Split (translate_isl_ast_to_gimple::widest_int_from_isl_expr_int): Split
...@@ -1713,12 +1713,19 @@ loop_preheader_edge (const struct loop *loop) ...@@ -1713,12 +1713,19 @@ loop_preheader_edge (const struct loop *loop)
edge e; edge e;
edge_iterator ei; edge_iterator ei;
gcc_assert (loops_state_satisfies_p (LOOPS_HAVE_PREHEADERS)); gcc_assert (loops_state_satisfies_p (LOOPS_HAVE_PREHEADERS)
&& ! loops_state_satisfies_p (LOOPS_MAY_HAVE_MULTIPLE_LATCHES));
FOR_EACH_EDGE (e, ei, loop->header->preds) FOR_EACH_EDGE (e, ei, loop->header->preds)
if (e->src != loop->latch) if (e->src != loop->latch)
break; break;
if (! e)
{
gcc_assert (! loop_outer (loop));
return single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun));
}
return e; return e;
} }
......
...@@ -750,9 +750,7 @@ build_iv_mapping (vec<tree> iv_map, gimple_poly_bb_p gbb, ...@@ -750,9 +750,7 @@ build_iv_mapping (vec<tree> iv_map, gimple_poly_bb_p gbb,
if (codegen_error_p ()) if (codegen_error_p ())
t = integer_zero_node; t = integer_zero_node;
loop_p old_loop = gbb_loop_at_index (gbb, region, i - 2); loop_p old_loop = gbb_loop_at_index (gbb, region, i - 1);
/* Record sth only for real loops. */
if (loop_in_sese_p (old_loop, region))
iv_map[old_loop->num] = t; iv_map[old_loop->num] = t;
} }
} }
...@@ -1571,6 +1569,12 @@ graphite_regenerate_ast_isl (scop_p scop) ...@@ -1571,6 +1569,12 @@ graphite_regenerate_ast_isl (scop_p scop)
update_ssa (TODO_update_ssa); update_ssa (TODO_update_ssa);
checking_verify_ssa (true, true); checking_verify_ssa (true, true);
rewrite_into_loop_closed_ssa (NULL, 0); rewrite_into_loop_closed_ssa (NULL, 0);
/* We analyzed evolutions of all SCOPs during SCOP detection
which cached evolutions. Now we've introduced PHIs for
liveouts which causes those cached solutions to be invalid
for code-generation purposes given we'd insert references
to SSA names not dominating their new use. */
scev_reset ();
} }
if (t.codegen_error_p ()) if (t.codegen_error_p ())
......
...@@ -381,7 +381,7 @@ public: ...@@ -381,7 +381,7 @@ public:
Something like "i * n" or "n * m" is not allowed. */ Something like "i * n" or "n * m" is not allowed. */
static bool graphite_can_represent_scev (tree scev); static bool graphite_can_represent_scev (sese_l scop, tree scev);
/* Return true when EXPR can be represented in the polyhedral model. /* Return true when EXPR can be represented in the polyhedral model.
...@@ -934,7 +934,7 @@ scop_detection::graphite_can_represent_init (tree e) ...@@ -934,7 +934,7 @@ scop_detection::graphite_can_represent_init (tree e)
Something like "i * n" or "n * m" is not allowed. */ Something like "i * n" or "n * m" is not allowed. */
bool bool
scop_detection::graphite_can_represent_scev (tree scev) scop_detection::graphite_can_represent_scev (sese_l scop, tree scev)
{ {
if (chrec_contains_undetermined (scev)) if (chrec_contains_undetermined (scev))
return false; return false;
...@@ -945,13 +945,13 @@ scop_detection::graphite_can_represent_scev (tree scev) ...@@ -945,13 +945,13 @@ scop_detection::graphite_can_represent_scev (tree scev)
case BIT_NOT_EXPR: case BIT_NOT_EXPR:
CASE_CONVERT: CASE_CONVERT:
case NON_LVALUE_EXPR: case NON_LVALUE_EXPR:
return graphite_can_represent_scev (TREE_OPERAND (scev, 0)); return graphite_can_represent_scev (scop, TREE_OPERAND (scev, 0));
case PLUS_EXPR: case PLUS_EXPR:
case POINTER_PLUS_EXPR: case POINTER_PLUS_EXPR:
case MINUS_EXPR: case MINUS_EXPR:
return graphite_can_represent_scev (TREE_OPERAND (scev, 0)) return graphite_can_represent_scev (scop, TREE_OPERAND (scev, 0))
&& graphite_can_represent_scev (TREE_OPERAND (scev, 1)); && graphite_can_represent_scev (scop, TREE_OPERAND (scev, 1));
case MULT_EXPR: case MULT_EXPR:
return !CONVERT_EXPR_CODE_P (TREE_CODE (TREE_OPERAND (scev, 0))) return !CONVERT_EXPR_CODE_P (TREE_CODE (TREE_OPERAND (scev, 0)))
...@@ -959,18 +959,20 @@ scop_detection::graphite_can_represent_scev (tree scev) ...@@ -959,18 +959,20 @@ scop_detection::graphite_can_represent_scev (tree scev)
&& !(chrec_contains_symbols (TREE_OPERAND (scev, 0)) && !(chrec_contains_symbols (TREE_OPERAND (scev, 0))
&& chrec_contains_symbols (TREE_OPERAND (scev, 1))) && chrec_contains_symbols (TREE_OPERAND (scev, 1)))
&& graphite_can_represent_init (scev) && graphite_can_represent_init (scev)
&& graphite_can_represent_scev (TREE_OPERAND (scev, 0)) && graphite_can_represent_scev (scop, TREE_OPERAND (scev, 0))
&& graphite_can_represent_scev (TREE_OPERAND (scev, 1)); && graphite_can_represent_scev (scop, TREE_OPERAND (scev, 1));
case POLYNOMIAL_CHREC: case POLYNOMIAL_CHREC:
/* Check for constant strides. With a non constant stride of /* Check for constant strides. With a non constant stride of
'n' we would have a value of 'iv * n'. Also check that the 'n' we would have a value of 'iv * n'. Also check that the
initial value can represented: for example 'n * m' cannot be initial value can represented: for example 'n * m' cannot be
represented. */ represented. */
gcc_assert (loop_in_sese_p (get_loop (cfun,
CHREC_VARIABLE (scev)), scop));
if (!evolution_function_right_is_integer_cst (scev) if (!evolution_function_right_is_integer_cst (scev)
|| !graphite_can_represent_init (scev)) || !graphite_can_represent_init (scev))
return false; return false;
return graphite_can_represent_scev (CHREC_LEFT (scev)); return graphite_can_represent_scev (scop, CHREC_LEFT (scev));
default: default:
break; break;
...@@ -994,7 +996,7 @@ scop_detection::graphite_can_represent_expr (sese_l scop, loop_p loop, ...@@ -994,7 +996,7 @@ scop_detection::graphite_can_represent_expr (sese_l scop, loop_p loop,
tree expr) tree expr)
{ {
tree scev = scalar_evolution_in_region (scop, loop, expr); tree scev = scalar_evolution_in_region (scop, loop, expr);
return graphite_can_represent_scev (scev); return graphite_can_represent_scev (scop, scev);
} }
/* Return true if the data references of STMT can be represented by Graphite. /* Return true if the data references of STMT can be represented by Graphite.
...@@ -1003,12 +1005,15 @@ scop_detection::graphite_can_represent_expr (sese_l scop, loop_p loop, ...@@ -1003,12 +1005,15 @@ scop_detection::graphite_can_represent_expr (sese_l scop, loop_p loop,
bool bool
scop_detection::stmt_has_simple_data_refs_p (sese_l scop, gimple *stmt) scop_detection::stmt_has_simple_data_refs_p (sese_l scop, gimple *stmt)
{ {
loop_p nest; edge nest;
loop_p loop = loop_containing_stmt (stmt); loop_p loop = loop_containing_stmt (stmt);
if (!loop_in_sese_p (loop, scop)) if (!loop_in_sese_p (loop, scop))
nest = loop; {
nest = scop.entry;
loop = NULL;
}
else else
nest = outermost_loop_in_sese (scop, gimple_bb (stmt)); nest = loop_preheader_edge (outermost_loop_in_sese (scop, gimple_bb (stmt)));
auto_vec<data_reference_p> drs; auto_vec<data_reference_p> drs;
if (! graphite_find_data_references_in_stmt (nest, loop, stmt, &drs)) if (! graphite_find_data_references_in_stmt (nest, loop, stmt, &drs))
...@@ -1019,7 +1024,7 @@ scop_detection::stmt_has_simple_data_refs_p (sese_l scop, gimple *stmt) ...@@ -1019,7 +1024,7 @@ scop_detection::stmt_has_simple_data_refs_p (sese_l scop, gimple *stmt)
FOR_EACH_VEC_ELT (drs, j, dr) FOR_EACH_VEC_ELT (drs, j, dr)
{ {
for (unsigned i = 0; i < DR_NUM_DIMENSIONS (dr); ++i) for (unsigned i = 0; i < DR_NUM_DIMENSIONS (dr); ++i)
if (! graphite_can_represent_scev (DR_ACCESS_FN (dr, i))) if (! graphite_can_represent_scev (scop, DR_ACCESS_FN (dr, i)))
return false; return false;
} }
...@@ -1376,12 +1381,15 @@ try_generate_gimple_bb (scop_p scop, basic_block bb) ...@@ -1376,12 +1381,15 @@ try_generate_gimple_bb (scop_p scop, basic_block bb)
vec<scalar_use> reads = vNULL; vec<scalar_use> reads = vNULL;
sese_l region = scop->scop_info->region; sese_l region = scop->scop_info->region;
loop_p nest; edge nest;
loop_p loop = bb->loop_father; loop_p loop = bb->loop_father;
if (!loop_in_sese_p (loop, region)) if (!loop_in_sese_p (loop, region))
nest = loop; {
nest = region.entry;
loop = NULL;
}
else else
nest = outermost_loop_in_sese (region, bb); nest = loop_preheader_edge (outermost_loop_in_sese (region, bb));
for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
gsi_next (&gsi)) gsi_next (&gsi))
......
...@@ -86,7 +86,7 @@ extract_affine_chrec (scop_p s, tree e, __isl_take isl_space *space) ...@@ -86,7 +86,7 @@ extract_affine_chrec (scop_p s, tree e, __isl_take isl_space *space)
isl_pw_aff *lhs = extract_affine (s, CHREC_LEFT (e), isl_space_copy (space)); isl_pw_aff *lhs = extract_affine (s, CHREC_LEFT (e), isl_space_copy (space));
isl_pw_aff *rhs = extract_affine (s, CHREC_RIGHT (e), isl_space_copy (space)); isl_pw_aff *rhs = extract_affine (s, CHREC_RIGHT (e), isl_space_copy (space));
isl_local_space *ls = isl_local_space_from_space (space); isl_local_space *ls = isl_local_space_from_space (space);
unsigned pos = sese_loop_depth (s->scop_info->region, get_chrec_loop (e)); unsigned pos = sese_loop_depth (s->scop_info->region, get_chrec_loop (e)) - 1;
isl_aff *loop = isl_aff_set_coefficient_si isl_aff *loop = isl_aff_set_coefficient_si
(isl_aff_zero_on_domain (ls), isl_dim_in, pos, 1); (isl_aff_zero_on_domain (ls), isl_dim_in, pos, 1);
isl_pw_aff *l = isl_pw_aff_from_aff (loop); isl_pw_aff *l = isl_pw_aff_from_aff (loop);
...@@ -763,8 +763,8 @@ add_loop_constraints (scop_p scop, __isl_take isl_set *domain, loop_p loop, ...@@ -763,8 +763,8 @@ add_loop_constraints (scop_p scop, __isl_take isl_set *domain, loop_p loop,
return domain; return domain;
const sese_l &region = scop->scop_info->region; const sese_l &region = scop->scop_info->region;
if (!loop_in_sese_p (loop, region)) if (!loop_in_sese_p (loop, region))
; return domain;
else
/* Recursion all the way up to the context loop. */ /* Recursion all the way up to the context loop. */
domain = add_loop_constraints (scop, domain, loop_outer (loop), context); domain = add_loop_constraints (scop, domain, loop_outer (loop), context);
...@@ -777,21 +777,6 @@ add_loop_constraints (scop_p scop, __isl_take isl_set *domain, loop_p loop, ...@@ -777,21 +777,6 @@ add_loop_constraints (scop_p scop, __isl_take isl_set *domain, loop_p loop,
domain = add_iter_domain_dimension (domain, loop, scop); domain = add_iter_domain_dimension (domain, loop, scop);
isl_space *space = isl_set_get_space (domain); isl_space *space = isl_set_get_space (domain);
if (!loop_in_sese_p (loop, region))
{
/* 0 == loop_i */
isl_local_space *ls = isl_local_space_from_space (space);
isl_constraint *c = isl_equality_alloc (ls);
c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, 1);
if (dump_file)
{
fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
print_isl_constraint (dump_file, c);
}
domain = isl_set_add_constraint (domain, c);
return domain;
}
/* 0 <= loop_i */ /* 0 <= loop_i */
isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space)); isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space));
isl_constraint *c = isl_inequality_alloc (ls); isl_constraint *c = isl_inequality_alloc (ls);
......
...@@ -461,7 +461,6 @@ scalar_evolution_in_region (const sese_l &region, loop_p loop, tree t) ...@@ -461,7 +461,6 @@ scalar_evolution_in_region (const sese_l &region, loop_p loop, tree t)
{ {
gimple *def; gimple *def;
struct loop *def_loop; struct loop *def_loop;
basic_block before = region.entry->src;
/* SCOP parameters. */ /* SCOP parameters. */
if (TREE_CODE (t) == SSA_NAME if (TREE_CODE (t) == SSA_NAME
...@@ -472,7 +471,7 @@ scalar_evolution_in_region (const sese_l &region, loop_p loop, tree t) ...@@ -472,7 +471,7 @@ scalar_evolution_in_region (const sese_l &region, loop_p loop, tree t)
|| loop_in_sese_p (loop, region)) || loop_in_sese_p (loop, region))
/* FIXME: we would need instantiate SCEV to work on a region, and be more /* FIXME: we would need instantiate SCEV to work on a region, and be more
flexible wrt. memory loads that may be invariant in the region. */ flexible wrt. memory loads that may be invariant in the region. */
return instantiate_scev (before, loop, return instantiate_scev (region.entry, loop,
analyze_scalar_evolution (loop, t)); analyze_scalar_evolution (loop, t));
def = SSA_NAME_DEF_STMT (t); def = SSA_NAME_DEF_STMT (t);
...@@ -494,7 +493,7 @@ scalar_evolution_in_region (const sese_l &region, loop_p loop, tree t) ...@@ -494,7 +493,7 @@ scalar_evolution_in_region (const sese_l &region, loop_p loop, tree t)
if (has_vdefs) if (has_vdefs)
return chrec_dont_know; return chrec_dont_know;
return instantiate_scev (before, loop, t); return instantiate_scev (region.entry, loop, t);
} }
/* Return true if BB is empty, contains only DEBUG_INSNs. */ /* Return true if BB is empty, contains only DEBUG_INSNs. */
......
...@@ -334,6 +334,8 @@ gbb_loop_at_index (gimple_poly_bb_p gbb, sese_l &region, int index) ...@@ -334,6 +334,8 @@ gbb_loop_at_index (gimple_poly_bb_p gbb, sese_l &region, int index)
while (--depth > index) while (--depth > index)
loop = loop_outer (loop); loop = loop_outer (loop);
gcc_assert (loop_in_sese_p (loop, region));
return loop; return loop;
} }
......
2017-10-13 Richard Biener <rguenther@suse.de> 2017-10-13 Richard Biener <rguenther@suse.de>
PR tree-optimization/82451
* gcc.dg/graphite/pr82451.c: New testcase.
* gfortran.dg/graphite/id-27.f90: Likewise.
* gfortran.dg/graphite/pr82451.f: Likewise.
2017-10-13 Richard Biener <rguenther@suse.de>
PR tree-optimization/82525 PR tree-optimization/82525
* gcc.dg/graphite/id-30.c: New testcase. * gcc.dg/graphite/id-30.c: New testcase.
* gfortran.dg/graphite/id-28.f90: Likewise. * gfortran.dg/graphite/id-28.f90: Likewise.
......
/* Check that the two loops are fused and that we manage to fold the two xor /* Check that the two loops are fused and that we manage to fold the two xor
operations. */ operations. */
/* { dg-options "-O2 -floop-nest-optimize -fdump-tree-forwprop4-all -fdump-tree-graphite-all" } */ /* { dg-options "-O2 -floop-nest-optimize -fdump-tree-forwprop-all -fdump-tree-graphite-all" } */
/* Make sure we fuse the loops like this: /* Make sure we fuse the loops like this:
AST generated by isl: AST generated by isl:
for (int c0 = 0; c0 <= 99; c0 += 1) { for (int c0 = 0; c0 <= 99; c0 += 1) {
S_3(0, c0); S_3(c0);
S_6(0, c0); S_6(c0);
S_9(0, c0); S_9(c0);
} */ } */
/* { dg-final { scan-tree-dump-times "AST generated by isl:.*for \\(int c0 = 0; c0 <= 99; c0 \\+= 1\\) \\{.*S_.*\\(0, c0\\);.*S_.*\\(0, c0\\);.*S_.*\\(0, c0\\);.*\\}" 1 "graphite" } } */ /* { dg-final { scan-tree-dump-times "AST generated by isl:.*for \\(int c0 = 0; c0 <= 99; c0 \\+= 1\\) \\{.*S_.*\\(c0\\);.*S_.*\\(c0\\);.*S_.*\\(c0\\);.*\\}" 1 "graphite" } } */
/* Check that after fusing the loops, the scalar computation is also fused. */ /* Check that after fusing the loops, the scalar computation is also fused. */
/* { dg-final { scan-tree-dump-times "gimple_simplified to\[^\\n\]*\\^ 12" 1 "forwprop4" } } */ /* { dg-final { scan-tree-dump-times "gimple_simplified to\[^\\n\]*\\^ 12" 1 "forwprop4" } } */
......
...@@ -3,13 +3,13 @@ ...@@ -3,13 +3,13 @@
/* Make sure we fuse the loops like this: /* Make sure we fuse the loops like this:
AST generated by isl: AST generated by isl:
for (int c0 = 0; c0 <= 99; c0 += 1) { for (int c0 = 0; c0 <= 99; c0 += 1) {
S_3(0, c0); S_3(c0);
S_6(0, c0); S_6(c0);
S_9(0, c0); S_9(c0);
} }
*/ */
/* { dg-final { scan-tree-dump-times "AST generated by isl:.*for \\(int c0 = 0; c0 <= 99; c0 \\+= 1\\) \\{.*S_.*\\(0, c0\\);.*S_.*\\(0, c0\\);.*S_.*\\(0, c0\\);.*\\}" 1 "graphite" } } */ /* { dg-final { scan-tree-dump-times "AST generated by isl:.*for \\(int c0 = 0; c0 <= 99; c0 \\+= 1\\) \\{.*S_.*\\(c0\\);.*S_.*\\(c0\\);.*S_.*\\(c0\\);.*\\}" 1 "graphite" } } */
#define MAX 100 #define MAX 100
int A[MAX], B[MAX], C[MAX]; int A[MAX], B[MAX], C[MAX];
......
/* { dg-do compile } */
/* { dg-options "-O -floop-parallelize-all" } */
static int a[];
int b[1];
int c;
static void
d (int *f, int *g)
{
int e;
for (e = 0; e < 2; e++)
g[e] = 1;
for (e = 0; e < 2; e++)
g[e] = f[e] + f[e + 1];
}
void
h ()
{
for (;; c += 8)
d (&a[c], b);
}
! { dg-additional-options "-Ofast" }
MODULE module_ra_gfdleta
INTEGER, PARAMETER :: NBLY=15
REAL , SAVE :: EM1(28,180),EM1WDE(28,180),TABLE1(28,180), &
TABLE2(28,180),TABLE3(28,180),EM3(28,180), &
SOURCE(28,NBLY), DSRCE(28,NBLY)
CONTAINS
SUBROUTINE TABLE
INTEGER, PARAMETER :: NBLX=47
INTEGER , PARAMETER:: NBLW = 163
REAL :: &
SUM(28,180),PERTSM(28,180),SUM3(28,180), &
SUMWDE(28,180),SRCWD(28,NBLX),SRC1NB(28,NBLW), &
DBDTNB(28,NBLW)
REAL :: &
ZMASS(181),ZROOT(181),SC(28),DSC(28),XTEMV(28), &
TFOUR(28),FORTCU(28),X(28),X1(28),X2(180),SRCS(28), &
R1T(28),R2(28),S2(28),T3(28),R1WD(28)
REAL :: EXPO(180),FAC(180)
I = 0
DO 417 J=121,180
FAC(J)=ZMASS(J)*(ONE-(ONE+X2(J))*EXPO(J))/(X2(J)*X2(J))
417 CONTINUE
DO 421 J=121,180
SUM3(I,J)=SUM3(I,J)+DBDTNB(I,N)*FAC(J)
421 CONTINUE
IF (CENT.GT.160. .AND. CENT.LT.560.) THEN
DO 420 J=1,180
DO 420 I=1,28
SUMWDE(I,J)=SUMWDE(I,J)+SRC1NB(I,N)*EXPO(J)
420 CONTINUE
ENDIF
DO 433 J=121,180
EM3(I,J)=SUM3(I,J)/FORTCU(I)
433 CONTINUE
DO 501 I=1,28
EM1WDE(I,J)=SUMWDE(I,J)/TFOUR(I)
501 CONTINUE
END SUBROUTINE TABLE
END MODULE module_RA_GFDLETA
! { dg-do compile }
! { dg-options "-O2 -floop-nest-optimize" }
MODULE LES3D_DATA
PARAMETER ( NSCHEME = 4, ICHEM = 0, ISGSK = 0, IVISC = 1 )
DOUBLE PRECISION DT, TIME, STATTIME, CFL, RELNO, TSTND, ALREF
INTEGER IDYN, IMAX, JMAX, KMAX
PARAMETER( RUNIV = 8.3145D3,
> TPRANDLT = 0.91D0)
DOUBLE PRECISION,ALLOCATABLE,DIMENSION(:,:,:) ::
> U, V, W, P, T, H, EK,
> UAV, VAV, WAV, PAV, TAV, HAV, EKAV
DOUBLE PRECISION,ALLOCATABLE,DIMENSION(:,:,:,:) ::
> CONC, HF, QAV, COAV, HFAV, DU
DOUBLE PRECISION,ALLOCATABLE,DIMENSION(:,:,:,:,:) ::
> Q
END MODULE LES3D_DATA
SUBROUTINE FLUXJ()
USE LES3D_DATA
ALLOCATABLE QS(:), FSJ(:,:,:)
ALLOCATABLE DWDX(:),DWDY(:),DWDZ(:)
ALLOCATABLE DHDY(:), DKDY(:)
PARAMETER ( R12I = 1.0D0 / 12.0D0,
> TWO3 = 2.0D0 / 3.0D0 )
ALLOCATE( QS(IMAX-1), FSJ(IMAX-1,0:JMAX-1,ND))
ALLOCATE( DWDX(IMAX-1),DWDY(IMAX-1),DWDZ(IMAX-1))
I1 = 1
DO K = K1,K2
DO J = J1,J2
DO I = I1, I2
FSJ(I,J,5) = FSJ(I,J,5) + PAV(I,J,K) * QS(I)
END DO
DO I = I1, I2
DWDX(I) = DXI * R12I * (WAV(I-2,J,K) - WAV(I+2,J,K) +
> 8.0D0 * (WAV(I+1,J,K) - WAV(I-1,J,K)))
END DO
END DO
END DO
DEALLOCATE( QS, FSJ, DHDY, DKDY)
END
...@@ -957,15 +957,14 @@ access_fn_component_p (tree op) ...@@ -957,15 +957,14 @@ access_fn_component_p (tree op)
} }
/* Determines the base object and the list of indices of memory reference /* Determines the base object and the list of indices of memory reference
DR, analyzed in LOOP and instantiated in loop nest NEST. */ DR, analyzed in LOOP and instantiated before NEST. */
static void static void
dr_analyze_indices (struct data_reference *dr, loop_p nest, loop_p loop) dr_analyze_indices (struct data_reference *dr, edge nest, loop_p loop)
{ {
vec<tree> access_fns = vNULL; vec<tree> access_fns = vNULL;
tree ref, op; tree ref, op;
tree base, off, access_fn; tree base, off, access_fn;
basic_block before_loop;
/* If analyzing a basic-block there are no indices to analyze /* If analyzing a basic-block there are no indices to analyze
and thus no access functions. */ and thus no access functions. */
...@@ -977,7 +976,6 @@ dr_analyze_indices (struct data_reference *dr, loop_p nest, loop_p loop) ...@@ -977,7 +976,6 @@ dr_analyze_indices (struct data_reference *dr, loop_p nest, loop_p loop)
} }
ref = DR_REF (dr); ref = DR_REF (dr);
before_loop = block_before_loop (nest);
/* REALPART_EXPR and IMAGPART_EXPR can be handled like accesses /* REALPART_EXPR and IMAGPART_EXPR can be handled like accesses
into a two element array with a constant index. The base is into a two element array with a constant index. The base is
...@@ -1002,7 +1000,7 @@ dr_analyze_indices (struct data_reference *dr, loop_p nest, loop_p loop) ...@@ -1002,7 +1000,7 @@ dr_analyze_indices (struct data_reference *dr, loop_p nest, loop_p loop)
{ {
op = TREE_OPERAND (ref, 1); op = TREE_OPERAND (ref, 1);
access_fn = analyze_scalar_evolution (loop, op); access_fn = analyze_scalar_evolution (loop, op);
access_fn = instantiate_scev (before_loop, loop, access_fn); access_fn = instantiate_scev (nest, loop, access_fn);
access_fns.safe_push (access_fn); access_fns.safe_push (access_fn);
} }
else if (TREE_CODE (ref) == COMPONENT_REF else if (TREE_CODE (ref) == COMPONENT_REF
...@@ -1034,7 +1032,7 @@ dr_analyze_indices (struct data_reference *dr, loop_p nest, loop_p loop) ...@@ -1034,7 +1032,7 @@ dr_analyze_indices (struct data_reference *dr, loop_p nest, loop_p loop)
{ {
op = TREE_OPERAND (ref, 0); op = TREE_OPERAND (ref, 0);
access_fn = analyze_scalar_evolution (loop, op); access_fn = analyze_scalar_evolution (loop, op);
access_fn = instantiate_scev (before_loop, loop, access_fn); access_fn = instantiate_scev (nest, loop, access_fn);
if (TREE_CODE (access_fn) == POLYNOMIAL_CHREC) if (TREE_CODE (access_fn) == POLYNOMIAL_CHREC)
{ {
tree orig_type; tree orig_type;
...@@ -1139,7 +1137,7 @@ free_data_ref (data_reference_p dr) ...@@ -1139,7 +1137,7 @@ free_data_ref (data_reference_p dr)
in which the data reference should be analyzed. */ in which the data reference should be analyzed. */
struct data_reference * struct data_reference *
create_data_ref (loop_p nest, loop_p loop, tree memref, gimple *stmt, create_data_ref (edge nest, loop_p loop, tree memref, gimple *stmt,
bool is_read, bool is_conditional_in_stmt) bool is_read, bool is_conditional_in_stmt)
{ {
struct data_reference *dr; struct data_reference *dr;
...@@ -4970,7 +4968,8 @@ find_data_references_in_stmt (struct loop *nest, gimple *stmt, ...@@ -4970,7 +4968,8 @@ find_data_references_in_stmt (struct loop *nest, gimple *stmt,
FOR_EACH_VEC_ELT (references, i, ref) FOR_EACH_VEC_ELT (references, i, ref)
{ {
dr = create_data_ref (nest, loop_containing_stmt (stmt), ref->ref, dr = create_data_ref (nest ? loop_preheader_edge (nest) : NULL,
loop_containing_stmt (stmt), ref->ref,
stmt, ref->is_read, ref->is_conditional_in_stmt); stmt, ref->is_read, ref->is_conditional_in_stmt);
gcc_assert (dr != NULL); gcc_assert (dr != NULL);
datarefs->safe_push (dr); datarefs->safe_push (dr);
...@@ -4986,7 +4985,7 @@ find_data_references_in_stmt (struct loop *nest, gimple *stmt, ...@@ -4986,7 +4985,7 @@ find_data_references_in_stmt (struct loop *nest, gimple *stmt,
should be analyzed. */ should be analyzed. */
bool bool
graphite_find_data_references_in_stmt (loop_p nest, loop_p loop, gimple *stmt, graphite_find_data_references_in_stmt (edge nest, loop_p loop, gimple *stmt,
vec<data_reference_p> *datarefs) vec<data_reference_p> *datarefs)
{ {
unsigned i; unsigned i;
......
...@@ -436,11 +436,11 @@ extern void free_data_ref (data_reference_p); ...@@ -436,11 +436,11 @@ extern void free_data_ref (data_reference_p);
extern void free_data_refs (vec<data_reference_p> ); extern void free_data_refs (vec<data_reference_p> );
extern bool find_data_references_in_stmt (struct loop *, gimple *, extern bool find_data_references_in_stmt (struct loop *, gimple *,
vec<data_reference_p> *); vec<data_reference_p> *);
extern bool graphite_find_data_references_in_stmt (loop_p, loop_p, gimple *, extern bool graphite_find_data_references_in_stmt (edge, loop_p, gimple *,
vec<data_reference_p> *); vec<data_reference_p> *);
tree find_data_references_in_loop (struct loop *, vec<data_reference_p> *); tree find_data_references_in_loop (struct loop *, vec<data_reference_p> *);
bool loop_nest_has_data_refs (loop_p loop); bool loop_nest_has_data_refs (loop_p loop);
struct data_reference *create_data_ref (loop_p, loop_p, tree, gimple *, bool, struct data_reference *create_data_ref (edge, loop_p, tree, gimple *, bool,
bool); bool);
extern bool find_loop_nest (struct loop *, vec<loop_p> *); extern bool find_loop_nest (struct loop *, vec<loop_p> *);
extern struct data_dependence_relation *initialize_data_dependence_relation extern struct data_dependence_relation *initialize_data_dependence_relation
......
...@@ -2095,6 +2095,10 @@ analyze_scalar_evolution (struct loop *loop, tree var) ...@@ -2095,6 +2095,10 @@ analyze_scalar_evolution (struct loop *loop, tree var)
{ {
tree res; tree res;
/* ??? Fix callers. */
if (! loop)
return var;
if (dump_file && (dump_flags & TDF_SCEV)) if (dump_file && (dump_flags & TDF_SCEV))
{ {
fprintf (dump_file, "(analyze_scalar_evolution \n"); fprintf (dump_file, "(analyze_scalar_evolution \n");
...@@ -2271,7 +2275,7 @@ eq_idx_scev_info (const void *e1, const void *e2) ...@@ -2271,7 +2275,7 @@ eq_idx_scev_info (const void *e1, const void *e2)
static unsigned static unsigned
get_instantiated_value_entry (instantiate_cache_type &cache, get_instantiated_value_entry (instantiate_cache_type &cache,
tree name, basic_block instantiate_below) tree name, edge instantiate_below)
{ {
if (!cache.map) if (!cache.map)
{ {
...@@ -2281,7 +2285,7 @@ get_instantiated_value_entry (instantiate_cache_type &cache, ...@@ -2281,7 +2285,7 @@ get_instantiated_value_entry (instantiate_cache_type &cache,
scev_info_str e; scev_info_str e;
e.name_version = SSA_NAME_VERSION (name); e.name_version = SSA_NAME_VERSION (name);
e.instantiated_below = instantiate_below->index; e.instantiated_below = instantiate_below->dest->index;
void **slot = htab_find_slot_with_hash (cache.map, &e, void **slot = htab_find_slot_with_hash (cache.map, &e,
scev_info_hasher::hash (&e), INSERT); scev_info_hasher::hash (&e), INSERT);
if (!*slot) if (!*slot)
...@@ -2325,7 +2329,7 @@ loop_closed_phi_def (tree var) ...@@ -2325,7 +2329,7 @@ loop_closed_phi_def (tree var)
return NULL_TREE; return NULL_TREE;
} }
static tree instantiate_scev_r (basic_block, struct loop *, struct loop *, static tree instantiate_scev_r (edge, struct loop *, struct loop *,
tree, bool *, int); tree, bool *, int);
/* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW /* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW
...@@ -2344,7 +2348,7 @@ static tree instantiate_scev_r (basic_block, struct loop *, struct loop *, ...@@ -2344,7 +2348,7 @@ static tree instantiate_scev_r (basic_block, struct loop *, struct loop *,
instantiated, and to stop if it exceeds some limit. */ instantiated, and to stop if it exceeds some limit. */
static tree static tree
instantiate_scev_name (basic_block instantiate_below, instantiate_scev_name (edge instantiate_below,
struct loop *evolution_loop, struct loop *inner_loop, struct loop *evolution_loop, struct loop *inner_loop,
tree chrec, tree chrec,
bool *fold_conversions, bool *fold_conversions,
...@@ -2358,7 +2362,7 @@ instantiate_scev_name (basic_block instantiate_below, ...@@ -2358,7 +2362,7 @@ instantiate_scev_name (basic_block instantiate_below,
evolutions in outer loops), nothing to do. */ evolutions in outer loops), nothing to do. */
if (!def_bb if (!def_bb
|| loop_depth (def_bb->loop_father) == 0 || loop_depth (def_bb->loop_father) == 0
|| dominated_by_p (CDI_DOMINATORS, instantiate_below, def_bb)) || ! dominated_by_p (CDI_DOMINATORS, def_bb, instantiate_below->dest))
return chrec; return chrec;
/* We cache the value of instantiated variable to avoid exponential /* We cache the value of instantiated variable to avoid exponential
...@@ -2380,6 +2384,51 @@ instantiate_scev_name (basic_block instantiate_below, ...@@ -2380,6 +2384,51 @@ instantiate_scev_name (basic_block instantiate_below,
def_loop = find_common_loop (evolution_loop, def_bb->loop_father); def_loop = find_common_loop (evolution_loop, def_bb->loop_father);
if (! dominated_by_p (CDI_DOMINATORS,
def_loop->header, instantiate_below->dest))
{
gimple *def = SSA_NAME_DEF_STMT (chrec);
if (gassign *ass = dyn_cast <gassign *> (def))
{
switch (gimple_assign_rhs_class (ass))
{
case GIMPLE_UNARY_RHS:
{
tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
inner_loop, gimple_assign_rhs1 (ass),
fold_conversions, size_expr);
if (op0 == chrec_dont_know)
return chrec_dont_know;
res = fold_build1 (gimple_assign_rhs_code (ass),
TREE_TYPE (chrec), op0);
break;
}
case GIMPLE_BINARY_RHS:
{
tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
inner_loop, gimple_assign_rhs1 (ass),
fold_conversions, size_expr);
if (op0 == chrec_dont_know)
return chrec_dont_know;
tree op1 = instantiate_scev_r (instantiate_below, evolution_loop,
inner_loop, gimple_assign_rhs2 (ass),
fold_conversions, size_expr);
if (op1 == chrec_dont_know)
return chrec_dont_know;
res = fold_build2 (gimple_assign_rhs_code (ass),
TREE_TYPE (chrec), op0, op1);
break;
}
default:
res = chrec_dont_know;
}
}
else
res = chrec_dont_know;
global_cache->set (si, res);
return res;
}
/* If the analysis yields a parametric chrec, instantiate the /* If the analysis yields a parametric chrec, instantiate the
result again. */ result again. */
res = analyze_scalar_evolution (def_loop, chrec); res = analyze_scalar_evolution (def_loop, chrec);
...@@ -2411,8 +2460,9 @@ instantiate_scev_name (basic_block instantiate_below, ...@@ -2411,8 +2460,9 @@ instantiate_scev_name (basic_block instantiate_below,
inner_loop, res, inner_loop, res,
fold_conversions, size_expr); fold_conversions, size_expr);
} }
else if (!dominated_by_p (CDI_DOMINATORS, instantiate_below, else if (dominated_by_p (CDI_DOMINATORS,
gimple_bb (SSA_NAME_DEF_STMT (res)))) gimple_bb (SSA_NAME_DEF_STMT (res)),
instantiate_below->dest))
res = chrec_dont_know; res = chrec_dont_know;
} }
...@@ -2450,7 +2500,7 @@ instantiate_scev_name (basic_block instantiate_below, ...@@ -2450,7 +2500,7 @@ instantiate_scev_name (basic_block instantiate_below,
instantiated, and to stop if it exceeds some limit. */ instantiated, and to stop if it exceeds some limit. */
static tree static tree
instantiate_scev_poly (basic_block instantiate_below, instantiate_scev_poly (edge instantiate_below,
struct loop *evolution_loop, struct loop *, struct loop *evolution_loop, struct loop *,
tree chrec, bool *fold_conversions, int size_expr) tree chrec, bool *fold_conversions, int size_expr)
{ {
...@@ -2495,7 +2545,7 @@ instantiate_scev_poly (basic_block instantiate_below, ...@@ -2495,7 +2545,7 @@ instantiate_scev_poly (basic_block instantiate_below,
instantiated, and to stop if it exceeds some limit. */ instantiated, and to stop if it exceeds some limit. */
static tree static tree
instantiate_scev_binary (basic_block instantiate_below, instantiate_scev_binary (edge instantiate_below,
struct loop *evolution_loop, struct loop *inner_loop, struct loop *evolution_loop, struct loop *inner_loop,
tree chrec, enum tree_code code, tree chrec, enum tree_code code,
tree type, tree c0, tree c1, tree type, tree c0, tree c1,
...@@ -2541,43 +2591,6 @@ instantiate_scev_binary (basic_block instantiate_below, ...@@ -2541,43 +2591,6 @@ instantiate_scev_binary (basic_block instantiate_below,
/* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW /* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW
and EVOLUTION_LOOP, that were left under a symbolic form. and EVOLUTION_LOOP, that were left under a symbolic form.
"CHREC" is an array reference to be instantiated.
CACHE is the cache of already instantiated values.
Variable pointed by FOLD_CONVERSIONS is set to TRUE when the
conversions that may wrap in signed/pointer type are folded, as long
as the value of the chrec is preserved. If FOLD_CONVERSIONS is NULL
then we don't do such fold.
SIZE_EXPR is used for computing the size of the expression to be
instantiated, and to stop if it exceeds some limit. */
static tree
instantiate_array_ref (basic_block instantiate_below,
struct loop *evolution_loop, struct loop *inner_loop,
tree chrec, bool *fold_conversions, int size_expr)
{
tree res;
tree index = TREE_OPERAND (chrec, 1);
tree op1 = instantiate_scev_r (instantiate_below, evolution_loop,
inner_loop, index,
fold_conversions, size_expr);
if (op1 == chrec_dont_know)
return chrec_dont_know;
if (chrec && op1 == index)
return chrec;
res = unshare_expr (chrec);
TREE_OPERAND (res, 1) = op1;
return res;
}
/* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW
and EVOLUTION_LOOP, that were left under a symbolic form.
"CHREC" that stands for a convert expression "(TYPE) OP" is to be "CHREC" that stands for a convert expression "(TYPE) OP" is to be
instantiated. instantiated.
...@@ -2592,7 +2605,7 @@ instantiate_array_ref (basic_block instantiate_below, ...@@ -2592,7 +2605,7 @@ instantiate_array_ref (basic_block instantiate_below,
instantiated, and to stop if it exceeds some limit. */ instantiated, and to stop if it exceeds some limit. */
static tree static tree
instantiate_scev_convert (basic_block instantiate_below, instantiate_scev_convert (edge instantiate_below,
struct loop *evolution_loop, struct loop *inner_loop, struct loop *evolution_loop, struct loop *inner_loop,
tree chrec, tree type, tree op, tree chrec, tree type, tree op,
bool *fold_conversions, int size_expr) bool *fold_conversions, int size_expr)
...@@ -2643,7 +2656,7 @@ instantiate_scev_convert (basic_block instantiate_below, ...@@ -2643,7 +2656,7 @@ instantiate_scev_convert (basic_block instantiate_below,
instantiated, and to stop if it exceeds some limit. */ instantiated, and to stop if it exceeds some limit. */
static tree static tree
instantiate_scev_not (basic_block instantiate_below, instantiate_scev_not (edge instantiate_below,
struct loop *evolution_loop, struct loop *inner_loop, struct loop *evolution_loop, struct loop *inner_loop,
tree chrec, tree chrec,
enum tree_code code, tree type, tree op, enum tree_code code, tree type, tree op,
...@@ -2681,130 +2694,6 @@ instantiate_scev_not (basic_block instantiate_below, ...@@ -2681,130 +2694,6 @@ instantiate_scev_not (basic_block instantiate_below,
/* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW /* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW
and EVOLUTION_LOOP, that were left under a symbolic form. and EVOLUTION_LOOP, that were left under a symbolic form.
CHREC is an expression with 3 operands to be instantiated.
CACHE is the cache of already instantiated values.
Variable pointed by FOLD_CONVERSIONS is set to TRUE when the
conversions that may wrap in signed/pointer type are folded, as long
as the value of the chrec is preserved. If FOLD_CONVERSIONS is NULL
then we don't do such fold.
SIZE_EXPR is used for computing the size of the expression to be
instantiated, and to stop if it exceeds some limit. */
static tree
instantiate_scev_3 (basic_block instantiate_below,
struct loop *evolution_loop, struct loop *inner_loop,
tree chrec,
bool *fold_conversions, int size_expr)
{
tree op1, op2;
tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
inner_loop, TREE_OPERAND (chrec, 0),
fold_conversions, size_expr);
if (op0 == chrec_dont_know)
return chrec_dont_know;
op1 = instantiate_scev_r (instantiate_below, evolution_loop,
inner_loop, TREE_OPERAND (chrec, 1),
fold_conversions, size_expr);
if (op1 == chrec_dont_know)
return chrec_dont_know;
op2 = instantiate_scev_r (instantiate_below, evolution_loop,
inner_loop, TREE_OPERAND (chrec, 2),
fold_conversions, size_expr);
if (op2 == chrec_dont_know)
return chrec_dont_know;
if (op0 == TREE_OPERAND (chrec, 0)
&& op1 == TREE_OPERAND (chrec, 1)
&& op2 == TREE_OPERAND (chrec, 2))
return chrec;
return fold_build3 (TREE_CODE (chrec),
TREE_TYPE (chrec), op0, op1, op2);
}
/* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW
and EVOLUTION_LOOP, that were left under a symbolic form.
CHREC is an expression with 2 operands to be instantiated.
CACHE is the cache of already instantiated values.
Variable pointed by FOLD_CONVERSIONS is set to TRUE when the
conversions that may wrap in signed/pointer type are folded, as long
as the value of the chrec is preserved. If FOLD_CONVERSIONS is NULL
then we don't do such fold.
SIZE_EXPR is used for computing the size of the expression to be
instantiated, and to stop if it exceeds some limit. */
static tree
instantiate_scev_2 (basic_block instantiate_below,
struct loop *evolution_loop, struct loop *inner_loop,
tree chrec,
bool *fold_conversions, int size_expr)
{
tree op1;
tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
inner_loop, TREE_OPERAND (chrec, 0),
fold_conversions, size_expr);
if (op0 == chrec_dont_know)
return chrec_dont_know;
op1 = instantiate_scev_r (instantiate_below, evolution_loop,
inner_loop, TREE_OPERAND (chrec, 1),
fold_conversions, size_expr);
if (op1 == chrec_dont_know)
return chrec_dont_know;
if (op0 == TREE_OPERAND (chrec, 0)
&& op1 == TREE_OPERAND (chrec, 1))
return chrec;
return fold_build2 (TREE_CODE (chrec), TREE_TYPE (chrec), op0, op1);
}
/* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW
and EVOLUTION_LOOP, that were left under a symbolic form.
CHREC is an expression with 2 operands to be instantiated.
CACHE is the cache of already instantiated values.
Variable pointed by FOLD_CONVERSIONS is set to TRUE when the
conversions that may wrap in signed/pointer type are folded, as long
as the value of the chrec is preserved. If FOLD_CONVERSIONS is NULL
then we don't do such fold.
SIZE_EXPR is used for computing the size of the expression to be
instantiated, and to stop if it exceeds some limit. */
static tree
instantiate_scev_1 (basic_block instantiate_below,
struct loop *evolution_loop, struct loop *inner_loop,
tree chrec,
bool *fold_conversions, int size_expr)
{
tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
inner_loop, TREE_OPERAND (chrec, 0),
fold_conversions, size_expr);
if (op0 == chrec_dont_know)
return chrec_dont_know;
if (op0 == TREE_OPERAND (chrec, 0))
return chrec;
return fold_build1 (TREE_CODE (chrec), TREE_TYPE (chrec), op0);
}
/* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW
and EVOLUTION_LOOP, that were left under a symbolic form.
CHREC is the scalar evolution to instantiate. CHREC is the scalar evolution to instantiate.
CACHE is the cache of already instantiated values. CACHE is the cache of already instantiated values.
...@@ -2818,7 +2707,7 @@ instantiate_scev_1 (basic_block instantiate_below, ...@@ -2818,7 +2707,7 @@ instantiate_scev_1 (basic_block instantiate_below,
instantiated, and to stop if it exceeds some limit. */ instantiated, and to stop if it exceeds some limit. */
static tree static tree
instantiate_scev_r (basic_block instantiate_below, instantiate_scev_r (edge instantiate_below,
struct loop *evolution_loop, struct loop *inner_loop, struct loop *evolution_loop, struct loop *inner_loop,
tree chrec, tree chrec,
bool *fold_conversions, int size_expr) bool *fold_conversions, int size_expr)
...@@ -2870,50 +2759,20 @@ instantiate_scev_r (basic_block instantiate_below, ...@@ -2870,50 +2759,20 @@ instantiate_scev_r (basic_block instantiate_below,
fold_conversions, size_expr); fold_conversions, size_expr);
case ADDR_EXPR: case ADDR_EXPR:
if (is_gimple_min_invariant (chrec))
return chrec;
/* Fallthru. */
case SCEV_NOT_KNOWN: case SCEV_NOT_KNOWN:
return chrec_dont_know; return chrec_dont_know;
case SCEV_KNOWN: case SCEV_KNOWN:
return chrec_known; return chrec_known;
case ARRAY_REF:
return instantiate_array_ref (instantiate_below, evolution_loop,
inner_loop, chrec,
fold_conversions, size_expr);
default: default:
break; if (CONSTANT_CLASS_P (chrec))
}
if (VL_EXP_CLASS_P (chrec))
return chrec_dont_know;
switch (TREE_CODE_LENGTH (TREE_CODE (chrec)))
{
case 3:
return instantiate_scev_3 (instantiate_below, evolution_loop,
inner_loop, chrec,
fold_conversions, size_expr);
case 2:
return instantiate_scev_2 (instantiate_below, evolution_loop,
inner_loop, chrec,
fold_conversions, size_expr);
case 1:
return instantiate_scev_1 (instantiate_below, evolution_loop,
inner_loop, chrec,
fold_conversions, size_expr);
case 0:
return chrec; return chrec;
default:
break;
}
/* Too complicated to handle. */
return chrec_dont_know; return chrec_dont_know;
}
} }
/* Analyze all the parameters of the chrec that were left under a /* Analyze all the parameters of the chrec that were left under a
...@@ -2923,7 +2782,7 @@ instantiate_scev_r (basic_block instantiate_below, ...@@ -2923,7 +2782,7 @@ instantiate_scev_r (basic_block instantiate_below,
a function parameter. */ a function parameter. */
tree tree
instantiate_scev (basic_block instantiate_below, struct loop *evolution_loop, instantiate_scev (edge instantiate_below, struct loop *evolution_loop,
tree chrec) tree chrec)
{ {
tree res; tree res;
...@@ -2931,7 +2790,9 @@ instantiate_scev (basic_block instantiate_below, struct loop *evolution_loop, ...@@ -2931,7 +2790,9 @@ instantiate_scev (basic_block instantiate_below, struct loop *evolution_loop,
if (dump_file && (dump_flags & TDF_SCEV)) if (dump_file && (dump_flags & TDF_SCEV))
{ {
fprintf (dump_file, "(instantiate_scev \n"); fprintf (dump_file, "(instantiate_scev \n");
fprintf (dump_file, " (instantiate_below = %d)\n", instantiate_below->index); fprintf (dump_file, " (instantiate_below = %d -> %d)\n",
instantiate_below->src->index, instantiate_below->dest->index);
if (evolution_loop)
fprintf (dump_file, " (evolution_loop = %d)\n", evolution_loop->num); fprintf (dump_file, " (evolution_loop = %d)\n", evolution_loop->num);
fprintf (dump_file, " (chrec = "); fprintf (dump_file, " (chrec = ");
print_generic_expr (dump_file, chrec); print_generic_expr (dump_file, chrec);
...@@ -2980,7 +2841,7 @@ resolve_mixers (struct loop *loop, tree chrec, bool *folded_casts) ...@@ -2980,7 +2841,7 @@ resolve_mixers (struct loop *loop, tree chrec, bool *folded_casts)
destr = true; destr = true;
} }
tree ret = instantiate_scev_r (block_before_loop (loop), loop, NULL, tree ret = instantiate_scev_r (loop_preheader_edge (loop), loop, NULL,
chrec, &fold_conversions, 0); chrec, &fold_conversions, 0);
if (folded_casts && !*folded_casts) if (folded_casts && !*folded_casts)
......
...@@ -30,7 +30,7 @@ extern void scev_reset (void); ...@@ -30,7 +30,7 @@ extern void scev_reset (void);
extern void scev_reset_htab (void); extern void scev_reset_htab (void);
extern void scev_finalize (void); extern void scev_finalize (void);
extern tree analyze_scalar_evolution (struct loop *, tree); extern tree analyze_scalar_evolution (struct loop *, tree);
extern tree instantiate_scev (basic_block, struct loop *, tree); extern tree instantiate_scev (edge, struct loop *, tree);
extern tree resolve_mixers (struct loop *, tree, bool *); extern tree resolve_mixers (struct loop *, tree, bool *);
extern void gather_stats_on_scev_database (void); extern void gather_stats_on_scev_database (void);
extern void final_value_replacement_loop (struct loop *); extern void final_value_replacement_loop (struct loop *);
...@@ -60,7 +60,7 @@ block_before_loop (loop_p loop) ...@@ -60,7 +60,7 @@ block_before_loop (loop_p loop)
static inline tree static inline tree
instantiate_parameters (struct loop *loop, tree chrec) instantiate_parameters (struct loop *loop, tree chrec)
{ {
return instantiate_scev (block_before_loop (loop), loop, chrec); return instantiate_scev (loop_preheader_edge (loop), loop, chrec);
} }
/* Returns the loop of the polynomial chrec CHREC. */ /* Returns the loop of the polynomial chrec CHREC. */
......
...@@ -1632,7 +1632,8 @@ determine_loop_nest_reuse (struct loop *loop, struct mem_ref_group *refs, ...@@ -1632,7 +1632,8 @@ determine_loop_nest_reuse (struct loop *loop, struct mem_ref_group *refs,
for (gr = refs; gr; gr = gr->next) for (gr = refs; gr; gr = gr->next)
for (ref = gr->refs; ref; ref = ref->next) for (ref = gr->refs; ref; ref = ref->next)
{ {
dr = create_data_ref (nest, loop_containing_stmt (ref->stmt), dr = create_data_ref (loop_preheader_edge (nest),
loop_containing_stmt (ref->stmt),
ref->mem, ref->stmt, !ref->write_p, false); ref->mem, ref->stmt, !ref->write_p, false);
if (dr) if (dr)
......
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