OSDN Git Service

2009-03-31 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 31 Mar 2009 13:16:36 +0000 (13:16 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 31 Mar 2009 13:16:36 +0000 (13:16 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@145343 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/forwprop-12.c [new file with mode: 0644]
gcc/tree-ssa-forwprop.c
gcc/tree.h

index 5b975fd..0f81767 100644 (file)
@@ -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
index a56e885..4951600 100644 (file)
@@ -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;
index 4dab877..9b1aef3 100644 (file)
@@ -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 (file)
index 0000000..a74809b
--- /dev/null
@@ -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" } } */
index 859d6fe..044f843 100644 (file)
@@ -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)
index 1a83c25..4e67c6a 100644 (file)
@@ -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);