https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95853
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org --- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Created attachment 49606 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=49606&action=edit gcc11-pr95853-wip.patch I've tried to implement this, but on: #if __SIZEOF_INT128__ typedef __uint128_t W; typedef unsigned long long T; #else typedef unsigned long long W; typedef unsigned int T; #endif struct S { int p; T r; }; struct S foo (T x, T y) { W z = (W) x + y; return (struct S) { z > ~(T) 0, (T) z }; } struct S bar (T x) { W z = (W) x + 132; return (struct S) { z > ~(T) 0, (T) z }; } struct S baz (T x, unsigned short y) { W z = (W) x + y; return (struct S) { z > ~(T) 0, (T) z }; } struct S qux (unsigned short x, T y) { W z = (W) x + y; return (struct S) { z > ~(T) 0, (T) z }; } it actually handles only the baz and qux functions. The problem is that for foo and bar forwprop1 (for this optimization unhelpfully) forward propagates the addition, so we end up with: _1 = (__int128 unsigned) x_6(D); _2 = (__int128 unsigned) y_7(D); z_8 = _1 + _2; _3 = z_8 > 18446744073709551615; _4 = (int) _3; _5 = x_6(D) + y_7(D); D.1971.p = _4; D.1971.r = _5; return D.1971; and there is no (easy) connection between the two additions. I guess I could look through immediate uses of the rhs1's setter in that case.