aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2009-03-31 13:16:36 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2009-03-31 13:16:36 +0000
commit108f6c2f4efe0141c859eeb52fae610b8806ffc8 (patch)
tree3df6a2c649d9c629a5bac8622a791c03866243b3
parent8f6121903f11d285d7494ae15bb9d36a27e1a405 (diff)
downloadgcc-108f6c2f4efe0141c859eeb52fae610b8806ffc8.zip
gcc-108f6c2f4efe0141c859eeb52fae610b8806ffc8.tar.gz
gcc-108f6c2f4efe0141c859eeb52fae610b8806ffc8.tar.bz2
tree.h (div_if_zero_remainder): Declare.
2009-03-31 Richard Guenther <rguenther@suse.de> * 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. * gcc.dg/tree-ssa/forwprop-12.c: New testcase. From-SVN: r145343
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/fold-const.c2
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/forwprop-12.c22
-rw-r--r--gcc/tree-ssa-forwprop.c48
-rw-r--r--gcc/tree.h1
6 files changed, 74 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5b975fd..0f81767 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2009-03-31 Richard Guenther <rguenther@suse.de>
+
+ * 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 <joseph@codesourcery.com>
PR target/39592
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index a56e885..4951600 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 4dab877..9b1aef3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2009-03-31 Richard Guenther <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/forwprop-12.c: New testcase.
+
2009-03-31 Joseph Myers <joseph@codesourcery.com>
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 0000000..a74809b
--- /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 859d6fe..044f843 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 1a83c25..4e67c6a 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);