OSDN Git Service

* tree-ssa-ccp.c (insert_clobber_before_stack_restore): Recurse on copy
[pf3gnuchains/gcc-fork.git] / gcc / tree-affine.c
index 59ac3d7..69cce2e 100644 (file)
@@ -1,18 +1,18 @@
 /* Operations with affine combinations of trees.
-   Copyright (C) 2005, 2007 Free Software Foundation, Inc.
-   
+   Copyright (C) 2005, 2007, 2008, 2010 Free Software Foundation, Inc.
+
 This file is part of GCC.
-   
+
 GCC is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
 Free Software Foundation; either version 3, or (at your option) any
 later version.
-   
+
 GCC is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
-   
+
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
@@ -20,17 +20,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
 #include "tree.h"
-#include "rtl.h"
-#include "tm_p.h"
-#include "hard-reg-set.h"
 #include "output.h"
-#include "diagnostic.h"
+#include "tree-pretty-print.h"
 #include "tree-dump.h"
 #include "pointer-set.h"
 #include "tree-affine.h"
-#include "tree-gimple.h"
+#include "gimple.h"
 #include "flags.h"
 
 /* Extends CST as appropriate for the affine combinations COMB.  */
@@ -122,7 +118,7 @@ aff_combination_scale (aff_tree *comb, double_int scale)
          comb->n++;
        }
       else
-       comb->rest = fold_build2 (MULT_EXPR, type, comb->rest, 
+       comb->rest = fold_build2 (MULT_EXPR, type, comb->rest,
                                  double_int_to_tree (type, scale));
     }
 }
@@ -182,7 +178,7 @@ aff_combination_add_elt (aff_tree *comb, tree elt, double_int scale)
   else
     elt = fold_build2 (MULT_EXPR, type,
                       fold_convert (type, elt),
-                      double_int_to_tree (type, scale)); 
+                      double_int_to_tree (type, scale));
 
   if (comb->rest)
     comb->rest = fold_build2 (PLUS_EXPR, type, comb->rest,
@@ -313,6 +309,15 @@ tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
       return;
 
     case ADDR_EXPR:
+      /* Handle &MEM[ptr + CST] which is equivalent to POINTER_PLUS_EXPR.  */
+      if (TREE_CODE (TREE_OPERAND (expr, 0)) == MEM_REF)
+       {
+         expr = TREE_OPERAND (expr, 0);
+         tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
+         tree_to_aff_combination (TREE_OPERAND (expr, 1), sizetype, &tmp);
+         aff_combination_add (comb, &tmp);
+         return;
+       }
       core = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, &bitpos,
                                  &toffset, &mode, &unsignedp, &volatilep,
                                  false);
@@ -335,6 +340,25 @@ tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
        }
       return;
 
+    case MEM_REF:
+      if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR)
+       tree_to_aff_combination (TREE_OPERAND (TREE_OPERAND (expr, 0), 0),
+                                type, comb);
+      else if (integer_zerop (TREE_OPERAND (expr, 1)))
+       {
+         aff_combination_elt (comb, type, expr);
+         return;
+       }
+      else
+       aff_combination_elt (comb, type,
+                            build2 (MEM_REF, TREE_TYPE (expr),
+                                    TREE_OPERAND (expr, 0),
+                                    build_int_cst
+                                     (TREE_TYPE (TREE_OPERAND (expr, 1)), 0)));
+      tree_to_aff_combination (TREE_OPERAND (expr, 1), sizetype, &tmp);
+      aff_combination_add (comb, &tmp);
+      return;
+
     default:
       break;
     }
@@ -363,7 +387,7 @@ add_elt_to_tree (tree expr, tree type, tree elt, double_int scale,
        return fold_convert (type, elt);
 
       if (POINTER_TYPE_P (type))
-        return fold_build2 (POINTER_PLUS_EXPR, type, expr, elt);
+        return fold_build_pointer_plus (expr, elt);
       return fold_build2 (PLUS_EXPR, type, expr, elt);
     }
 
@@ -375,7 +399,7 @@ add_elt_to_tree (tree expr, tree type, tree elt, double_int scale,
       if (POINTER_TYPE_P (type))
        {
          elt = fold_build1 (NEGATE_EXPR, type1, elt);
-         return fold_build2 (POINTER_PLUS_EXPR, type, expr, elt);
+         return fold_build_pointer_plus (expr, elt);
        }
       return fold_build2 (MINUS_EXPR, type, expr, elt);
     }
