tree-ssa-sccvn.c (ao_ref_init_from_vn_reference): Use offset_int for offset and size...
authorEric Botcazou <ebotcazou@adacore.com>
Wed, 16 Sep 2015 10:02:21 +0000 (10:02 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Wed, 16 Sep 2015 10:02:21 +0000 (10:02 +0000)
* tree-ssa-sccvn.c (ao_ref_init_from_vn_reference): Use offset_int for
offset and size computations instead of HOST_WIDE_INT.

From-SVN: r227819

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/opt49.adb [new file with mode: 0644]
gcc/tree-ssa-sccvn.c

index fca25b9b867a330dea7dabe2ad47e292b5cf1efa..085de31e554bb76892cfdb5727ce4e330b919af4 100644 (file)
@@ -1,3 +1,8 @@
+2015-09-16  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * tree-ssa-sccvn.c (ao_ref_init_from_vn_reference): Use offset_int for
+       offset and size computations instead of HOST_WIDE_INT.
+
 2015-09-16  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/67442
index 9035db974d012345014688ca4ea585f41ed362b9..945db718bd04bcbd9fd73329e1927b121a947bed 100644 (file)
@@ -1,3 +1,7 @@
+2015-09-16  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/opt49.adb: New test.
+
 2015-09-16  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/67442
diff --git a/gcc/testsuite/gnat.dg/opt49.adb b/gcc/testsuite/gnat.dg/opt49.adb
new file mode 100644 (file)
index 0000000..4b91973
--- /dev/null
@@ -0,0 +1,31 @@
+-- { dg-do run }
+-- { dg-options "-O -fstack-check" }
+
+procedure Opt49 is
+
+   function Ident (I : Integer) return Integer;
+   pragma No_Inline (Ident);
+
+   function Ident (I : Integer) return Integer is
+   begin
+     return I;
+   end;
+
+   Int_0 : Integer := Ident (0);
+   Int_4 : Integer := Ident (4);
+
+   A : array (-4 .. Int_4) of Integer;
+
+begin
+   A := (-4 , -3 , -2 , -1 , 100 , 1 , 2 , 3 , 4);
+   A (-4 .. Int_0) :=  A (Int_0 .. 4); 
+   if A /= (100 ,  1 ,  2 ,  3 ,  4  , 1 , 2 , 3 , 4) then
+      raise Program_Error;
+   end if;
+
+   A := (-4 , -3 , -2 , -1 , 100 ,  1 ,  2 ,  3 ,  4);
+   A (Int_0 .. 4) := A (-4 .. Int_0); 
+   if A /= (-4 , -3 , -2 , -1 , -4  , -3 , -2 , -1 , 100) then
+      raise Program_Error;
+   end if;
+end;
index d9eb9f361ef83390ffe847c09f59693e11ea1009..f7904e2d3ce832d62799320d257c40e7f6ac9725 100644 (file)
@@ -953,9 +953,9 @@ ao_ref_init_from_vn_reference (ao_ref *ref,
   unsigned i;
   tree base = NULL_TREE;
   tree *op0_p = &base;
-  HOST_WIDE_INT offset = 0;
-  HOST_WIDE_INT max_size;
-  HOST_WIDE_INT size = -1;
+  offset_int offset = 0;
+  offset_int max_size;
+  offset_int size = -1;
   tree size_tree = NULL_TREE;
   alias_set_type base_alias_set = -1;
 
@@ -971,15 +971,11 @@ ao_ref_init_from_vn_reference (ao_ref *ref,
       if (mode == BLKmode)
        size_tree = TYPE_SIZE (type);
       else
-        size = GET_MODE_BITSIZE (mode);
-    }
-  if (size_tree != NULL_TREE)
-    {
-      if (!tree_fits_uhwi_p (size_tree))
-       size = -1;
-      else
-       size = tree_to_uhwi (size_tree);
+       size = int (GET_MODE_BITSIZE (mode));
     }
+  if (size_tree != NULL_TREE
+      && TREE_CODE (size_tree) == INTEGER_CST)
+    size = wi::to_offset (size_tree);
 
   /* Initially, maxsize is the same as the accessed element size.
      In the following it will only grow (or become -1).  */
@@ -1034,7 +1030,7 @@ ao_ref_init_from_vn_reference (ao_ref *ref,
 
        /* And now the usual component-reference style ops.  */
        case BIT_FIELD_REF:
-         offset += tree_to_shwi (op->op1);
+         offset += wi::to_offset (op->op1);
          break;
 
        case COMPONENT_REF:
@@ -1043,15 +1039,16 @@ ao_ref_init_from_vn_reference (ao_ref *ref,
            /* We do not have a complete COMPONENT_REF tree here so we
               cannot use component_ref_field_offset.  Do the interesting
               parts manually.  */
+           tree this_offset = DECL_FIELD_OFFSET (field);
 
-           if (op->op1
-               || !tree_fits_uhwi_p (DECL_FIELD_OFFSET (field)))
+           if (op->op1 || TREE_CODE (this_offset) != INTEGER_CST)
              max_size = -1;
            else
              {
-               offset += (tree_to_uhwi (DECL_FIELD_OFFSET (field))
-                          * BITS_PER_UNIT);
-               offset += TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field));
+               offset_int woffset = wi::lshift (wi::to_offset (this_offset),
+                                                LOG2_BITS_PER_UNIT);
+               woffset += wi::to_offset (DECL_FIELD_BIT_OFFSET (field));
+               offset += woffset;
              }
            break;
          }
@@ -1059,17 +1056,18 @@ ao_ref_init_from_vn_reference (ao_ref *ref,
        case ARRAY_RANGE_REF:
        case ARRAY_REF:
          /* We recorded the lower bound and the element size.  */
-         if (!tree_fits_shwi_p (op->op0)
-             || !tree_fits_shwi_p (op->op1)
-             || !tree_fits_shwi_p (op->op2))
+         if (TREE_CODE (op->op0) != INTEGER_CST
+             || TREE_CODE (op->op1) != INTEGER_CST
+             || TREE_CODE (op->op2) != INTEGER_CST)
            max_size = -1;
          else
            {
-             HOST_WIDE_INT hindex = tree_to_shwi (op->op0);
-             hindex -= tree_to_shwi (op->op1);
-             hindex *= tree_to_shwi (op->op2);
-             hindex *= BITS_PER_UNIT;
-             offset += hindex;
+             offset_int woffset
+               = wi::sext (wi::to_offset (op->op0) - wi::to_offset (op->op1),
+                           TYPE_PRECISION (TREE_TYPE (op->op0)));
+             woffset *= wi::to_offset (op->op2);
+             woffset = wi::lshift (woffset, LOG2_BITS_PER_UNIT);
+             offset += woffset;
            }
          break;
 
@@ -1102,9 +1100,6 @@ ao_ref_init_from_vn_reference (ao_ref *ref,
 
   ref->ref = NULL_TREE;
   ref->base = base;
-  ref->offset = offset;
-  ref->size = size;
-  ref->max_size = max_size;
   ref->ref_alias_set = set;
   if (base_alias_set != -1)
     ref->base_alias_set = base_alias_set;
@@ -1113,6 +1108,30 @@ ao_ref_init_from_vn_reference (ao_ref *ref,
   /* We discount volatiles from value-numbering elsewhere.  */
   ref->volatile_p = false;
 
+  if (!wi::fits_shwi_p (size) || wi::neg_p (size))
+    {
+      ref->offset = 0;
+      ref->size = -1;
+      ref->max_size = -1;
+      return true;
+    }
+
+  ref->size = size.to_shwi ();
+
+  if (!wi::fits_shwi_p (offset))
+    {
+      ref->offset = 0;
+      ref->max_size = -1;
+      return true;
+    }
+
+  ref->offset = offset.to_shwi ();
+
+  if (!wi::fits_shwi_p (max_size) || wi::neg_p (max_size))
+    ref->max_size = -1;
+  else
+    ref->max_size = max_size.to_shwi ();
+
   return true;
 }