]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/69553 (Optimizations O1/O2 makes std::array value incorrect when...
authorRichard Biener <rguenther@suse.de>
Thu, 18 Feb 2016 14:34:59 +0000 (14:34 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 18 Feb 2016 14:34:59 +0000 (14:34 +0000)
2016-02-18  Richard Biener  <rguenther@suse.de>

PR middle-end/69553
* fold-const.c (operand_equal_p): Properly compare offsets for
IMAGPART_EXPR and ARRAY_REF.

* g++.dg/torture/pr69553.C: New testcase.

From-SVN: r233520

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

index c3118b95207793d0dc069f328cfb7201289a581c..b5bbb901c3f2c06801fd3579316d6aac841a90b7 100644 (file)
@@ -1,3 +1,9 @@
+2016-02-18  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/69553
+       * fold-const.c (operand_equal_p): Properly compare offsets for
+       IMAGPART_EXPR and ARRAY_REF.
+
 2016-02-18  Nick Clifton  <nickc@redhat.com>
 
         PR target/62254
index 4992f4bdfb88126bc7e9ce8a65bb783fb9a45f20..41c652e43ee5ed828c603598c0e21c97415cafe7 100644 (file)
@@ -3008,8 +3008,15 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
          flags &= ~OEP_ADDRESS_OF;
          return OP_SAME (0);
 
-       case REALPART_EXPR:
        case IMAGPART_EXPR:
+         /* Require the same offset.  */
+         if (!operand_equal_p (TYPE_SIZE (TREE_TYPE (arg0)),
+                               TYPE_SIZE (TREE_TYPE (arg1)),
+                               flags & ~OEP_ADDRESS_OF))
+           return 0;
+
+       /* Fallthru.  */
+       case REALPART_EXPR:
        case VIEW_CONVERT_EXPR:
          return OP_SAME (0);
 
@@ -3049,17 +3056,29 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
 
        case ARRAY_REF:
        case ARRAY_RANGE_REF:
-         /* Operands 2 and 3 may be null.
-            Compare the array index by value if it is constant first as we
-            may have different types but same value here.  */
          if (!OP_SAME (0))
            return 0;
          flags &= ~OEP_ADDRESS_OF;
+         /* Compare the array index by value if it is constant first as we
+            may have different types but same value here.  */
          return ((tree_int_cst_equal (TREE_OPERAND (arg0, 1),
                                       TREE_OPERAND (arg1, 1))
                   || OP_SAME (1))
                  && OP_SAME_WITH_NULL (2)
-                 && OP_SAME_WITH_NULL (3));
+                 && OP_SAME_WITH_NULL (3)
+                 /* Compare low bound and element size as with OEP_ADDRESS_OF
+                    we have to account for the offset of the ref.  */
+                 && (TREE_TYPE (TREE_OPERAND (arg0, 0))
+                     == TREE_TYPE (TREE_OPERAND (arg1, 0))
+                     || (operand_equal_p (array_ref_low_bound
+                                            (CONST_CAST_TREE (arg0)),
+                                          array_ref_low_bound
+                                            (CONST_CAST_TREE (arg1)), flags)
+                         && operand_equal_p (array_ref_element_size
+                                               (CONST_CAST_TREE (arg0)),
+                                             array_ref_element_size
+                                               (CONST_CAST_TREE (arg1)),
+                                             flags))));
 
        case COMPONENT_REF:
          /* Handle operand 2 the same as for ARRAY_REF.  Operand 0
index a3aff74c66aeb13abbcd87289dfa63f713fc8a42..90ed5deecf89e266d0aeb9c31759615f5b5f8de2 100644 (file)
@@ -1,3 +1,8 @@
+2016-02-18  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/69553
+       * g++.dg/torture/pr69553.C: New testcase.
+
 2016-02-18  Nick Clifton  <nickc@redhat.com>
 
         PR target/62254
diff --git a/gcc/testsuite/g++.dg/torture/pr69553.C b/gcc/testsuite/g++.dg/torture/pr69553.C
new file mode 100644 (file)
index 0000000..e68e42f
--- /dev/null
@@ -0,0 +1,35 @@
+// { dg-do run }
+template <typename _Tp, long _Nm> struct A {
+    typedef _Tp _Type[_Nm];
+    static _Tp &_S_ref(const _Type &p1, int p2) {
+       return const_cast<_Tp &>(p1[p2]);
+    }
+};
+template <typename _Tp, long _Nm> struct B {
+    typedef A<_Tp, _Nm> _AT_Type;
+    typename _AT_Type::_Type _M_elems;
+    _Tp &operator[](long p1) const { return _AT_Type::_S_ref(_M_elems, p1); }
+};
+int t;
+void foo(int p1, int &p2) {
+    if ((t & 1) == 0) {
+       if (p1 != 1)
+         __builtin_abort();
+       if (p2 != 2)
+         __builtin_abort();
+    }
+    t++;
+}
+__attribute__((noinline))
+     void test1(const B<int, 2> &p1) { foo(p1[0], p1[1]); }
+     void test(B<B<int, 2>, 2> &p1) {
+        test1(p1[0]);
+        test1(p1[1]);
+        foo(p1[0][0], p1[0][1]);
+     }
+int main() {
+    B<B<int, 2>, 2> t;
+    t[0][0] = 1;
+    t[0][1] = 2;
+    test(t);
+}