2005-05-11 Richard Guenther <rguenth@gcc.gnu.org>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 11 May 2005 08:14:44 +0000 (08:14 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 11 May 2005 08:14:44 +0000 (08:14 +0000)
PR middle-end/19807
PR tree-optimization/19639
* fold-const.c (try_move_mult_to_index): Handle INTEGER_CST
and generic summands for char* as s * delta, too, folding &a[i]
CODE x to &a[i CODE x/s].  Use tree_int_cst_equal
for comparison of steps.  Convert types for index addition.
(fold_binary): Adjust the callers to always dispatch to
try_move_mult_to_index.
* tree-ssa-propagate.c (set_rhs): Avoid setting rhs to
expr with non-gimple ARRAY_REF offset.

* g++.dg/tree-ssa/pr19807.C: New testcase.

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

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/tree-ssa/pr19807.C [new file with mode: 0644]
gcc/tree-ssa-propagate.c

index 1621f15..d6dd1b7 100644 (file)
@@ -1,5 +1,18 @@
 2005-05-11  Richard Guenther  <rguenth@gcc.gnu.org>
 
+       PR middle-end/19807
+       PR tree-optimization/19639
+       * fold-const.c (try_move_mult_to_index): Handle INTEGER_CST
+       and generic summands for char* as s * delta, too, folding &a[i]
+       CODE x to &a[i CODE x/s].  Use tree_int_cst_equal
+       for comparison of steps.  Convert types for index addition.
+       (fold_binary): Adjust the callers to always dispatch to
+       try_move_mult_to_index.
+       * tree-ssa-propagate.c (set_rhs): Avoid setting rhs to
+       expr with non-gimple ARRAY_REF offset.
+
+2005-05-11  Richard Guenther  <rguenth@gcc.gnu.org>
+
        * fold-const.c (fold_indirect_ref_1): Avoid removing
        NOP_EXPRs with type qualifiers like const.
 
index dc8d417..21250f6 100644 (file)
@@ -6259,55 +6259,81 @@ fold_sign_changed_comparison (enum tree_code code, tree type,
 }
 
 /* Tries to replace &a[idx] CODE s * delta with &a[idx CODE delta], if s is
-   step of the array.  ADDR is the address. MULT is the multiplicative expression.
+   step of the array.  Reconstructs s and delta in the case of s * delta
+   being an integer constant (and thus already folded).
+   ADDR is the address. MULT is the multiplicative expression.
    If the function succeeds, the new address expression is returned.  Otherwise
    NULL_TREE is returned.  */
 
 static tree
-try_move_mult_to_index (enum tree_code code, tree addr, tree mult)
+try_move_mult_to_index (enum tree_code code, tree addr, tree op1)
 {
   tree s, delta, step;
-  tree arg0 = TREE_OPERAND (mult, 0), arg1 = TREE_OPERAND (mult, 1);
   tree ref = TREE_OPERAND (addr, 0), pref;
   tree ret, pos;
   tree itype;
 
-  STRIP_NOPS (arg0);
-  STRIP_NOPS (arg1);
-  
-  if (TREE_CODE (arg0) == INTEGER_CST)
+  /* Canonicalize op1 into a possibly non-constant delta
+     and an INTEGER_CST s.  */
+  if (TREE_CODE (op1) == MULT_EXPR)
     {
-      s = arg0;
-      delta = arg1;
+      tree arg0 = TREE_OPERAND (op1, 0), arg1 = TREE_OPERAND (op1, 1);
+
+      STRIP_NOPS (arg0);
+      STRIP_NOPS (arg1);
+  
+      if (TREE_CODE (arg0) == INTEGER_CST)
+        {
+          s = arg0;
+          delta = arg1;
+        }
+      else if (TREE_CODE (arg1) == INTEGER_CST)
+        {
+          s = arg1;
+          delta = arg0;
+        }
+      else
+        return NULL_TREE;
     }
-  else if (TREE_CODE (arg1) == INTEGER_CST)
+  else if (TREE_CODE (op1) == INTEGER_CST)
     {
-      s = arg1;
-      delta = arg0;
+      delta = op1;
+      s = NULL_TREE;
     }
   else
-    return NULL_TREE;
+    {
+      /* Simulate we are delta * 1.  */
+      delta = op1;
+      s = integer_one_node;
+    }
 
   for (;; ref = TREE_OPERAND (ref, 0))
     {
       if (TREE_CODE (ref) == ARRAY_REF)
        {
          step = array_ref_element_size (ref);
-
          if (TREE_CODE (step) != INTEGER_CST)
            continue;
 
-         itype = TREE_TYPE (step);
+         if (s)
+           {
+             if (! tree_int_cst_equal (step, s))
+                continue;
+           }
+         else
+           {
+             /* Try if delta is a multiple of step.  */
+             tree mod = int_const_binop (TRUNC_MOD_EXPR, delta, step, 0);
+             if (!integer_zerop (mod))
+               continue;
 
-         /* If the type sizes do not match, we might run into problems
-            when one of them would overflow.  */
-         if (TYPE_PRECISION (itype) != TYPE_PRECISION (TREE_TYPE (s)))
-           continue;
+             delta = int_const_binop (EXACT_DIV_EXPR, delta, step, 0);
+           }
 
-         if (!operand_equal_p (step, fold_convert (itype, s), 0))
+         itype = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0)));
+         if (! itype)
            continue;
 
-         delta = fold_convert (itype, delta);
          break;
        }
 
