diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4b7045179b4..517ff746289 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2010-07-21 Martin Jambor + + PR tree-optimization/44900 + * tree-sra.c (load_assign_lhs_subreplacements): Updated comments. + (sra_modify_assign): Move gsi to the next statmenent unconditionally. + 2010-07-21 Bernd Schmidt PR middle-end/44738 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 56aba5fd6eb..a6555a89896 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-07-21 Martin Jambor + + PR tree-optimization/44900 + * g++.dg/torture/pr44900.C: New test. + 2010-07-21 Bernd Schmidt PR middle-end/44738 diff --git a/gcc/testsuite/g++.dg/torture/pr44900.C b/gcc/testsuite/g++.dg/torture/pr44900.C new file mode 100644 index 00000000000..5c0efcb4b4e --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr44900.C @@ -0,0 +1,76 @@ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-msse" } */ +/* { dg-require-effective-target sse } */ + +typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__)); +typedef float __v4sf __attribute__ ((__vector_size__ (16))); + +extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, +__artificial__)) +_mm_set_ps (const float __Z, const float __Y, const float __X, const float __W) +{ + return __extension__ (__m128)(__v4sf){ __W, __X, __Y, __Z }; +} + +struct vec +{ + union { + __m128 v; + float e[4]; + }; + + static const vec & zero() + { + static const vec v = _mm_set_ps(0, 0, 0, 0); + return v; + } + + vec() {} + vec(const __m128 & a) : v(a) {} + + operator const __m128&() const { return v; } +}; + +struct vec2 +{ + vec _v1; + vec _v2; + + vec2() {} + vec2(const vec & a, const vec & b) : _v1(a), _v2(b) {} + + static vec2 load(const float * a) + { + return vec2( + __builtin_ia32_loadups(&a[0]), + __builtin_ia32_loadups(&a[4])); + } + + const vec & v1() const { return _v1; } + const vec & v2() const { return _v2; } +}; + +extern "C" void abort(void); + + +inline bool operator==(const vec & a, const vec & b) +{ return 0xf == __builtin_ia32_movmskps(__builtin_ia32_cmpeqps(a, b)); } + +int main( int argc, char * argv[] ) +{ + __attribute__((aligned(16))) float data[] = + { 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5 }; + + float * p = &data[2]; + vec2 a; + + a = vec2::load(p); + + vec v1 = a.v1(); + vec v2 = a.v2(); + + if (v2.e[3] != 7.0) + abort(); + + return 0; +} diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index e4971d2385b..9fd6d2cc592 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -2416,9 +2416,11 @@ handle_unscalarized_data_in_subtree (struct access *top_racc, tree lhs, (sub)tree. If that is not possible, refresh the TOP_RACC base aggregate and load the accesses from it. LEFT_OFFSET is the offset of the left whole subtree being copied, RIGHT_OFFSET is the same thing for the right subtree. - GSI is stmt iterator used for statement insertions. *REFRESHED is true iff - the rhs top aggregate has already been refreshed by contents of its scalar - reductions and is set to true if this function has to do it. */ + NEW_GSI is stmt iterator used for statement insertions after the original + assignment, OLD_GSI is used to insert statements before the assignment. + *REFRESHED keeps the information whether we have needed to refresh + replacements of the LHS and from which side of the assignments this takes + place. */ static void load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc, @@ -2722,9 +2724,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi) &orig_gsi, gsi, &refreshed, lhs); if (refreshed != SRA_UDH_RIGHT) { - if (*stmt == gsi_stmt (*gsi)) - gsi_next (gsi); - + gsi_next (gsi); unlink_stmt_vdef (*stmt); gsi_remove (&orig_gsi, true); sra_stats.deleted++;