https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101419
--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
It is the cunrolli pass where things go wrong (it VNs the &u->c for both
__builtin_object_size calls while previously only the first one was &u->c and
the second was &u->i).
Now, objsz2 obviously needs to be done after IPA opts (most importantly
inlining), but what other opt passes we want in between IPA and objsz2 is a
question:
PUSH_INSERT_PASSES_WITHIN (pass_all_optimizations)
NEXT_PASS (pass_remove_cgraph_callee_edges);
/* Initial scalar cleanups before alias computation.
They ensure memory accesses are not indirect wherever possible. */
NEXT_PASS (pass_strip_predict_hints, false /* early_p */);
NEXT_PASS (pass_ccp, true /* nonzero_p */);
NEXT_PASS (pass_post_ipa_warn);
/* After CCP we rewrite no longer addressed locals into SSA
form if possible. */
NEXT_PASS (pass_complete_unrolli);
NEXT_PASS (pass_backprop);
NEXT_PASS (pass_phiprop);
NEXT_PASS (pass_forwprop);
NEXT_PASS (pass_object_sizes, false /* insert_min_max_p */);
I bet the rewriting no longer addressed locals into SSA form if possible done
for ccp could be sometimes relevant, because when an address is stored into a
previously address taken local and read back, then __bos could see it if in SSA
form and not otherwise. And in theory the cunrolli could reveal some cases,
though not sure.
So, either do the TODO_update_address_taken sooner (e.g. at end of
pass_remove_cgraph_callee_edges - does ccp itself bring any address taken
removal opportunities?) and then do objsz2, or schedule another objsz pass with
insert_minmax right at the start of pass_all_optimizations?
Out of ideas and it is still just mitigation.
Another way would be change SCCVN to handle it conservatively for __bos (x, 1)
but that could break the rarely used __bos (x, 3) - but it can break randomly
for both now. E.g. in the
_8 = &u_5(D)->c;
use (_8);
...
_9 = &u_5(D)->i;
use2 (_9);
case when objsz2 wasn't done yet (check with property) and perhaps if any __bos
(x, 1) are seen (cfun flag propagated conservatively during inlining), compute
__bos (ptr, 1) for both and rewrite the setter to the larger one, i.e. not
optimize into:
_8 = &u_5(D)->c;
use (_8);
...
use2 (_8);
but
_8 = &u_5(D)->i;
use (_8);
...
use2 (_8);