diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5b975fd18e43..0f81767d3793 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2009-03-31 Richard Guenther + + * tree.h (div_if_zero_remainder): Declare. + * fold-const.c (div_if_zero_remainder): Export. + * tree-ssa-forwprop.c + (forward_propagate_addr_into_variable_array_index): Handle + constant array index addition outside of the variable index. + 2009-03-31 Joseph Myers PR target/39592 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index a56e885fbf8f..4951600a2976 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -874,7 +874,7 @@ div_and_round_double (enum tree_code code, int uns, of type CODE and returns the quotient. Otherwise returns NULL_TREE. */ -static tree +tree div_if_zero_remainder (enum tree_code code, const_tree arg1, const_tree arg2) { unsigned HOST_WIDE_INT int1l, int2l; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4dab8771ddad..9b1aef31f306 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2009-03-31 Richard Guenther + + * gcc.dg/tree-ssa/forwprop-12.c: New testcase. + 2009-03-31 Joseph Myers PR target/39592 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-12.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-12.c new file mode 100644 index 000000000000..a74809b609e3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-12.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-forwprop1" } */ + +struct X { int a[256]; }; + +int foo(struct X *p, __SIZE_TYPE__ i) +{ + int *q = &p->a[0]; + int *q2 = (int *)((void *)q + i*4 + 32); + return *q2; +} + +int bar(struct X *p, int i) +{ + return *((int *)p + i + 8); +} + +/* We should have propagated the base array address through the + address arithmetic into the memory access as an array access. */ + +/* { dg-final { scan-tree-dump-times "->a\\\[D\\\." 2 "forwprop1" } } */ +/* { dg-final { cleanup-tree-dump "forwprop1" } } */ diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index 859d6fe61726..044f8436559e 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -618,8 +618,13 @@ forward_propagate_addr_into_variable_array_index (tree offset, tree def_rhs, gimple_stmt_iterator *use_stmt_gsi) { - tree index; + tree index, tunit; gimple offset_def, use_stmt = gsi_stmt (*use_stmt_gsi); + tree tmp; + + tunit = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (def_rhs))); + if (!host_integerp (tunit, 1)) + return false; /* Get the offset's defining statement. */ offset_def = SSA_NAME_DEF_STMT (offset); @@ -629,7 +634,7 @@ forward_propagate_addr_into_variable_array_index (tree offset, along in case the element size is one. In that case, however, we do not allow multiplications because they can be computing index to a higher level dimension (PR 37861). */ - if (integer_onep (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (def_rhs))))) + if (integer_onep (tunit)) { if (is_gimple_assign (offset_def) && gimple_assign_rhs_code (offset_def) == MULT_EXPR) @@ -648,18 +653,41 @@ forward_propagate_addr_into_variable_array_index (tree offset, multiplication of an object by the size of the array elements. This implicitly verifies that the size of the array elements is constant. */ - offset = gimple_assign_rhs1 (offset_def); - if (gimple_assign_rhs_code (offset_def) != MULT_EXPR - || TREE_CODE (gimple_assign_rhs2 (offset_def)) != INTEGER_CST - || !simple_cst_equal (gimple_assign_rhs2 (offset_def), - TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (def_rhs))))) + if (gimple_assign_rhs_code (offset_def) == MULT_EXPR + && TREE_CODE (gimple_assign_rhs2 (offset_def)) == INTEGER_CST + && tree_int_cst_equal (gimple_assign_rhs2 (offset_def), tunit)) + { + /* The first operand to the MULT_EXPR is the desired index. */ + index = gimple_assign_rhs1 (offset_def); + } + /* If we have idx * tunit + CST * tunit re-associate that. */ + else if ((gimple_assign_rhs_code (offset_def) == PLUS_EXPR + || gimple_assign_rhs_code (offset_def) == MINUS_EXPR) + && TREE_CODE (gimple_assign_rhs1 (offset_def)) == SSA_NAME + && TREE_CODE (gimple_assign_rhs2 (offset_def)) == INTEGER_CST + && (tmp = div_if_zero_remainder (EXACT_DIV_EXPR, + gimple_assign_rhs2 (offset_def), + tunit)) != NULL_TREE) + { + gimple offset_def2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (offset_def)); + if (gimple_assign_rhs_code (offset_def2) == MULT_EXPR + && TREE_CODE (gimple_assign_rhs2 (offset_def2)) == INTEGER_CST + && tree_int_cst_equal (gimple_assign_rhs2 (offset_def2), tunit)) + { + index = fold_build2 (gimple_assign_rhs_code (offset_def), + TREE_TYPE (offset), + gimple_assign_rhs1 (offset_def2), tmp); + } + else + return false; + } + else return false; - - /* The first operand to the MULT_EXPR is the desired index. */ - index = offset; } /* Replace the pointer addition with array indexing. */ + index = force_gimple_operand_gsi (use_stmt_gsi, index, true, NULL_TREE, + true, GSI_SAME_STMT); gimple_assign_set_rhs_from_tree (use_stmt_gsi, unshare_expr (def_rhs)); use_stmt = gsi_stmt (*use_stmt_gsi); TREE_OPERAND (TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0), 1) diff --git a/gcc/tree.h b/gcc/tree.h index 1a83c2505da5..4e67c6aeaddb 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -4832,6 +4832,7 @@ extern tree build_fold_indirect_ref (tree); extern tree fold_indirect_ref (tree); extern tree constant_boolean_node (int, tree); extern tree build_low_bits_mask (tree, unsigned); +extern tree div_if_zero_remainder (enum tree_code, const_tree, const_tree); extern bool tree_swap_operands_p (const_tree, const_tree, bool); extern enum tree_code swap_tree_comparison (enum tree_code);