http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59125
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org --- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> --- Hack to disable the CSE for the relevant cases (which I think are not-offsetting COMPONENT_REFs): Index: gcc/tree-ssa-sccvn.c =================================================================== --- gcc/tree-ssa-sccvn.c (revision 204787) +++ gcc/tree-ssa-sccvn.c (working copy) @@ -759,7 +759,7 @@ copy_reference_ops_from_ref (tree ref, v } /* For non-calls, store the information that makes up the address. */ - + tree orig = ref; while (ref) { vn_reference_op_s temp; @@ -809,7 +809,9 @@ copy_reference_ops_from_ref (tree ref, v + tree_to_double_int (bit_offset) .rshift (BITS_PER_UNIT == 8 ? 3 : exact_log2 (BITS_PER_UNIT)); - if (off.fits_shwi ()) + if (off.fits_shwi () + && (TREE_CODE (orig) != ADDR_EXPR + || !off.is_zero ())) temp.off = off.low; } } regresses for example struct s { union { int i; char c[8]; } u; short x; }; char *foo (int b, struct s *p) { int *p1; char *p2; if (b) p1 = &p->u.i; p2 = p->u.c; return p2 + *p1; } which we then only PRE on the RTL level. Basically we won't treat those addresses as equal anymore. Unfortunately the object-size pass runs quite late so even the 2nd FRE is already finished (and I think first_instance doesn't work for passes that are also run during early opts). I'd say cfun->after_inlining should work but it won't because object-size is so late. I don't like moving passes around on the branch, but well ... we'd move it right after the forwprop run after inlining. I'm going to test that for trunk now (I still hate how objsize works and how we want it run so late).