The following fixes an ommision in find_constructor_constant_at_offset to handle RANGE_EXPR in array constructor indices. The handling is conservative in that it only handles the first index in the range.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk sofar. Richard. 2017-06-19 Richard Biener <rguent...@suse.de> PR ipa/81112 * ipa-prop.c (find_constructor_constant_at_offset): Handle RANGE_EXPR conservatively. * g++.dg/torture/pr81112.C: New testcase. Index: gcc/ipa-prop.c =================================================================== --- gcc/ipa-prop.c (revision 249245) +++ gcc/ipa-prop.c (working copy) @@ -3030,7 +3030,10 @@ find_constructor_constant_at_offset (tre if (index) { - off = wi::to_offset (index); + if (TREE_CODE (index) == RANGE_EXPR) + off = wi::to_offset (TREE_OPERAND (index, 0)); + else + off = wi::to_offset (index); if (TYPE_DOMAIN (type) && TYPE_MIN_VALUE (TYPE_DOMAIN (type))) { tree low_bound = TYPE_MIN_VALUE (TYPE_DOMAIN (type)); @@ -3039,6 +3042,8 @@ find_constructor_constant_at_offset (tre TYPE_PRECISION (TREE_TYPE (index))); } off *= wi::to_offset (unit_size); + /* ??? Handle more than just the first index of a + RANGE_EXPR. */ } else off = wi::to_offset (unit_size) * ix; Index: gcc/testsuite/g++.dg/torture/pr81112.C =================================================================== --- gcc/testsuite/g++.dg/torture/pr81112.C (nonexistent) +++ gcc/testsuite/g++.dg/torture/pr81112.C (working copy) @@ -0,0 +1,67 @@ +// { dg-do compile } + +class AssertionResult { + bool success_; +}; + +AssertionResult AssertionSuccess(); + +template <typename T1> +AssertionResult EXPECT_EQ(const T1& expected, const T1& actual) { + if (expected == actual) { + return AssertionSuccess(); + } + return AssertionSuccess(); +} + +struct uuid +{ + unsigned char data[16]; +}; + +bool operator== (uuid const& lhs, uuid const& rhs); + +typedef long long __m128i __attribute__ ((__vector_size__ (16), __may_alias__)); +typedef int __v4si __attribute__ ((__vector_size__ (16))); +typedef char __v16qi __attribute__ ((__vector_size__ (16))); +typedef long long __m128i_u __attribute__ ((__vector_size__ (16), __may_alias__, __aligned__ (1))); + +int foo (__v16qi); + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + _mm_loadu_si128 (__m128i_u const *__P) +{ + return *__P; +} +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + _mm_cmpeq_epi32 (__m128i __A, __m128i __B) +{ + return (__m128i) ((__v4si)__A == (__v4si)__B); +} +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + _mm_movemask_epi8 (__m128i __A) +{ + return foo ((__v16qi)__A); +} + + +__m128i load_unaligned_si128(const unsigned char* p) +{ + return _mm_loadu_si128(reinterpret_cast< const __m128i* >(p)); +} + +inline bool operator== (uuid const& lhs, uuid const& rhs) +{ + __m128i mm_left = load_unaligned_si128(lhs.data); + __m128i mm_right = load_unaligned_si128(rhs.data); + + __m128i mm_cmp = _mm_cmpeq_epi32(mm_left, mm_right); + + return _mm_movemask_epi8(mm_cmp) == 0xFFFF; +} + +void crash_gcc7() +{ + static const uuid u = uuid(); + EXPECT_EQ(u, u); +}