@@ -6330,8 +6356,9 @@ try_move_mult_to_index (enum tree_code code, tree addr, tree mult)
     }
 
   TREE_OPERAND (pos, 1) = fold_build2 (code, itype,
-                                      TREE_OPERAND (pos, 1),
-                                      delta);
+                                      fold_convert (itype,
+                                                    TREE_OPERAND (pos, 1)),
+                                      fold_convert (itype, delta));
 
   return build1 (ADDR_EXPR, TREE_TYPE (addr), ret);
 }
@@ -7441,15 +7468,13 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          /* Try replacing &a[i1] + c * i2 with &a[i1 + i2], if c is step
             of the array.  Loop optimizer sometimes produce this type of
             expressions.  */
-         if (TREE_CODE (arg0) == ADDR_EXPR
-             && TREE_CODE (arg1) == MULT_EXPR)
+         if (TREE_CODE (arg0) == ADDR_EXPR)
            {
              tem = try_move_mult_to_index (PLUS_EXPR, arg0, arg1);
              if (tem)
                return fold_convert (type, fold (tem));
            }
-         else if (TREE_CODE (arg1) == ADDR_EXPR
-                  && TREE_CODE (arg0) == MULT_EXPR)
+         else if (TREE_CODE (arg1) == ADDR_EXPR)
            {
              tem = try_move_mult_to_index (PLUS_EXPR, arg1, arg0);
              if (tem)
@@ -7867,8 +7892,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       /* Try replacing &a[i1] - c * i2 with &a[i1 - i2], if c is step
         of the array.  Loop optimizer sometimes produce this type of
         expressions.  */
-      if (TREE_CODE (arg0) == ADDR_EXPR
-         && TREE_CODE (arg1) == MULT_EXPR)
+      if (TREE_CODE (arg0) == ADDR_EXPR)
        {
          tem = try_move_mult_to_index (MINUS_EXPR, arg0, arg1);
          if (tem)
index d92bf93..030b2fe 100644 (file)
@@ -1,3 +1,9 @@
+2005-05-11  Richard Guenther  <rguenth@gcc.gnu.org>
+
+       PR middle-end/19807
+       PR tree-optimization/19639
+       * g++.dg/tree-ssa/pr19807.C: New testcase.
+
 2005-05-10  Francois-Xavier Coudert  <coudert@clipper.ens.fr>
 
        PR libfortran/21471
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr19807.C b/gcc/testsuite/g++.dg/tree-ssa/pr19807.C
new file mode 100644 (file)
index 0000000..0ff10db
--- /dev/null
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+
+int a[4];
+int *x, *y, *z;
+
+void foo(void)
+{
+       x = &a[3] - 1;
+       y = &a[1] + 1;
+       z = 1 + &a[1];
+}
+
+void bar(int i)
+{
+       x = &a[i] - 1;
+       y = &a[i] + 1;
+       z = 1 + &a[i];
+}
+
+/* { dg-final { scan-tree-dump-times "&a\\\[2\\\]" 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "&a\\\[.* - 1\\\]" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "&a\\\[.* \\+ 1\\\]" 1 "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
index 9f9fef1..c83d2cd 100644 (file)
@@ -576,6 +576,12 @@ set_rhs (tree *stmt_p, tree expr)
       if (!is_gimple_val (TREE_OPERAND (expr, 0)))
        return false;
     }
+  else if (code == ADDR_EXPR)
+    {
+      if (TREE_CODE (TREE_OPERAND (expr, 0)) == ARRAY_REF
+         && !is_gimple_val (TREE_OPERAND (TREE_OPERAND (expr, 0), 1)))
+       return false;
+    }
   else if (code == COMPOUND_EXPR)
     return false;