"For every pessimization, there's an equal and opposite optimization". In the review of my original patch for PR middle-end/98865, Richard Biener pointed out that match.pd shouldn't be transforming X*Y into X&-Y as the former is considered cheaper by tree-ssa's cost model (operator count). A corollary of this is that we should instead be transforming X&-Y into the cheaper X*Y as a preferred canonical form (especially as RTL expansion now intelligently selects the appropriate implementation based on the target's costs). With this patch we now generate identical code for: int foo(int x, int y) { return -(x&1) & y; } int bar(int x, int y) { return (x&1) * y; } specifically on x86_64-pc-linux-gnu both use and/neg/and when optimizing for speed, but both use and/mul when optimizing for size. One minor wrinkle/improvement is that this patch includes three additional optimizations (that account for the change in canonical form) to continue to optimize PR92834 and PR94786. This patch has been tested on x86_64-pc-linux-gnu with make bootstrap and make -k check, both with and without --target_board=unix{-m32}, with no new failures. Ok for mainline? 2022-05-24 Roger Sayle gcc/ChangeLog * match.pd (match_zero_one_valued_p): New predicate. (mult @0 @1): Use zero_one_valued_p for optimization to the expression "bit_and @0 @1". (bit_and (negate zero_one_valued_p@0) @1): Optimize to MULT_EXPR. (plus @0 (mult (minus @1 @0) zero_one_valued_p@2): New transform. (minus @0 (mult (minus @0 @1) zero_one_valued_p@2): Likewise. (bit_xor @0 (mult (bit_xor @0 @1) zero_one_valued_p@2): Likewise. gcc/testsuite/ChangeLog * gcc.dg/pr98865.c: New test case. Thanks in advance, Roger --