From f003579e9cdd2f28f7a5b0985d541c2f375bbf11 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 18 Feb 2016 14:34:59 +0000 Subject: [PATCH] re PR middle-end/69553 (Optimizations O1/O2 makes std::array value incorrect when passed to function) 2016-02-18 Richard Biener 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 | 6 ++++++ gcc/fold-const.c | 29 +++++++++++++++++++++++----- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/torture/pr69553.C | 35 ++++++++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/torture/pr69553.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c3118b9..b5bbb90 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2016-02-18 Richard Biener + + PR middle-end/69553 + * fold-const.c (operand_equal_p): Properly compare offsets for + IMAGPART_EXPR and ARRAY_REF. + 2016-02-18 Nick Clifton PR target/62254 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 4992f4b..41c652e 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a3aff74..90ed5de 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-02-18 Richard Biener + + PR middle-end/69553 + * g++.dg/torture/pr69553.C: New testcase. + 2016-02-18 Nick Clifton 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 index 0000000..e68e42f --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr69553.C @@ -0,0 +1,35 @@ +// { dg-do run } +template struct A { + typedef _Tp _Type[_Nm]; + static _Tp &_S_ref(const _Type &p1, int p2) { + return const_cast<_Tp &>(p1[p2]); + } +}; +template 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 &p1) { foo(p1[0], p1[1]); } + void test(B, 2> &p1) { + test1(p1[0]); + test1(p1[1]); + foo(p1[0][0], p1[0][1]); + } +int main() { + B, 2> t; + t[0][0] = 1; + t[0][1] = 2; + test(t); +} -- 2.7.4