diff options
author | Daniel Berlin <dberlin@dberlin.org> | 2005-04-04 19:02:16 +0000 |
---|---|---|
committer | Daniel Berlin <dberlin@gcc.gnu.org> | 2005-04-04 19:02:16 +0000 |
commit | b89361c670cc86ff43dcf87de2b293c19b8dce35 (patch) | |
tree | 3d8c8ff124a2a0ad303cc21d734adc4803674f99 /gcc | |
parent | 6a5d24d70d5c0f4d53b1796ed5e8c3fd252dc268 (diff) | |
download | gcc-b89361c670cc86ff43dcf87de2b293c19b8dce35.zip gcc-b89361c670cc86ff43dcf87de2b293c19b8dce35.tar.gz gcc-b89361c670cc86ff43dcf87de2b293c19b8dce35.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-1.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-2.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-3.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-4.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-5.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-6.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-7.c | 12 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c | 21 | ||||
-rw-r--r-- | gcc/tree-ssa-pre.c | 116 |
10 files changed, 138 insertions, 41 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fd38d96..5c4716f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +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 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-1.c index a2fc435..3bdd204 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-1.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-2.c index 3a11078..6df2611 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-2.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-3.c index 6952bc6..3925f75 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-3.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-3.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-4.c index acb7f5a..6f4c2f3 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-4.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-4.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-5.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-5.c index c3f79c2..8756944 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-5.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-5.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-6.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-6.c index 39b0e83..a639e9d 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-6.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-6.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-7.c new file mode 100644 index 0000000..642c36c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-7.c @@ -0,0 +1,12 @@ +/* { 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" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c new file mode 100644 index 0000000..f8e1921 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c @@ -0,0 +1,21 @@ +/* { 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" } } */ diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index 5593c00..6ca0b0a 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -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,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 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); - 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; + 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 */ |