https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82224
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |alias Status|UNCONFIRMED |ASSIGNED Last reconfirmed| |2017-09-18 Component|c |tree-optimization Ever confirmed|0 |1 --- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> --- It's more related to PR77745. With the testcase we are still removing the stores that change the active union member. They do have the same alias set unfortunately given they use union s1s2 * in their access path. The IL that we then up optimizing is <bb 2> [100.00%] [count: INV]: q[0].v1.x = 4321; ... _3 = &q + _2; _14 = MEM[(struct s1 *)&q].x; ... if (_15 != 0) goto <bb 3>; [33.00%] [count: INV] else goto <bb 4>; [67.00%] [count: INV] <bb 3> [33.00%] [count: INV]: MEM[(struct s2 *)_3].x = 1234; <bb 4> [100.00%] [count: INV]: _17 = MEM[(struct s1 *)&q].x; ... where you can see all loads/stores being done through s1/s2 types which do _not_ alias. So we have q->v1.x = 4321; // make v1 active if ((&q->v1)->x) // read via pointer to active member, supposedly valid { q->v2.x = q->v1.x; // change v2 to be active, same value, optimized away (&q->v2)->x = 1234; // write via pointer to active member q->v1.x = q->v2.x; // change v1 to be active, same value, optimized away } if ((&q->v1)->x != 1234) abort (); if we do not DSE the active member changing stores everything works as desired. Note that for GCC it isn't necessary to go through the union type when changing the active type. Note it definitely is desirable to elide the load/store changing the active member in the end. It's going to be tricky to find a solution that doesn't pessimize optimization when unions are involved. DOM is similarly affected, in the end it needs sufficiently obfuscated IL to trick our "handle must-aliases conservatively" code enough.