From 7b1737d07a6b869120d7fca9bd755c9e426a0bfe Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Fri, 16 Mar 2007 10:11:14 +0000 Subject: [PATCH] re PR tree-optimization/31146 (forwprop does not look through casts) 2007-03-16 Richard Guenther PR tree-optimization/31146 * tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Restructure to allow recursion of forward_propagate_addr_expr. (forward_propagate_addr_into_variable_array_index): Likewise. (forward_propagate_addr_expr): Likewise. (tree_ssa_forward_propagate_single_use_vars): Likewise. (forward_propagate_addr_expr_1): Recurse on simple copies instead of propagating into them. Do so for useless conversions as well. (forward_propagate_addr_expr): Clean up unused statements after recursion. * g++.dg/tree-ssa/pr31146.C: New testcase. From-SVN: r122985 --- gcc/ChangeLog | 14 ++++++ gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/g++.dg/tree-ssa/pr31146.C | 16 +++++++ gcc/tree-ssa-forwprop.c | 80 +++++++++++++++++++-------------- 4 files changed, 81 insertions(+), 34 deletions(-) create mode 100644 gcc/testsuite/g++.dg/tree-ssa/pr31146.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 47f05b9..e85b40d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,19 @@ 2007-03-16 Richard Guenther + PR tree-optimization/31146 + * tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Restructure + to allow recursion of forward_propagate_addr_expr. + (forward_propagate_addr_into_variable_array_index): Likewise. + (forward_propagate_addr_expr): Likewise. + (tree_ssa_forward_propagate_single_use_vars): Likewise. + (forward_propagate_addr_expr_1): Recurse on simple copies + instead of propagating into them. Do so for useless conversions + as well. + (forward_propagate_addr_expr): Clean up unused statements after + recursion. + +2007-03-16 Richard Guenther + * builtins.c (expand_builtin_cexpi): Use the right argument for the expansion via cexp. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5050902..1b47256 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2007-03-16 Richard Guenther + + PR tree-optimization/31146 + * g++.dg/tree-ssa/pr31146.C: New testcase. + 2007-03-16 Richard Sandiford * lib/target-supports.exp (check_missing_uclibc_feature): Don't diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr31146.C b/gcc/testsuite/g++.dg/tree-ssa/pr31146.C new file mode 100644 index 0000000..e91d174 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/pr31146.C @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-forwprop1" } */ + +/* We should be able to optimize this to i[j] = 1 during + early optimizations. */ + +int i[5]; +void foo (int j) +{ + void *p = &i[j]; + int *q = (int *)p; + *q = 1; +} + +/* { dg-final { scan-tree-dump "i\\\[j.*\\\] = 1;" "forwprop1" } } */ +/* { dg-final { cleanup-tree-dump "forwprop1" } } */ diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index a854841..a755a4a 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -149,6 +149,7 @@ Boston, MA 02110-1301, USA. */ This will (of course) be extended as other needs arise. */ +static bool forward_propagate_addr_expr (tree name, tree rhs); /* Set to true if we delete EH edges during the optimization. */ static bool cfg_changed; @@ -591,7 +592,7 @@ tidy_after_forward_propagate_addr (tree stmt) mark_symbols_for_renaming (stmt); } -/* STMT defines LHS which is contains the address of the 0th element +/* DEF_RHS defines LHS which is contains the address of the 0th element in an array. USE_STMT uses LHS to compute the address of an arbitrary element within the array. The (variable) byte offset of the element is contained in OFFSET. @@ -608,7 +609,7 @@ tidy_after_forward_propagate_addr (tree stmt) static bool forward_propagate_addr_into_variable_array_index (tree offset, tree lhs, - tree stmt, tree use_stmt) + tree def_rhs, tree use_stmt) { tree index; @@ -650,8 +651,7 @@ forward_propagate_addr_into_variable_array_index (tree offset, tree lhs, index = TREE_OPERAND (offset, 0); /* Replace the pointer addition with array indexing. */ - GIMPLE_STMT_OPERAND (use_stmt, 1) - = unshare_expr (GIMPLE_STMT_OPERAND (stmt, 1)); + GIMPLE_STMT_OPERAND (use_stmt, 1) = unshare_expr (def_rhs); TREE_OPERAND (TREE_OPERAND (GIMPLE_STMT_OPERAND (use_stmt, 1), 0), 1) = index; @@ -662,7 +662,8 @@ forward_propagate_addr_into_variable_array_index (tree offset, tree lhs, return true; } -/* STMT is a statement of the form SSA_NAME = ADDR_EXPR . +/* NAME is a SSA_NAME representing DEF_RHS which is of the form + ADDR_EXPR . Try to forward propagate the ADDR_EXPR into the use USE_STMT. Often this will allow for removal of an ADDR_EXPR and INDIRECT_REF @@ -672,9 +673,8 @@ forward_propagate_addr_into_variable_array_index (tree offset, tree lhs, be not totally successful, yet things may have been changed). */ static bool -forward_propagate_addr_expr_1 (tree stmt, tree use_stmt) +forward_propagate_addr_expr_1 (tree name, tree def_rhs, tree use_stmt) { - tree name = GIMPLE_STMT_OPERAND (stmt, 0); tree lhs, rhs, array_ref; /* Strip away any outer COMPONENT_REF/ARRAY_REF nodes from the LHS. @@ -683,36 +683,37 @@ forward_propagate_addr_expr_1 (tree stmt, tree use_stmt) while (TREE_CODE (lhs) == COMPONENT_REF || TREE_CODE (lhs) == ARRAY_REF) lhs = TREE_OPERAND (lhs, 0); + rhs = GIMPLE_STMT_OPERAND (use_stmt, 1); + /* Now see if the LHS node is an INDIRECT_REF using NAME. If so, propagate the ADDR_EXPR into the use of NAME and fold the result. */ if (TREE_CODE (lhs) == INDIRECT_REF && TREE_OPERAND (lhs, 0) == name) { /* This should always succeed in creating gimple, so there is no need to save enough state to undo this propagation. */ - TREE_OPERAND (lhs, 0) = unshare_expr (GIMPLE_STMT_OPERAND (stmt, 1)); + TREE_OPERAND (lhs, 0) = unshare_expr (def_rhs); fold_stmt_inplace (use_stmt); tidy_after_forward_propagate_addr (use_stmt); - } - /* Trivial case. The use statement could be a trivial copy. We - go ahead and handle that case here since it's trivial and - removes the need to run copy-prop before this pass to get - the best results. Also note that by handling this case here - we can catch some cascading effects, ie the single use is - in a copy, and the copy is used later by a single INDIRECT_REF - for example. */ - else if (TREE_CODE (lhs) == SSA_NAME - && GIMPLE_STMT_OPERAND (use_stmt, 1) == name) - { - GIMPLE_STMT_OPERAND (use_stmt, 1) - = unshare_expr (GIMPLE_STMT_OPERAND (stmt, 1)); - tidy_after_forward_propagate_addr (use_stmt); - return true; + /* The only case we did not replace all uses this way is if the + use statement is of the form *name = name. */ + return rhs != name; } + /* Trivial case. The use statement could be a trivial copy or a + useless conversion. Recurse to the uses of the lhs as copyprop does + not copy through differen variant pointers and FRE does not catch + all useless conversions. */ + else if ((TREE_CODE (lhs) == SSA_NAME + && rhs == name) + || ((TREE_CODE (rhs) == NOP_EXPR + || TREE_CODE (rhs) == CONVERT_EXPR) + && tree_ssa_useless_type_conversion_1 (TREE_TYPE (rhs), + TREE_TYPE (def_rhs)))) + return forward_propagate_addr_expr (lhs, def_rhs); + /* Strip away any outer COMPONENT_REF, ARRAY_REF or ADDR_EXPR nodes from the RHS. */ - rhs = GIMPLE_STMT_OPERAND (use_stmt, 1); while (TREE_CODE (rhs) == COMPONENT_REF || TREE_CODE (rhs) == ARRAY_REF || TREE_CODE (rhs) == ADDR_EXPR) @@ -724,7 +725,7 @@ forward_propagate_addr_expr_1 (tree stmt, tree use_stmt) { /* This should always succeed in creating gimple, so there is no need to save enough state to undo this propagation. */ - TREE_OPERAND (rhs, 0) = unshare_expr (GIMPLE_STMT_OPERAND (stmt, 1)); + TREE_OPERAND (rhs, 0) = unshare_expr (def_rhs); fold_stmt_inplace (use_stmt); tidy_after_forward_propagate_addr (use_stmt); return true; @@ -734,7 +735,7 @@ forward_propagate_addr_expr_1 (tree stmt, tree use_stmt) array indexing. They only apply when we have the address of element zero in an array. If that is not the case then there is nothing to do. */ - array_ref = TREE_OPERAND (GIMPLE_STMT_OPERAND (stmt, 1), 0); + array_ref = TREE_OPERAND (def_rhs, 0); if (TREE_CODE (array_ref) != ARRAY_REF || TREE_CODE (TREE_TYPE (TREE_OPERAND (array_ref, 0))) != ARRAY_TYPE || !integer_zerop (TREE_OPERAND (array_ref, 1))) @@ -751,7 +752,7 @@ forward_propagate_addr_expr_1 (tree stmt, tree use_stmt) && TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST) { tree orig = unshare_expr (rhs); - TREE_OPERAND (rhs, 0) = unshare_expr (GIMPLE_STMT_OPERAND (stmt, 1)); + TREE_OPERAND (rhs, 0) = unshare_expr (def_rhs); /* If folding succeeds, then we have just exposed new variables in USE_STMT which will need to be renamed. If folding fails, @@ -783,7 +784,7 @@ forward_propagate_addr_expr_1 (tree stmt, tree use_stmt) tree offset_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 1)); res = forward_propagate_addr_into_variable_array_index (offset_stmt, lhs, - stmt, use_stmt); + def_rhs, use_stmt); return res; } @@ -798,7 +799,7 @@ forward_propagate_addr_expr_1 (tree stmt, tree use_stmt) bool res; tree offset_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 0)); res = forward_propagate_addr_into_variable_array_index (offset_stmt, lhs, - stmt, use_stmt); + def_rhs, use_stmt); return res; } return false; @@ -812,10 +813,9 @@ forward_propagate_addr_expr_1 (tree stmt, tree use_stmt) Returns true, if all uses have been propagated into. */ static bool -forward_propagate_addr_expr (tree stmt) +forward_propagate_addr_expr (tree name, tree rhs) { - int stmt_loop_depth = bb_for_stmt (stmt)->loop_depth; - tree name = GIMPLE_STMT_OPERAND (stmt, 0); + int stmt_loop_depth = bb_for_stmt (SSA_NAME_DEF_STMT (name))->loop_depth; imm_use_iterator iter; tree use_stmt; bool all = true; @@ -843,10 +843,22 @@ forward_propagate_addr_expr (tree stmt) push_stmt_changes (&use_stmt); - result = forward_propagate_addr_expr_1 (stmt, use_stmt); + result = forward_propagate_addr_expr_1 (name, rhs, use_stmt); all &= result; pop_stmt_changes (&use_stmt); + + /* Remove intermediate now unused copy and conversion chains. */ + if (result + && TREE_CODE (GIMPLE_STMT_OPERAND (use_stmt, 0)) == SSA_NAME + && (TREE_CODE (GIMPLE_STMT_OPERAND (use_stmt, 1)) == SSA_NAME + || TREE_CODE (GIMPLE_STMT_OPERAND (use_stmt, 1)) == NOP_EXPR + || TREE_CODE (GIMPLE_STMT_OPERAND (use_stmt, 1)) == CONVERT_EXPR)) + { + block_stmt_iterator bsi = bsi_for_stmt (use_stmt); + release_defs (use_stmt); + bsi_remove (&bsi, true); + } } return all; @@ -981,7 +993,7 @@ tree_ssa_forward_propagate_single_use_vars (void) if (TREE_CODE (rhs) == ADDR_EXPR) { - if (forward_propagate_addr_expr (stmt)) + if (forward_propagate_addr_expr (lhs, rhs)) { release_defs (stmt); todoflags |= TODO_remove_unused_locals; -- 2.7.4