https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91384
--- Comment #10 from Richard Biener <rguenth at gcc dot gnu.org> --- But then void foo (void); void bar (void); int test (int a) { if (a) foo (); else bar (); return -a; } is not optimized either (the usual argument - the user could have written it in the way the compiler canonicalizes). On RTL where the CCs are appearant that's a LCM / PRE problem with the compare anticipating the zero flag here and the negate computing it. That makes it profitable to move the negate and eliminate the CC flag compute with it (for the testcase above). On the original case where we have int test (int a) { int r = -a; if (a) foo (); else bar (); return r; } that's more a local CSE opportunity (though of course for this modified testcase we sink the -a compute to the return, re-creating the first case in this comment). As it is only RTL representing CC at all this is really a RTL global optimization issue in the end. GIMPLE can only help to a limited extent and all missed canonicalization (like if we add a single_use check) eventually leads to missed global CSE opportunities.