Hi, this fixes a thinko that leads to wrong-code generation that is in the "new" SRA since the beginning. When there are two unscalarizable regions in an access tree, one within another, the aggregate assignment modification code may use them as basis of new memory accesses, which means it very likely ignores an array reference along the way. Using such a region in the code path is useless anyway since by its nature there cannot be any replacements there.
This is a patch for trunk (on which it has passed bootstrap and testing on x86_64-linux) and the 4.7 branch, I'm in the process of testing equivalents for the 4.5 and 4.6 branches (the diff contexts differ slightly). OK for everywhere if all tests pass? Thanks, Martin 2012-03-24 Martin Jambor <mjam...@suse.cz> PR middle-end/52693 * tree-sra.c (sra_modify_assign): Do not call load_assign_lhs_subreplacements when working with an unscalarizable region. * testsuite/gcc.dg/torture/pr52693.c: New test. Index: src/gcc/tree-sra.c =================================================================== --- src.orig/gcc/tree-sra.c +++ src/gcc/tree-sra.c @@ -3071,7 +3071,13 @@ sra_modify_assign (gimple *stmt, gimple_ } else { - if (access_has_children_p (lacc) && access_has_children_p (racc)) + if (access_has_children_p (lacc) + && access_has_children_p (racc) + /* When an access represents an unscalarizable region, it usually + represents accesses with variable offset and thus must not be used + to generate new memory accesses. */ + && !lacc->grp_unscalarizable_region + && !racc->grp_unscalarizable_region) { gimple_stmt_iterator orig_gsi = *gsi; enum unscalarized_data_handling refreshed; Index: src/gcc/testsuite/gcc.dg/torture/pr52693.c =================================================================== --- /dev/null +++ src/gcc/testsuite/gcc.dg/torture/pr52693.c @@ -0,0 +1,33 @@ +/* { dg-do run } */ + +struct pair +{ + int x; + int y; +}; + +struct array +{ + struct pair elems[ 2 ]; + unsigned index; +}; + +extern void abort (); + +void __attribute__ ((noinline,noclone)) +test_results (int x1, int y1, int x2, int y2) +{ + if (x1 != x2 || y1 != y2) + abort (); +} + +int +main (void) +{ + struct array arr = {{{1,2}, {3,4}}, 1}; + struct pair last = arr.elems[arr.index]; + + test_results ( last.x, last.y, arr.elems[1].x, arr.elems[1].y); + + return 0; +}