re PR tree-optimization/91169 (cd2a31a FAILs)
authorRichard Biener <rguenther@suse.de>
Mon, 5 Aug 2019 12:30:49 +0000 (12:30 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 5 Aug 2019 12:30:49 +0000 (12:30 +0000)
2019-08-05  Richard Biener  <rguenther@suse.de>

PR middle-end/91169
* fold-const.c (get_array_ctor_element_at_index): Create
offset_ints according to the sign of the index type and treat
that as signed if it is obviously so.

* gnat.dg/array37.adb: New testcase.

From-SVN: r274114

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/array37.adb [new file with mode: 0644]

index 121da52..c118e4d 100644 (file)
@@ -1,3 +1,10 @@
+2019-08-05  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/91169
+       * fold-const.c (get_array_ctor_element_at_index): Create
+       offset_ints according to the sign of the index type and treat
+       that as signed if it is obviously so.
+
 2019-08-05  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/91341
index 0a24101..716d739 100644 (file)
@@ -11850,6 +11850,7 @@ get_array_ctor_element_at_index (tree ctor, offset_int access_index,
                                 unsigned *ctor_idx)
 {
   tree index_type = NULL_TREE;
+  signop index_sgn = UNSIGNED;
   offset_int low_bound = 0;
 
   if (TREE_CODE (TREE_TYPE (ctor)) == ARRAY_TYPE)
@@ -11860,22 +11861,37 @@ get_array_ctor_element_at_index (tree ctor, offset_int access_index,
          /* Static constructors for variably sized objects makes no sense.  */
          gcc_assert (TREE_CODE (TYPE_MIN_VALUE (domain_type)) == INTEGER_CST);
          index_type = TREE_TYPE (TYPE_MIN_VALUE (domain_type));
-         low_bound = wi::to_offset (TYPE_MIN_VALUE (domain_type));
+         /* ???  When it is obvious that the range is signed, treat it so.  */
+         if (TYPE_UNSIGNED (index_type)
+             && TYPE_MAX_VALUE (domain_type)
+             && tree_int_cst_lt (TYPE_MAX_VALUE (domain_type),
+                                 TYPE_MIN_VALUE (domain_type)))
+           {
+             index_sgn = SIGNED;
+             low_bound
+               = offset_int::from (wi::to_wide (TYPE_MIN_VALUE (domain_type)),
+                                   SIGNED);
+           }
+         else
+           {
+             index_sgn = TYPE_SIGN (index_type);
+             low_bound = wi::to_offset (TYPE_MIN_VALUE (domain_type));
+           }
        }
     }
 
   if (index_type)
     access_index = wi::ext (access_index, TYPE_PRECISION (index_type),
-                           TYPE_SIGN (index_type));
+                           index_sgn);
 
-  offset_int index = low_bound - 1;
+  offset_int index = low_bound;
   if (index_type)
-    index = wi::ext (index, TYPE_PRECISION (index_type),
-                    TYPE_SIGN (index_type));
+    index = wi::ext (index, TYPE_PRECISION (index_type), index_sgn);
 
-  offset_int max_index;
+  offset_int max_index = index;
   unsigned cnt;
   tree cfield, cval;
+  bool first_p = true;
 
   FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
     {
@@ -11885,27 +11901,34 @@ get_array_ctor_element_at_index (tree ctor, offset_int access_index,
       if (cfield)
        {
          if (TREE_CODE (cfield) == INTEGER_CST)
-           max_index = index = wi::to_offset (cfield);
+           max_index = index
+             = offset_int::from (wi::to_wide (cfield), index_sgn);
          else
            {
              gcc_assert (TREE_CODE (cfield) == RANGE_EXPR);
-             index = wi::to_offset (TREE_OPERAND (cfield, 0));
-             max_index = wi::to_offset (TREE_OPERAND (cfield, 1));
+             index = offset_int::from (wi::to_wide (TREE_OPERAND (cfield, 0)),
+                                       index_sgn);
+             max_index
+               = offset_int::from (wi::to_wide (TREE_OPERAND (cfield, 1)),
+                                   index_sgn);
+             gcc_checking_assert (wi::le_p (index, max_index, index_sgn));
            }
        }
-      else
+      else if (!first_p)
        {
-         index += 1;
+         index = max_index + 1;
          if (index_type)
-           index = wi::ext (index, TYPE_PRECISION (index_type),
-                            TYPE_SIGN (index_type));
+           index = wi::ext (index, TYPE_PRECISION (index_type), index_sgn);
+         gcc_checking_assert (wi::gt_p (index, max_index, index_sgn));
          max_index = index;
        }
+      else
+       first_p = false;
 
       /* Do we have match?  */
-      if (wi::cmpu (access_index, index) >= 0)
+      if (wi::cmp (access_index, index, index_sgn) >= 0)
        {
-         if (wi::cmpu (access_index, max_index) <= 0)
+         if (wi::cmp (access_index, max_index, index_sgn) <= 0)
            {
              if (ctor_idx)
                *ctor_idx = cnt;
index e19f136..5dc9d11 100644 (file)
@@ -1,3 +1,8 @@
+2019-08-05  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/91169
+       * gnat.dg/array37.adb: New testcase.
+
 2019-08-05  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/91341
diff --git a/gcc/testsuite/gnat.dg/array37.adb b/gcc/testsuite/gnat.dg/array37.adb
new file mode 100644 (file)
index 0000000..f1ee385
--- /dev/null
@@ -0,0 +1,19 @@
+-- { dg-do run }
+-- { dg-options "-O" }
+
+procedure Array37 is
+
+  type Arr is array (Integer range -1 .. 1) of Integer;
+
+  A : Arr := (-100, 0, 100);
+
+  function Ident (I : Integer) return Integer IS
+  begin
+    return I;
+  end;
+
+begin
+  if Ident (A (1)) <= Ident (A (0)) then
+    raise Program_Error;
+  end if;
+end;