re PR c++/83659 (ICE on compilable C++ code: in tree_to_shwi, at tree.c:6821)
authorMarek Polacek <polacek@redhat.com>
Fri, 9 Feb 2018 05:46:18 +0000 (05:46 +0000)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 9 Feb 2018 05:46:18 +0000 (06:46 +0100)
PR c++/83659
* fold-const.c (fold_indirect_ref_1): Use VECTOR_TYPE_P macro.
Formatting fixes.  Verify first that tree_fits_poly_int64_p (op01).
Sync some changes from cxx_fold_indirect_ref.

* constexpr.c (cxx_fold_indirect_ref): Sync some changes from
fold_indirect_ref_1, including poly_*int64.  Verify first that
tree_fits_poly_int64_p (op01).  Formatting fixes.

* g++.dg/torture/pr83659.C: New test.

Co-Authored-By: Jakub Jelinek <jakub@redhat.com>
From-SVN: r257512

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr83659.C [new file with mode: 0644]

index b5e19ed8f5bbf1d4ad86a723e5ba95c3cae186c9..d9c544387fc4d0b3ea30f2f2f6359a7e1bf3c2f5 100644 (file)
@@ -1,3 +1,11 @@
+2018-02-09  Marek Polacek  <polacek@redhat.com>
+           Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/83659
+       * fold-const.c (fold_indirect_ref_1): Use VECTOR_TYPE_P macro.
+       Formatting fixes.  Verify first that tree_fits_poly_int64_p (op01).
+       Sync some changes from cxx_fold_indirect_ref.
+
 2018-02-09  Alexandre Oliva <aoliva@redhat.com>
 
        * cfgexpand.c (expand_gimple_basic_block): Handle inline entry
index be4db4b789adec026629141c0d136c4968c5a7de..ac53a74d35f9fd4e3651bf59fcc0f93ceb624e7c 100644 (file)
@@ -1,3 +1,11 @@
+2018-02-09  Marek Polacek  <polacek@redhat.com>
+           Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/83659
+       * constexpr.c (cxx_fold_indirect_ref): Sync some changes from
+       fold_indirect_ref_1, including poly_*int64.  Verify first that
+       tree_fits_poly_int64_p (op01).  Formatting fixes.
+
 2018-02-08  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * constexpr.c (cxx_eval_component_reference): Use INDIRECT_REF_P.
index 39a2e1ab578ceff57db50ac04390bf77e757ca2a..729244127067186b93fddab856c0b0731d2263b3 100644 (file)
@@ -3025,9 +3025,10 @@ cxx_eval_vec_init (const constexpr_ctx *ctx, tree t,
 static tree
 cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
 {
-  tree sub, subtype;
+  tree sub = op0;
+  tree subtype;
+  poly_uint64 const_op01;
 
-  sub = op0;
   STRIP_NOPS (sub);
   subtype = TREE_TYPE (sub);
   if (!POINTER_TYPE_P (subtype))
@@ -3082,7 +3083,8 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
        {
          tree part_width = TYPE_SIZE (type);
          tree index = bitsize_int (0);
-         return fold_build3_loc (loc, BIT_FIELD_REF, type, op, part_width, index);
+         return fold_build3_loc (loc, BIT_FIELD_REF, type, op, part_width,
+                                 index);
        }
       /* Also handle conversion to an empty base class, which
         is represented with a NOP_EXPR.  */
@@ -3107,7 +3109,7 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
        }
     }
   else if (TREE_CODE (sub) == POINTER_PLUS_EXPR
-          && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
+          && poly_int_tree_p (TREE_OPERAND (sub, 1), &const_op01))
     {
       tree op00 = TREE_OPERAND (sub, 0);
       tree op01 = TREE_OPERAND (sub, 1);
@@ -3121,29 +3123,37 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
 
          /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
          if (VECTOR_TYPE_P (op00type)
-             && (same_type_ignoring_top_level_qualifiers_p
-                 (type, TREE_TYPE (op00type))))
+             && same_type_ignoring_top_level_qualifiers_p
+                                               (type, TREE_TYPE (op00type))
+             /* POINTER_PLUS_EXPR second operand is sizetype, unsigned,
+                but we want to treat offsets with MSB set as negative.
+                For the code below negative offsets are invalid and
+                TYPE_SIZE of the element is something unsigned, so
+                check whether op01 fits into poly_int64, which implies
+                it is from 0 to INTTYPE_MAXIMUM (HOST_WIDE_INT), and
+                then just use poly_uint64 because we want to treat the
+                value as unsigned.  */
+             && tree_fits_poly_int64_p (op01))
            {
-             HOST_WIDE_INT offset = tree_to_shwi (op01);
              tree part_width = TYPE_SIZE (type);
-             unsigned HOST_WIDE_INT part_widthi = tree_to_shwi (part_width)/BITS_PER_UNIT;
-             unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
-             tree index = bitsize_int (indexi);
-
-             if (known_lt (offset / part_widthi,
-                           TYPE_VECTOR_SUBPARTS (op00type)))
-               return fold_build3_loc (loc,
-                                       BIT_FIELD_REF, type, op00,
-                                       part_width, index);
-
+             poly_uint64 max_offset
+               = (tree_to_uhwi (part_width) / BITS_PER_UNIT
+                  * TYPE_VECTOR_SUBPARTS (op00type));
+             if (known_lt (const_op01, max_offset))
+               {
+                 tree index = bitsize_int (const_op01 * BITS_PER_UNIT);
+                 return fold_build3_loc (loc,
+                                         BIT_FIELD_REF, type, op00,
+                                         part_width, index);
+               }
            }
          /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
          else if (TREE_CODE (op00type) == COMPLEX_TYPE
                   && (same_type_ignoring_top_level_qualifiers_p
                       (type, TREE_TYPE (op00type))))
            {
-             tree size = TYPE_SIZE_UNIT (type);
-             if (tree_int_cst_equal (size, op01))
+             if (known_eq (wi::to_poly_offset (TYPE_SIZE_UNIT (type)),
+                           const_op01))
                return fold_build1_loc (loc, IMAGPART_EXPR, type, op00);
            }
          /* ((foo *)&fooarray)[1] => fooarray[1] */
