https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59739
--- Comment #8 from Richard Biener <rguenth at gcc dot gnu.org> ---
The last testcase shows
<bb 2> :
# .MEM_9 = VDEF <.MEM_6(D)>
D.8527 = S::operator<=> (a_7(D), b_8(D));
<bb 3> :
# VUSE <.MEM_9>
__v$_M_value_21 = D.8527._M_value;
if (__v$_M_value_21 < 0)
goto <bb 7>; [INV]
else
goto <bb 4>; [INV]
<bb 4> :
# .MEM_11 = VDEF <.MEM_9>
D.8527 = S::operator<=> (a_7(D), b_8(D));
so in this case the result is even the same memory temporary.
Consider
x = foo(1);
x.z = 2;
use (x);
x = foo(1);
"saving" the result of foo(1) to be re-used the 2nd time would require
a new temporary aggregate. It's basically lowering to
_1 = foo (1);
x = _1;
x.z = 2;
use (x);
x = _1;
with the hope that _1 and x can be coalesced later.
The C++ case can possibly be handled directly in visit_reference_op_call
by looking up with the next VUSE after discovering the same LHS is being
used. But wiring this into VN itself is a bit difficult. Figuring
the 2nd store is a redundant one might be easier in this case.
This wouldn't help for the C testcase from comment#4 which uses two
different LHS temporaries.