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>
* doc/invoke.texi (SPARC options): Document that
......
......@@ -17,5 +17,5 @@ int main(int argc, char **argv)
}
/* We should eliminate one evaluation of b + c along the 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" } } */
......@@ -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
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" } } */
......@@ -11,5 +11,5 @@ unsigned foo1 (unsigned a, unsigned b)
return j + k;
}
/* 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" } } */
......@@ -11,5 +11,5 @@ int main(void)
}
/* We should eliminate the x+1 computation from this routine, replacing
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" } } */
......@@ -12,5 +12,5 @@ foo (int i)
}
/* We should detect that a+b is the same along both edges, and replace it with
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" } } */
......@@ -10,5 +10,5 @@ int main(int x)
}
/* We should eliminate one evaluation of x + 1 along the x = 2 path,
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-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,
return NULL;
case tcc_binary:
case tcc_comparison:
{
tree oldop1 = TREE_OPERAND (expr, 0);
tree oldop2 = TREE_OPERAND (expr, 1);
......@@ -1057,6 +1058,7 @@ valid_in_set (value_set_t set, tree expr)
switch (TREE_CODE_CLASS (TREE_CODE (expr)))
{
case tcc_binary:
case tcc_comparison:
{
tree op1 = TREE_OPERAND (expr, 0);
tree op2 = TREE_OPERAND (expr, 1);
......@@ -1077,6 +1079,10 @@ valid_in_set (value_set_t set, tree expr)
gcc_assert (TREE_CODE (expr) == SSA_NAME);
return true;
case tcc_declaration:
/* VAR_DECL and PARM_DECL are never anticipatable. */
return false;
default:
/* No other cases should be encountered. */
gcc_unreachable ();
......@@ -1284,6 +1290,7 @@ find_or_generate_expression (basic_block block, tree expr, tree stmts)
genop = VALUE_HANDLE_EXPR_SET (expr)->head->expr;
gcc_assert (UNARY_CLASS_P (genop)
|| BINARY_CLASS_P (genop)
|| COMPARISON_CLASS_P (genop)
|| REFERENCE_CLASS_P (genop));
genop = create_expression_by_pieces (block, genop, stmts);
}
......@@ -1315,6 +1322,7 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts)
switch (TREE_CODE_CLASS (TREE_CODE (expr)))
{
case tcc_binary:
case tcc_comparison:
{
tree_stmt_iterator tsi;
tree forced_stmts;
......@@ -1466,6 +1474,7 @@ insert_into_preds_of_block (basic_block block, value_set_node_t node,
bprime = pred->src;
eprime = avail[bprime->index];
if (BINARY_CLASS_P (eprime)
|| COMPARISON_CLASS_P (eprime)
|| UNARY_CLASS_P (eprime))
{
builtexpr = create_expression_by_pieces (bprime,
......@@ -1579,6 +1588,7 @@ insert_aux (basic_block block)
node = node->next)
{
if (BINARY_CLASS_P (node->expr)
|| COMPARISON_CLASS_P (node->expr)
|| UNARY_CLASS_P (node->expr))
{
tree *avail;
......@@ -1767,44 +1777,72 @@ 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
expression with the same structure as EXPR but with its operands
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
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
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;
enum tree_code code = TREE_CODE (expr);
tree vexpr;
alloc_pool pool;
gcc_assert (TREE_CODE_CLASS (code) == tcc_unary
|| TREE_CODE_CLASS (code) == tcc_binary
|| TREE_CODE_CLASS (code) == tcc_comparison
|| TREE_CODE_CLASS (code) == tcc_reference);
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)
vexpr = pool_alloc (reference_node_pool);
pool = reference_node_pool;
else
vexpr = pool_alloc (binary_node_pool);
pool = binary_node_pool;
vexpr = pool_alloc (pool);
memcpy (vexpr, expr, tree_size (expr));
for (i = 0; i < TREE_CODE_LENGTH (code); i++)
{
tree op = TREE_OPERAND (expr, i);
if (op != NULL)
tree val, op;
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);
op = tempop ? tempop : op;
val = vn_lookup_or_add (op, vuses);
}
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;
}
......@@ -1902,8 +1940,29 @@ compute_avail (void)
vuse_optype vuses = STMT_VUSE_OPS (stmt);
STRIP_USELESS_TYPE_CONVERSION (rhs);
if (TREE_CODE (rhs) == SSA_NAME
|| is_gimple_min_invariant (rhs))
if (UNARY_CLASS_P (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
and add its value to the AVAIL_OUT set for the block.
......@@ -1916,19 +1975,6 @@ compute_avail (void)
value_insert_into_set (EXP_GEN (block), rhs);
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
......@@ -2286,10 +2332,10 @@ execute_pre (bool do_fre)
if (dump_file && (dump_flags & TDF_STATS))
{
fprintf (dump_file, "Insertions:%d\n", pre_stats.insertions);
fprintf (dump_file, "New PHIs:%d\n", pre_stats.phis);
fprintf (dump_file, "Eliminated:%d\n", pre_stats.eliminations);
fprintf (dump_file, "Constified:%d\n", pre_stats.constified);
fprintf (dump_file, "Insertions: %d\n", pre_stats.insertions);
fprintf (dump_file, "New PHIs: %d\n", pre_stats.phis);
fprintf (dump_file, "Eliminated: %d\n", pre_stats.eliminations);
fprintf (dump_file, "Constified: %d\n", pre_stats.constified);
}
bsi_commit_edge_inserts ();
......@@ -2336,7 +2382,7 @@ struct tree_opt_pass pass_pre =
/* Gate and execute functions for FRE. */
static void
do_fre (void)
execute_fre (void)
{
execute_pre (true);
}
......@@ -2351,7 +2397,7 @@ struct tree_opt_pass pass_fre =
{
"fre", /* name */
gate_fre, /* gate */
do_fre, /* execute */
execute_fre, /* execute */
NULL, /* sub */
NULL, /* next */
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