@@ -3198,7 +3208,8 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
     {
       tree type_domain;
       tree min_val = size_zero_node;
-      tree newsub = cxx_fold_indirect_ref (loc, TREE_TYPE (subtype), sub, NULL);
+      tree newsub
+       = cxx_fold_indirect_ref (loc, TREE_TYPE (subtype), sub, NULL);
       if (newsub)
        sub = newsub;
       else
index c86c3f9b44d5f58c181acdd3c04976e8301c2a05..87d00a57476beaa905acf36523b764a960a69201 100644 (file)
@@ -14115,6 +14115,7 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0)
     {
       tree op = TREE_OPERAND (sub, 0);
       tree optype = TREE_TYPE (op);
+
       /* *&CONST_DECL -> to the value of the const decl.  */
       if (TREE_CODE (op) == CONST_DECL)
        return DECL_INITIAL (op);
@@ -14148,12 +14149,13 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0)
               && type == TREE_TYPE (optype))
        return fold_build1_loc (loc, REALPART_EXPR, type, op);
       /* *(foo *)&vectorfoo => BIT_FIELD_REF<vectorfoo,...> */
-      else if (TREE_CODE (optype) == VECTOR_TYPE
+      else if (VECTOR_TYPE_P (optype)
               && type == TREE_TYPE (optype))
        {
          tree part_width = TYPE_SIZE (type);
          tree index = bitsize_int (0);
-         return fold_build3_loc (loc, BIT_FIELD_REF, type, op, part_width, index);
+         return fold_build3_loc (loc, BIT_FIELD_REF, type, op, part_width,
+                                 index);
        }
     }
 
@@ -14171,8 +14173,17 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0)
          op00type = TREE_TYPE (op00);
 
          /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
-         if (TREE_CODE (op00type) == VECTOR_TYPE
-             && type == TREE_TYPE (op00type))
+         if (VECTOR_TYPE_P (op00type)
+             && type == TREE_TYPE (op00type)
+             /* POINTER_PLUS_EXPR second operand is sizetype, unsigned,
+                but we want to treat offsets with MSB set as negative.
+                For the code below negative offsets are invalid and
+                TYPE_SIZE of the element is something unsigned, so
+                check whether op01 fits into poly_int64, which implies
+                it is from 0 to INTTYPE_MAXIMUM (HOST_WIDE_INT), and
+                then just use poly_uint64 because we want to treat the
+                value as unsigned.  */
+             && tree_fits_poly_int64_p (op01))
            {
              tree part_width = TYPE_SIZE (type);
              poly_uint64 max_offset
@@ -14199,16 +14210,16 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0)
                   && type == TREE_TYPE (op00type))
            {
              tree type_domain = TYPE_DOMAIN (op00type);
-             tree min = size_zero_node;
+             tree min_val = size_zero_node;
              if (type_domain && TYPE_MIN_VALUE (type_domain))
-               min = TYPE_MIN_VALUE (type_domain);
+               min_val = TYPE_MIN_VALUE (type_domain);
              offset_int off = wi::to_offset (op01);
              offset_int el_sz = wi::to_offset (TYPE_SIZE_UNIT (type));
              offset_int remainder;
              off = wi::divmod_trunc (off, el_sz, SIGNED, &remainder);
-             if (remainder == 0 && TREE_CODE (min) == INTEGER_CST)
+             if (remainder == 0 && TREE_CODE (min_val) == INTEGER_CST)
                {
-                 off = off + wi::to_offset (min);
+                 off = off + wi::to_offset (min_val);
                  op01 = wide_int_to_tree (sizetype, off);
                  return build4_loc (loc, ARRAY_REF, type, op00, op01,
                                     NULL_TREE, NULL_TREE);
index dfa8cb87d930d0e9e16a6e0c01b3e6f55bc50569..49a2275c73293d95e786859795979018d087cdf7 100644 (file)
@@ -1,3 +1,9 @@
+2018-02-09  Marek Polacek  <polacek@redhat.com>
+           Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/83659
+       * g++.dg/torture/pr83659.C: New test.
+
 2018-02-08  David Malcolm  <dmalcolm@redhat.com>
 
        PR tree-optimization/84136
diff --git a/gcc/testsuite/g++.dg/torture/pr83659.C b/gcc/testsuite/g++.dg/torture/pr83659.C
new file mode 100644 (file)
index 0000000..bdcdca2
--- /dev/null
@@ -0,0 +1,18 @@
+// PR c++/83659
+// { dg-do compile }
+
+typedef int V __attribute__ ((__vector_size__ (16)));
+V a;
+V b[2];
+
+int
+foo ()
+{
+  return reinterpret_cast <int *> (&a)[-1] += 1;
+}
+
+int
+bar ()
+{
+  return reinterpret_cast <int *> (&a[1])[-1];
+}