This fixes the issue that SRA creates access replacements that cannot represent all values that can be represented with the storage of the access. The simple thing to do is to create an access replacement with a type that covers the whole access.
Of course there is the catch that we cannot do that (easily) for bitfield accesses, so leave those alone for now. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2012-02-14 Richard Guenther <rguent...@suse.de> PR tree-optimization/52244 PR tree-optimization/51528 * tree-sra.c (analyze_access_subtree): Only create INTEGER_TYPE replacements for integral types. * gcc.dg/torture/pr52244.c: New testcase. Index: gcc/tree-sra.c =================================================================== *** gcc/tree-sra.c (revision 184203) --- gcc/tree-sra.c (working copy) *************** analyze_access_subtree (struct access *r *** 2172,2182 **** && (root->grp_scalar_write || root->grp_assignment_write)))) { bool new_integer_type; ! if (TREE_CODE (root->type) == ENUMERAL_TYPE) { tree rt = root->type; ! root->type = build_nonstandard_integer_type (TYPE_PRECISION (rt), TYPE_UNSIGNED (rt)); new_integer_type = true; } else --- 2172,2192 ---- && (root->grp_scalar_write || root->grp_assignment_write)))) { bool new_integer_type; ! /* Always create access replacements that cover the whole access. ! For integral types this means the precision has to match. ! Avoid assumptions based on the integral type kind, too. */ ! if (INTEGRAL_TYPE_P (root->type) ! && (TREE_CODE (root->type) != INTEGER_TYPE ! || TYPE_PRECISION (root->type) != root->size) ! /* But leave bitfield accesses alone. */ ! && (root->offset % BITS_PER_UNIT) == 0) { tree rt = root->type; ! root->type = build_nonstandard_integer_type (root->size, TYPE_UNSIGNED (rt)); + root->expr = build_ref_for_offset (UNKNOWN_LOCATION, + root->base, root->offset, + root->type, NULL, false); new_integer_type = true; } else Index: gcc/testsuite/gcc.dg/torture/pr52244.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr52244.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr52244.c (revision 0) *************** *** 0 **** --- 1,36 ---- + /* { dg-do run } */ + + extern void abort (void); + + typedef union u_r + { + _Bool b; + unsigned char c; + } u_t; + + u_t + bar (void) + { + u_t u; + u.c = 0x12; + return u; + } + + u_t __attribute__ ((noinline)) + foo (void) + { + u_t u; + + u.b = 1; + u = bar (); + + return u; + } + + int main (int argc, char **argv) + { + u_t u = foo (); + if (u.c != 0x12) + abort (); + return 0; + }