re PR middle-end/69553 (Optimizations O1/O2 makes std::array value incorrect when passed to function)

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
This commit is contained in:
Richard Biener 2016-02-18 14:34:59 +00:00 committed by Richard Biener
parent cc7ab8a232
commit f003579e9c
4 changed files with 70 additions and 5 deletions

View 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

View 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

View 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

View File

@ -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);
}