Commit b89361c6 by Daniel Berlin Committed by Daniel Berlin

Fix PR tree-optimization/20703 Fix PR tree-optimization/20725

2005-04-02  Daniel Berlin  <dberlin@dberlin.org>
	    Diego Novillo <dnovillo@redhat.com>

	Fix PR tree-optimization/20703
	Fix PR tree-optimization/20725

	* tree-ssa-pre.c (phi_translate): Handle tcc_comparison.
	(create_expression_by_pieces): Ditto.
	(valid_in_set): Ditto. Also handle tcc_declaration.
	(find_or_generate_expression): Handle comparison class.
	(insert_into_preds_of_block): Ditto.
	(insert_aux): Ditto.
	(create_value_expr_from): Handle comparison class, recursively
	handle reference nodes.
	(compute_avail): Handle comparison classes, rewrite a little cleaner.
	(execute_pre): Fix spacing.
	(do_fre): Renamed to execute_fre.

Co-Authored-By: Diego Novillo <dnovillo@redhat.com>

From-SVN: r97567
parent 6a5d24d7
2005-04-02 Daniel Berlin <dberlin@dberlin.org>
Diego Novillo <dnovillo@redhat.com>
Fix PR tree-optimization/20703
Fix PR tree-optimization/20725
* tree-ssa-pre.c (phi_translate): Handle tcc_comparison.
(create_expression_by_pieces): Ditto.
(valid_in_set): Ditto. Also handle tcc_declaration.
(find_or_generate_expression): Handle comparison class.
(insert_into_preds_of_block): Ditto.
(insert_aux): Ditto.
(create_value_expr_from): Handle comparison class, recursively
handle reference nodes.
(compute_avail): Handle comparison classes, rewrite a little cleaner.
(execute_pre): Fix spacing.
(do_fre): Renamed to execute_fre.
2005-04-04 Eric Botcazou <ebotcazou@libertysurf.fr> 2005-04-04 Eric Botcazou <ebotcazou@libertysurf.fr>
* doc/invoke.texi (SPARC options): Document that * doc/invoke.texi (SPARC options): Document that
......
...@@ -17,5 +17,5 @@ int main(int argc, char **argv) ...@@ -17,5 +17,5 @@ int main(int argc, char **argv)
} }
/* We should eliminate one evaluation of b + c along the main path, /* We should eliminate one evaluation of b + c along the main path,
causing one reload. */ causing one reload. */
/* { dg-final { scan-tree-dump-times "Eliminated:1" 1 "pre"} } */ /* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */
/* { dg-final { cleanup-tree-dump "pre" } } */ /* { dg-final { cleanup-tree-dump "pre" } } */
...@@ -17,5 +17,5 @@ int motion_test1(int data, int data_0, int data_3, int v) ...@@ -17,5 +17,5 @@ int motion_test1(int data, int data_0, int data_3, int v)
} }
/* We should eliminate one computation of data_0 + data_3 along the /* We should eliminate one computation of data_0 + data_3 along the
main path, causing one reload. */ main path, causing one reload. */
/* { dg-final { scan-tree-dump-times "Eliminated:1" 1 "pre"} } */ /* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */
/* { dg-final { cleanup-tree-dump "pre" } } */ /* { dg-final { cleanup-tree-dump "pre" } } */
...@@ -11,5 +11,5 @@ unsigned foo1 (unsigned a, unsigned b) ...@@ -11,5 +11,5 @@ unsigned foo1 (unsigned a, unsigned b)
return j + k; return j + k;
} }
/* We should eliminate both 4*b and 4*a from the main body of the loop */ /* We should eliminate both 4*b and 4*a from the main body of the loop */
/* { dg-final { scan-tree-dump-times "Eliminated:2" 1 "pre"} } */ /* { dg-final { scan-tree-dump-times "Eliminated: 2" 1 "pre"} } */
/* { dg-final { cleanup-tree-dump "pre" } } */ /* { dg-final { cleanup-tree-dump "pre" } } */
...@@ -11,5 +11,5 @@ int main(void) ...@@ -11,5 +11,5 @@ int main(void)
} }
/* We should eliminate the x+1 computation from this routine, replacing /* We should eliminate the x+1 computation from this routine, replacing
it with a phi of 3, 4 */ it with a phi of 3, 4 */
/* { dg-final { scan-tree-dump-times "Eliminated:1" 1 "pre"} } */ /* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */
/* { dg-final { cleanup-tree-dump "pre" } } */ /* { dg-final { cleanup-tree-dump "pre" } } */
...@@ -12,5 +12,5 @@ foo (int i) ...@@ -12,5 +12,5 @@ foo (int i)
} }
/* We should detect that a+b is the same along both edges, and replace it with /* We should detect that a+b is the same along both edges, and replace it with
5 */ 5 */
/* { dg-final { scan-tree-dump-times "Constified:1" 1 "pre"} } */ /* { dg-final { scan-tree-dump-times "Constified: 1" 1 "pre"} } */
/* { dg-final { cleanup-tree-dump "pre" } } */ /* { dg-final { cleanup-tree-dump "pre" } } */
...@@ -10,5 +10,5 @@ int main(int x) ...@@ -10,5 +10,5 @@ int main(int x)
} }
/* We should eliminate one evaluation of x + 1 along the x = 2 path, /* We should eliminate one evaluation of x + 1 along the x = 2 path,
causing one elimination. */ causing one elimination. */
/* { dg-final { scan-tree-dump-times "Eliminated:1" 1 "pre"} } */ /* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */
/* { dg-final { cleanup-tree-dump "pre" } } */ /* { dg-final { cleanup-tree-dump "pre" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-pre-stats" } */
int
foo (int *array)
{
if (array[1] != 0)
return array[1];
return 0;
}
/* We should eliminate one address calculation, and one load. */
/* { dg-final { scan-tree-dump-times "Eliminated: 2" 1 "pre"} } */
/* { dg-final { cleanup-tree-dump "pre" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-pre-stats" } */
struct s {
int *n;
};
int
foo (unsigned int i, struct s *array)
{
int *p = array[i].n;
if (p)
{
int *q = array[i].n;
if (p != q)
return 1;
}
return 0;
}
/* We should eliminate two address calculations, one cast, and one load. */
/* { dg-final { scan-tree-dump-times "Eliminated: 4" 1 "pre"} } */
/* { dg-final { cleanup-tree-dump "pre" } } */
...@@ -871,6 +871,7 @@ phi_translate (tree expr, value_set_t set, basic_block pred, ...@@ -871,6 +871,7 @@ phi_translate (tree expr, value_set_t set, basic_block pred,
return NULL; return NULL;
case tcc_binary: case tcc_binary:
case tcc_comparison:
{ {
tree oldop1 = TREE_OPERAND (expr, 0); tree oldop1 = TREE_OPERAND (expr, 0);
tree oldop2 = TREE_OPERAND (expr, 1); tree oldop2 = TREE_OPERAND (expr, 1);
...@@ -1057,6 +1058,7 @@ valid_in_set (value_set_t set, tree expr) ...@@ -1057,6 +1058,7 @@ valid_in_set (value_set_t set, tree expr)
switch (TREE_CODE_CLASS (TREE_CODE (expr))) switch (TREE_CODE_CLASS (TREE_CODE (expr)))
{ {
case tcc_binary: case tcc_binary:
case tcc_comparison:
{ {
tree op1 = TREE_OPERAND (expr, 0); tree op1 = TREE_OPERAND (expr, 0);
tree op2 = TREE_OPERAND (expr, 1); tree op2 = TREE_OPERAND (expr, 1);
...@@ -1077,6 +1079,10 @@ valid_in_set (value_set_t set, tree expr) ...@@ -1077,6 +1079,10 @@ valid_in_set (value_set_t set, tree expr)
gcc_assert (TREE_CODE (expr) == SSA_NAME); gcc_assert (TREE_CODE (expr) == SSA_NAME);
return true; return true;
case tcc_declaration:
/* VAR_DECL and PARM_DECL are never anticipatable. */
return false;
default: default:
/* No other cases should be encountered. */ /* No other cases should be encountered. */
gcc_unreachable (); gcc_unreachable ();
...@@ -1284,6 +1290,7 @@ find_or_generate_expression (basic_block block, tree expr, tree stmts) ...@@ -1284,6 +1290,7 @@ find_or_generate_expression (basic_block block, tree expr, tree stmts)
genop = VALUE_HANDLE_EXPR_SET (expr)->head->expr; genop = VALUE_HANDLE_EXPR_SET (expr)->head->expr;
gcc_assert (UNARY_CLASS_P (genop) gcc_assert (UNARY_CLASS_P (genop)
|| BINARY_CLASS_P (genop) || BINARY_CLASS_P (genop)
|| COMPARISON_CLASS_P (genop)
|| REFERENCE_CLASS_P (genop)); || REFERENCE_CLASS_P (genop));
genop = create_expression_by_pieces (block, genop, stmts); genop = create_expression_by_pieces (block, genop, stmts);
} }
...@@ -1315,6 +1322,7 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts) ...@@ -1315,6 +1322,7 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts)
switch (TREE_CODE_CLASS (TREE_CODE (expr))) switch (TREE_CODE_CLASS (TREE_CODE (expr)))
{ {
case tcc_binary: case tcc_binary:
case tcc_comparison:
{ {
tree_stmt_iterator tsi; tree_stmt_iterator tsi;
tree forced_stmts; tree forced_stmts;
...@@ -1466,6 +1474,7 @@ insert_into_preds_of_block (basic_block block, value_set_node_t node, ...@@ -1466,6 +1474,7 @@ insert_into_preds_of_block (basic_block block, value_set_node_t node,
bprime = pred->src; bprime = pred->src;
eprime = avail[bprime->index]; eprime = avail[bprime->index];
if (BINARY_CLASS_P (eprime) if (BINARY_CLASS_P (eprime)
|| COMPARISON_CLASS_P (eprime)
|| UNARY_CLASS_P (eprime)) || UNARY_CLASS_P (eprime))
{ {
builtexpr = create_expression_by_pieces (bprime, builtexpr = create_expression_by_pieces (bprime,
...@@ -1579,6 +1588,7 @@ insert_aux (basic_block block) ...@@ -1579,6 +1588,7 @@ insert_aux (basic_block block)
node = node->next) node = node->next)
{ {
if (BINARY_CLASS_P (node->expr) if (BINARY_CLASS_P (node->expr)
|| COMPARISON_CLASS_P (node->expr)
|| UNARY_CLASS_P (node->expr)) || UNARY_CLASS_P (node->expr))
{ {
tree *avail; tree *avail;
...@@ -1767,43 +1777,71 @@ add_to_sets (tree var, tree expr, vuse_optype vuses, bitmap_set_t s1, ...@@ -1767,43 +1777,71 @@ add_to_sets (tree var, tree expr, vuse_optype vuses, bitmap_set_t s1,
/* Given a unary or binary expression EXPR, create and return a new /* Given a unary or binary expression EXPR, create and return a new
expression with the same structure as EXPR but with its operands expression with the same structure as EXPR but with its operands
replaced with the value handles of each of the operands of EXPR. replaced with the value handles of each of the operands of EXPR.
Insert EXPR's operands into the EXP_GEN set for BLOCK.
VUSES represent the virtual use operands associated with EXPR (if VUSES represent the virtual use operands associated with EXPR (if
any). They are used when computing the hash value for EXPR. */ any). They are used when computing the hash value for EXPR.
Insert EXPR's operands into the EXP_GEN set for BLOCK. */
static inline tree static inline tree
create_value_expr_from (tree expr, basic_block block, vuse_optype vuses) create_value_expr_from (tree expr, basic_block block,
vuse_optype vuses)
{ {
int i; int i;
enum tree_code code = TREE_CODE (expr); enum tree_code code = TREE_CODE (expr);
tree vexpr; tree vexpr;
alloc_pool pool;
gcc_assert (TREE_CODE_CLASS (code) == tcc_unary gcc_assert (TREE_CODE_CLASS (code) == tcc_unary
|| TREE_CODE_CLASS (code) == tcc_binary || TREE_CODE_CLASS (code) == tcc_binary
|| TREE_CODE_CLASS (code) == tcc_comparison
|| TREE_CODE_CLASS (code) == tcc_reference); || TREE_CODE_CLASS (code) == tcc_reference);
if (TREE_CODE_CLASS (code) == tcc_unary) if (TREE_CODE_CLASS (code) == tcc_unary)
vexpr = pool_alloc (unary_node_pool); pool = unary_node_pool;
else if (TREE_CODE_CLASS (code) == tcc_reference) else if (TREE_CODE_CLASS (code) == tcc_reference)
vexpr = pool_alloc (reference_node_pool); pool = reference_node_pool;
else else
vexpr = pool_alloc (binary_node_pool); pool = binary_node_pool;
vexpr = pool_alloc (pool);
memcpy (vexpr, expr, tree_size (expr)); memcpy (vexpr, expr, tree_size (expr));
for (i = 0; i < TREE_CODE_LENGTH (code); i++) for (i = 0; i < TREE_CODE_LENGTH (code); i++)
{ {
tree op = TREE_OPERAND (expr, i); tree val, op;
if (op != NULL)
op = TREE_OPERAND (expr, i);
if (op == NULL_TREE)
continue;
/* If OP is a constant that has overflowed, do not value number
this expression. */
if (TREE_CODE_CLASS (TREE_CODE (op)) == tcc_constant
&& TREE_OVERFLOW (op))
{
pool_free (pool, vexpr);
return NULL;
}
/* Recursively value-numberize reference ops */
if (TREE_CODE_CLASS (TREE_CODE (op)) == tcc_reference)
{ {
tree val = vn_lookup_or_add (op, vuses); tree tempop = create_value_expr_from (op, block, vuses);
if (!is_undefined_value (op)) op = tempop ? tempop : op;
value_insert_into_set (EXP_GEN (block), op); val = vn_lookup_or_add (op, vuses);
if (TREE_CODE (val) == VALUE_HANDLE)
TREE_TYPE (val) = TREE_TYPE (TREE_OPERAND (vexpr, i));
TREE_OPERAND (vexpr, i) = val;
} }
else
/* Create a value handle for OP and add it to VEXPR. */
val = vn_lookup_or_add (op, NULL);
if (!is_undefined_value (op))
value_insert_into_set (EXP_GEN (block), op);
if (TREE_CODE (val) == VALUE_HANDLE)
TREE_TYPE (val) = TREE_TYPE (TREE_OPERAND (vexpr, i));
TREE_OPERAND (vexpr, i) = val;
} }
return vexpr; return vexpr;
...@@ -1902,8 +1940,29 @@ compute_avail (void) ...@@ -1902,8 +1940,29 @@ compute_avail (void)
vuse_optype vuses = STMT_VUSE_OPS (stmt); vuse_optype vuses = STMT_VUSE_OPS (stmt);
STRIP_USELESS_TYPE_CONVERSION (rhs); STRIP_USELESS_TYPE_CONVERSION (rhs);
if (TREE_CODE (rhs) == SSA_NAME if (UNARY_CLASS_P (rhs)
|| is_gimple_min_invariant (rhs)) || BINARY_CLASS_P (rhs)
|| COMPARISON_CLASS_P (rhs)
|| REFERENCE_CLASS_P (rhs))
{
/* For binary, unary, and reference expressions,
create a duplicate expression with the operands
replaced with the value handles of the original
RHS. */
tree newt = create_value_expr_from (rhs, block, vuses);
if (newt)
{
add_to_sets (lhs, newt, vuses, TMP_GEN (block),
AVAIL_OUT (block));
value_insert_into_set (EXP_GEN (block), newt);
continue;
}
}
else if (TREE_CODE (rhs) == SSA_NAME
|| is_gimple_min_invariant (rhs)
|| TREE_INVARIANT (rhs)
|| TREE_CODE (rhs) == ADDR_EXPR
|| DECL_P (rhs))
{ {
/* Compute a value number for the RHS of the statement /* Compute a value number for the RHS of the statement
and add its value to the AVAIL_OUT set for the block. and add its value to the AVAIL_OUT set for the block.
...@@ -1916,19 +1975,6 @@ compute_avail (void) ...@@ -1916,19 +1975,6 @@ compute_avail (void)
value_insert_into_set (EXP_GEN (block), rhs); value_insert_into_set (EXP_GEN (block), rhs);
continue; continue;
} }
else if (UNARY_CLASS_P (rhs) || BINARY_CLASS_P (rhs)
|| TREE_CODE (rhs) == INDIRECT_REF)
{
/* For binary, unary, and reference expressions,
create a duplicate expression with the operands
replaced with the value handles of the original
RHS. */
tree newt = create_value_expr_from (rhs, block, vuses);
add_to_sets (lhs, newt, vuses, TMP_GEN (block),
AVAIL_OUT (block));
value_insert_into_set (EXP_GEN (block), newt);
continue;
}
} }
/* For any other statement that we don't recognize, simply /* For any other statement that we don't recognize, simply
...@@ -2286,10 +2332,10 @@ execute_pre (bool do_fre) ...@@ -2286,10 +2332,10 @@ execute_pre (bool do_fre)
if (dump_file && (dump_flags & TDF_STATS)) if (dump_file && (dump_flags & TDF_STATS))
{ {
fprintf (dump_file, "Insertions:%d\n", pre_stats.insertions); fprintf (dump_file, "Insertions: %d\n", pre_stats.insertions);
fprintf (dump_file, "New PHIs:%d\n", pre_stats.phis); fprintf (dump_file, "New PHIs: %d\n", pre_stats.phis);
fprintf (dump_file, "Eliminated:%d\n", pre_stats.eliminations); fprintf (dump_file, "Eliminated: %d\n", pre_stats.eliminations);
fprintf (dump_file, "Constified:%d\n", pre_stats.constified); fprintf (dump_file, "Constified: %d\n", pre_stats.constified);
} }
bsi_commit_edge_inserts (); bsi_commit_edge_inserts ();
...@@ -2336,7 +2382,7 @@ struct tree_opt_pass pass_pre = ...@@ -2336,7 +2382,7 @@ struct tree_opt_pass pass_pre =
/* Gate and execute functions for FRE. */ /* Gate and execute functions for FRE. */
static void static void
do_fre (void) execute_fre (void)
{ {
execute_pre (true); execute_pre (true);
} }
...@@ -2351,7 +2397,7 @@ struct tree_opt_pass pass_fre = ...@@ -2351,7 +2397,7 @@ struct tree_opt_pass pass_fre =
{ {
"fre", /* name */ "fre", /* name */
gate_fre, /* gate */ gate_fre, /* gate */
do_fre, /* execute */ execute_fre, /* execute */
NULL, /* sub */ NULL, /* sub */
NULL, /* next */ NULL, /* next */
0, /* static_pass_number */ 0, /* static_pass_number */
......
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