Fold times negated into negative bitwise AND
GCC now simplifies `x * -y` to `-(x & y)` when `x` and `y` are known to be 0 or 1, improving code generation for conditional operations.
This commit adds a new simplification rule to match.pd that folds multiplications of 0/1 values with negated 0/1 values into a negative bitwise AND operation (x * -y becomes -(x & y)). This optimization, particularly useful after if-conversion produces 0/1 masks from comparisons, exposes underlying bitwise logic to subsequent compiler passes. It results in a modest ~2.4% performance improvement in a hot kernel for astcenc on AArch64 within SPEC2026.
In Details
The match.pd file in GCC drives pattern matching for tree-level optimizations. This particular new fold simplifies x * -y into -(x & y) when operands x, y are constrained to {0,1}. This complements an existing x * y -> x & y rule, specifically addressing cases where one operand is negated. This exposes the underlying bitwise AND to later passes and leverages the structural properties of 0/1 masks often produced by if-conversion for conditions, yielding better code generation, evidenced by the performance win in astcenc.
For Context
Compilers work to make your code run faster by identifying and simplifying patterns. This commit introduces a new optimization within GCC (specifically in the match.pd file) that recognizes a common pattern: multiplying a value that is either 0 or 1 by another value that is either 0 or 1, but negated. Instead of performing a multiplication and a negation, the compiler can now simplify this to a bitwise AND operation followed by a single negation. This is particularly useful when conditional statements are converted into arithmetic operations (a process called if-conversion), as those often produce 0/1 values. This simplification helps the compiler generate more efficient machine code, leading to small performance gains in certain applications, such as a 2.4% improvement in a specific part of the astcenc program.