From: Andrew Pinski <apin...@marvell.com> The problem here is tree-ssa-forwprop.c likes to produce &MEM <const char *> [(void *)_4 + 152B] which is the same as _4 p+ 152 which the rest of GCC likes better. This implements this transformation back to pointer plus to improve better code generation later on.
OK? Bootstrapped and tested on aarch64-linux-gnu. Changes from v1: * v2: Add comments. gcc/ChangeLog: PR tree-optimization/102216 * tree-ssa-forwprop.c (rewrite_assign_addr): New function. (forward_propagate_addr_expr_1): Use rewrite_assign_addr when rewriting into the addr_expr into an assignment. gcc/testsuite/ChangeLog: PR tree-optimization/102216 * g++.dg/tree-ssa/pr102216.C: New test. --- gcc/testsuite/g++.dg/tree-ssa/pr102216.C | 22 +++++++++ gcc/tree-ssa-forwprop.c | 58 ++++++++++++++++++------ 2 files changed, 67 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/g++.dg/tree-ssa/pr102216.C diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr102216.C b/gcc/testsuite/g++.dg/tree-ssa/pr102216.C new file mode 100644 index 00000000000..b903e4eb57d --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/pr102216.C @@ -0,0 +1,22 @@ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +void link_error (); +void g () +{ + const char **language_names; + + language_names = new const char *[6]; + + const char **language_names_p = language_names; + + language_names_p++; + language_names_p++; + language_names_p++; + + if ( (language_names_p) - (language_names+3) != 0) + link_error(); + delete[] language_names; +} +/* We should have removed the link_error on the gimple level as GCC should + be able to tell that language_names_p is the same as language_names+3. */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" } } */ + diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index a830bab78ba..e4331c60525 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -637,6 +637,47 @@ forward_propagate_into_cond (gimple_stmt_iterator *gsi_p) return 0; } +/* Rewrite the DEF_RHS as needed into the (plain) use statement. */ + +static void +rewrite_assign_addr (gimple_stmt_iterator *use_stmt_gsi, tree def_rhs) +{ + tree def_rhs_base; + poly_int64 def_rhs_offset; + + /* Get the base and offset. */ + if ((def_rhs_base = get_addr_base_and_unit_offset (TREE_OPERAND (def_rhs, 0), + &def_rhs_offset))) + { + tree new_ptr; + poly_offset_int off = 0; + + /* If the base was a MEM, then add the offset to the other + offset and adjust the base. */ + if (TREE_CODE (def_rhs_base) == MEM_REF) + { + off += mem_ref_offset (def_rhs_base); + new_ptr = TREE_OPERAND (def_rhs_base, 0); + } + else + new_ptr = build_fold_addr_expr (def_rhs_base); + + /* If we have the new base is not an address express, then use a p+ expression + as the new expression instead of &MEM[x, offset]. */ + if (TREE_CODE (new_ptr) != ADDR_EXPR) + { + tree offset = wide_int_to_tree (sizetype, off); + def_rhs = build2 (POINTER_PLUS_EXPR, TREE_TYPE (def_rhs), new_ptr, offset); + } + } + + /* Replace the rhs with the new expression. */ + def_rhs = unshare_expr (def_rhs); + gimple_assign_set_rhs_from_tree (use_stmt_gsi, def_rhs); + gimple *use_stmt = gsi_stmt (*use_stmt_gsi); + update_stmt (use_stmt); +} + /* We've just substituted an ADDR_EXPR into stmt. Update all the relevant data structures to match. */ @@ -696,8 +737,8 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, if (single_use_p && useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (def_rhs))) { - gimple_assign_set_rhs1 (use_stmt, unshare_expr (def_rhs)); - gimple_assign_set_rhs_code (use_stmt, TREE_CODE (def_rhs)); + rewrite_assign_addr (use_stmt_gsi, def_rhs); + gcc_assert (gsi_stmt (*use_stmt_gsi) == use_stmt); return true; } @@ -741,14 +782,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, if (forward_propagate_addr_expr (lhs, new_def_rhs, single_use_p)) return true; - if (useless_type_conversion_p (TREE_TYPE (lhs), - TREE_TYPE (new_def_rhs))) - gimple_assign_set_rhs_with_ops (use_stmt_gsi, TREE_CODE (new_def_rhs), - new_def_rhs); - else if (is_gimple_min_invariant (new_def_rhs)) - gimple_assign_set_rhs_with_ops (use_stmt_gsi, NOP_EXPR, new_def_rhs); - else - return false; + rewrite_assign_addr (use_stmt_gsi, new_def_rhs); gcc_assert (gsi_stmt (*use_stmt_gsi) == use_stmt); update_stmt (use_stmt); return true; @@ -951,9 +985,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, unshare_expr (def_rhs), fold_convert (ptr_type_node, rhs2))); - gimple_assign_set_rhs_from_tree (use_stmt_gsi, new_rhs); - use_stmt = gsi_stmt (*use_stmt_gsi); - update_stmt (use_stmt); + rewrite_assign_addr (use_stmt_gsi, new_rhs); tidy_after_forward_propagate_addr (use_stmt); return true; } -- 2.17.1