Re: [PATCH][committed][v2] match: fold two idioms built from the negation of a value
"H.J. Lu" <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <CAMe9rOqsD5BgmT9K+TAYSQgXbsZBLAg4AQk0eLifYYWJ0+A6eA@mail.gmail.com> |
On Thu, Aug 6, 2026 at 10:32 PM <[email protected]> wrote: > > From: Kyrylo Tkachov <[email protected]> > > X | -X has every bit from the lowest set bit of X upwards, so adding X to > it clears that bit, and masking with it isolates the padding needed to > round X up: > > X + (X | -X) -> X & (X - 1) > X + ((-X) & (C - 1)) -> (X + C - 1) & -C for a power of two C > > The second is the alignment round up written with the padding computed > first, which is how allocators tend to spell it. > > Neither needs a wrapping type. X - 1 overflows only for the most > negative value, where the source already does, and rounding X up is > representable exactly when X + C - 1 is, because the largest multiple of > C below the maximum leaves room for C - 1. Restrict both rules to integral > types. The bitwise operations also accept fixed-point types, whose > saturating arithmetic does not have these integer semantics. > > int f (int x) { return x + ((-x) & 15); } > > aarch64 -O2: > > before after > neg w1, w0 add w0, w0, 15 > and w1, w1, 15 and w0, w0, -16 > add w0, w1, w0 > > The vector spelling folds too, a uniform vector constant is matched with > uniform_integer_cst_p. > > Keep trapping and sanitized negations. Also keep the source addition > of X + (X | -X) under overflow sanitization because the replacement > would remove one recoverable diagnostic. Use :s on the consumed bitwise > expression. This prevents new work when it remains live, but allows the > fold when the replacement arithmetic is already available. > > Reuse the matched uniform constant and test its wide value directly. > This avoids rebuilding the same constant only to inspect it. > > Bootstrapped and tested on aarch64-none-linux-gnu. > Committed as per Richard's approval. > > gcc/ChangeLog: > > * match.pd (X + (X | -X)): New simplification. > (X + ((-X) & (C - 1))): Likewise. > > gcc/testsuite/ChangeLog: > > * gcc.dg/tree-ssa/signbit-1.c: New test. > * gcc.dg/tree-ssa/alignup-2.c: New test. > * gcc.dg/tree-ssa/vector-alignup-1.c: New test. > * gcc.dg/tree-ssa/alignup-overflow-1.c: New test. > * gcc.dg/tree-ssa/alignup-overflow-2.c: New test. > * gcc.dg/tree-ssa/signbit-4.c: New test. > On Linux/x86-64, I got FAIL: gcc.dg/tree-ssa/signbit-1.c scan-tree-dump-times optimized " \\| " 1 FAIL: gcc.dg/tree-ssa/signbit-1.c scan-tree-dump-times optimized " != 0" 3 -- H.J.