@@ -399,7 +423,7 @@ add_elt_to_tree (tree expr, tree type, tree elt, double_int scale,
     {
       if (code == MINUS_EXPR)
         elt = fold_build1 (NEGATE_EXPR, type1, elt);
-      return fold_build2 (POINTER_PLUS_EXPR, type, expr, elt);
+      return fold_build_pointer_plus (expr, elt);
     }
   return fold_build2 (code, type, expr, elt);
 }
@@ -410,7 +434,7 @@ tree
 aff_combination_to_tree (aff_tree *comb)
 {
   tree type = comb->type;
-  tree expr = comb->rest;
+  tree expr = NULL_TREE;
   unsigned i;
   double_int off, sgn;
   tree type1 = type;
@@ -423,6 +447,9 @@ aff_combination_to_tree (aff_tree *comb)
     expr = add_elt_to_tree (expr, type, comb->elts[i].val, comb->elts[i].coef,
                            comb);
 
+  if (comb->rest)
+    expr = add_elt_to_tree (expr, type, comb->rest, double_int_one, comb);
+
   /* Ensure that we get x - 1, not x + (-1) or x + 0xff..f if x is
      unsigned.  */
   if (double_int_negative_p (comb->offset))
@@ -471,7 +498,7 @@ aff_combination_remove_elt (aff_tree *comb, unsigned m)
 
 /* Adds C * COEF * VAL to R.  VAL may be NULL, in that case only
    C * COEF is added to R.  */
-   
+
 
 static void
 aff_combination_add_product (aff_tree *c, double_int coef, tree val,
@@ -534,7 +561,7 @@ aff_combination_mult (aff_tree *c1, aff_tree *c2, aff_tree *r)
 /* Returns the element of COMB whose value is VAL, or NULL if no such
    element exists.  If IDX is not NULL, it is set to the index of VAL in
    COMB.  */
-             
+
 static struct aff_comb_elt *
 aff_combination_find_elt (aff_tree *comb, tree val, unsigned *idx)
 {
@@ -567,11 +594,13 @@ struct name_expansion
    results.  */
 
 void
-aff_combination_expand (aff_tree *comb, struct pointer_map_t **cache)
+aff_combination_expand (aff_tree *comb ATTRIBUTE_UNUSED,
+                       struct pointer_map_t **cache ATTRIBUTE_UNUSED)
 {
   unsigned i;
   aff_tree to_add, current, curre;
-  tree e, def, rhs;
+  tree e, rhs;
+  gimple def;
   double_int scale;
   void **slot;
   struct name_expansion *exp;
@@ -580,6 +609,8 @@ aff_combination_expand (aff_tree *comb, struct pointer_map_t **cache)
   for (i = 0; i < comb->n; i++)
     {
       tree type, name;
+      enum tree_code code;
+
       e = comb->elts[i].val;
       type = TREE_TYPE (e);
       name = e;
@@ -591,19 +622,19 @@ aff_combination_expand (aff_tree *comb, struct pointer_map_t **cache)
       if (TREE_CODE (name) != SSA_NAME)
        continue;
       def = SSA_NAME_DEF_STMT (name);
-      if (TREE_CODE (def) != GIMPLE_MODIFY_STMT
-         || GIMPLE_STMT_OPERAND (def, 0) != name)
+      if (!is_gimple_assign (def) || gimple_assign_lhs (def) != name)
        continue;
 
-      rhs = GIMPLE_STMT_OPERAND (def, 1);
-      if (TREE_CODE (rhs) != SSA_NAME
-         && !EXPR_P (rhs)
-         && !is_gimple_min_invariant (rhs))
+      code = gimple_assign_rhs_code (def);
+      if (code != SSA_NAME
+         && !IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
+         && (get_gimple_rhs_class (code) != GIMPLE_SINGLE_RHS
+             || !is_gimple_min_invariant (gimple_assign_rhs1 (def))))
        continue;
 
       /* We do not know whether the reference retains its value at the
         place where the expansion is used.  */
-      if (REFERENCE_CLASS_P (rhs))
+      if (TREE_CODE_CLASS (code) == tcc_reference)
        continue;
 
       if (!*cache)
@@ -616,29 +647,27 @@ aff_combination_expand (aff_tree *comb, struct pointer_map_t **cache)
          exp = XNEW (struct name_expansion);
          exp->in_progress = 1;
          *slot = exp;
-         if (e != name)
+         /* In principle this is a generally valid folding, but
+            it is not unconditionally an optimization, so do it
+            here and not in fold_unary.  */
+         /* Convert (T1)(X *+- CST) into (T1)X *+- (T1)CST if T1 is wider
+            than the type of X and overflow for the type of X is
+            undefined.  */
+         if (e != name
+             && INTEGRAL_TYPE_P (type)
+             && INTEGRAL_TYPE_P (TREE_TYPE (name))
+             && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (name))
+             && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (name))
+             && (code == PLUS_EXPR || code == MINUS_EXPR || code == MULT_EXPR)
+             && TREE_CODE (gimple_assign_rhs2 (def)) == INTEGER_CST)
+           rhs = fold_build2 (code, type,
+                              fold_convert (type, gimple_assign_rhs1 (def)),
+                              fold_convert (type, gimple_assign_rhs2 (def)));
+         else
            {
-             /* In principle this is a generally valid folding, but
-                it is not unconditionally an optimization, so do it
-                here and not in fold_unary.  */
-             /* Convert (T1)(X *+- CST) into (T1)X *+- (T1)CST if T1 is wider
-                than the type of X and overflow for the type of X is
-                undefined.  */
-             if (INTEGRAL_TYPE_P (type)
-                 && INTEGRAL_TYPE_P (TREE_TYPE (rhs))
-                 && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (rhs))
-                 && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (rhs))
-                 && (TREE_CODE (rhs) == PLUS_EXPR
-                     || TREE_CODE (rhs) == MINUS_EXPR
-                     || TREE_CODE (rhs) == MULT_EXPR)
-                 && TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST)
-               {
-                 rhs = fold_build2 (TREE_CODE (rhs), type,
-                                    fold_convert (type, TREE_OPERAND (rhs, 0)),
-                                    fold_convert (type, TREE_OPERAND (rhs, 1)));
-               }
-             else
-               rhs = fold_convert (type, rhs);
+             rhs = gimple_assign_rhs_to_tree (def);
+             if (e != name)
+               rhs = fold_convert (type, rhs);
            }
          tree_to_aff_combination_expand (rhs, comb->type, &current, cache);
          exp->expansion = current;
@@ -801,7 +830,7 @@ print_aff (FILE *file, aff_tree *val)
        {
          fprintf (file, "    [%d] = ", i);
          print_generic_expr (file, val->elts[i].val, TDF_VOPS|TDF_MEMSYMS);
-         
+
          fprintf (file, " * ");
          dump_double_int (file, val->elts[i].coef, uns);
          if (i != val->n - 1)
@@ -819,7 +848,7 @@ print_aff (FILE *file, aff_tree *val)
 
 /* Prints the affine VAL to the standard error, used for debugging.  */
 
-void
+DEBUG_FUNCTION void
 debug_aff (aff_tree *val)
 {
   print_aff (stderr, val);
@@ -858,3 +887,30 @@ get_inner_reference_aff (tree ref, aff_tree *addr, double_int *size)
   *size = shwi_to_double_int ((bitsize + BITS_PER_UNIT - 1) / BITS_PER_UNIT);
 }
 
+/* Returns true if a region of size SIZE1 at position 0 and a region of
+   size SIZE2 at position DIFF cannot overlap.  */
+
+bool
+aff_comb_cannot_overlap_p (aff_tree *diff, double_int size1, double_int size2)
+{
+  double_int d, bound;
+
+  /* Unless the difference is a constant, we fail.  */
+  if (diff->n != 0)
+    return false;
+
+  d = diff->offset;
+  if (double_int_negative_p (d))
+    {
+      /* The second object is before the first one, we succeed if the last
+        element of the second object is before the start of the first one.  */
+      bound = double_int_add (d, double_int_add (size2, double_int_minus_one));
+      return double_int_negative_p (bound);
+    }
+  else
+    {
+      /* We succeed if the second object starts after the first one ends.  */
+      return double_int_scmp (size1, d) <= 0;
+    }
+}
+