Re: [PATCH 4/4] match.pd: build signed low-bit masks in an unsigned type
Andrea Pinski <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <CALvbMcAggv5Qpk4-1gzY=DSwgnyhF49odDV=gW5wgPUvm+uCcQ@mail.gmail.com> |
On Thu, Aug 20, 2026 at 4:57 AM <[email protected]> wrote: > > From: Kyrylo Tkachov <[email protected]> > > The PR71636 fold turns > > x & ((1U << b) - 1) > > into > > x & ~(~0U << b) > > but only when the mask type is unsigned. Signed source and vector forms keep > the longer expression. > > int f (int x, int b) > { > return x & ((1 << b) - 1); > } > > aarch64 -O2 before: > > f: > mov w2, 1 > lsl w2, w2, w1 > sub w2, w2, #1 > and w0, w2, w0 > ret > > After: > > f: > mov w2, -1 > lsl w2, w2, w1 > bic w0, w0, w2 > ret > > Build a signed mask in the corresponding unsigned type and convert it back. > This makes the all-ones shift defined and exposes the shorter form. The > preceding vector constant canonicalization lets the vector spelling reach the > same addition-of-minus-one rule. > > The signed form is not valid when the source addition can trap or is > instrumented for overflow. It can also remove the signed shift-base check for > the top-bit count. Keep these cases. After GIMPLE lowering, an explicit > shift sanitizer check remains visible, so the fold is safe again. > > Vector types carry the lane signedness used by the unsigned and trapping > checks. The first patch makes TYPE_OVERFLOW_SANITIZED accept integral vector > types. Query the matched type directly and test the canonical vector addition > under the sanitizer. > > Bootstrapped and tested on aarch64-none-linux-gnu and x86_64-pc-linux-gnu. > Ok for trunk? > Thanks, > Kyrill > > gcc/ChangeLog: > > * match.pd (x & ((1 << b) - 1)): Handle signed scalar and vector > types. > > gcc/testsuite/ChangeLog: > > * gcc.dg/tree-ssa/pr71636-signed-1.c: New test. > * gcc.dg/tree-ssa/pr71636-signed-vector-1.c: Likewise. > * gcc.dg/tree-ssa/pr71636-signed-vector-ubsan-1.c: Likewise. > * gcc.dg/tree-ssa/pr71636-signed-trap-1.c: Likewise. > * gcc.dg/tree-ssa/pr71636-signed-ubsan-1.c: Likewise. > * gcc.dg/tree-ssa/pr71636-signed-shift-ubsan-1.c: Likewise. > > Signed-off-by: Kyrylo Tkachov <[email protected]> > --- > gcc/match.pd | 13 +++++++--- > .../gcc.dg/tree-ssa/pr71636-signed-1.c | 24 +++++++++++++++++++ > .../tree-ssa/pr71636-signed-shift-ubsan-1.c | 11 +++++++++ > .../gcc.dg/tree-ssa/pr71636-signed-trap-1.c | 10 ++++++++ > .../gcc.dg/tree-ssa/pr71636-signed-ubsan-1.c | 10 ++++++++ > .../gcc.dg/tree-ssa/pr71636-signed-vector-1.c | 24 +++++++++++++++++++ > .../tree-ssa/pr71636-signed-vector-ubsan-1.c | 14 +++++++++++ > 7 files changed, 103 insertions(+), 3 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-1.c > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-shift-ubsan-1.c > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-trap-1.c > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-ubsan-1.c > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-vector-1.c > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-vector-ubsan-1.c > > diff --git a/gcc/match.pd b/gcc/match.pd > index e41f4c19bf4..ec54ffd68f9 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -1577,11 +1577,18 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (convert @0) > (convert @1))))) > > -/* PR71636: Transform x & ((1U << b) - 1) -> x & ~(~0U << b); */ > +/* PR71636: Transform x & ((1U << b) - 1) -> x & ~(~0U << b). For signed > + types, build the mask in the corresponding unsigned type, where shifting > + all ones left is defined. Preserve signed overflow and shift checks. */ > (simplify > (bit_and:c @0 (plus:s (lshift:s integer_onep @1) integer_minus_onep)) > - (if (TYPE_UNSIGNED (type)) > - (bit_and @0 (bit_not (lshift { build_all_ones_cst (type); } @1))))) > + (if (TYPE_UNSIGNED (type) > + || (!TYPE_OVERFLOW_TRAPS (type) > + && !TYPE_OVERFLOW_SANITIZED (type) > + && (GIMPLE || !sanitize_flags_p (SANITIZE_SHIFT_BASE)))) > + (with { tree utype = unsigned_type_for (type); } > + (bit_and @0 (convert I would put :type on the convert above to signify you are converting from utype to type; yes I know gnematch can figure that out but it is for the reader of the pattern to understand that Otherwise ok. . > + (bit_not (lshift { build_all_ones_cst (utype); } @1))))))) > > /* PR112533: Canonicalize boolean comparisons of masked pow2 bits into > xor-mask tests. > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-1.c > new file mode 100644 > index 00000000000..9db533fdf64 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-1.c > @@ -0,0 +1,24 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-optimized" } */ > + > +int > +f_signed (int x, int b) > +{ > + return x & ((1 << b) - 1); > +} > + > +unsigned int > +f_unsigned (unsigned int x, int b) > +{ > + return x & ((1U << b) - 1U); > +} > + > +long > +f_long (long x, int b) > +{ > + return x & ((1L << b) - 1L); > +} > + > +/* { dg-final { scan-tree-dump-not "1 <<" "optimized" } } */ > +/* { dg-final { scan-tree-dump-not " \\+ -1;" "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "= ~" 3 "optimized" } } */ > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-shift-ubsan-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-shift-ubsan-1.c > new file mode 100644 > index 00000000000..3abee74264c > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-shift-ubsan-1.c > @@ -0,0 +1,11 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fsanitize=shift-base -fdump-tree-optimized" } */ > + > +int > +f (int x, int b) > +{ > + return x & ((1 << b) - 1); > +} > + > +/* { dg-final { scan-tree-dump-times "__builtin___ubsan_handle_shift_out_of_bounds" 1 "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "= ~" 1 "optimized" } } */ > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-trap-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-trap-1.c > new file mode 100644 > index 00000000000..13a1a5b4cf2 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-trap-1.c > @@ -0,0 +1,10 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -ftrapv -fdump-tree-optimized" } */ > + > +int > +f (int x, int b) > +{ > + return x & ((1 << b) - 1); > +} > + > +/* { dg-final { scan-tree-dump-times " \\+ -1;" 1 "optimized" } } */ > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-ubsan-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-ubsan-1.c > new file mode 100644 > index 00000000000..68c1b92f18b > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-ubsan-1.c > @@ -0,0 +1,10 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fsanitize=signed-integer-overflow -fdump-tree-optimized" } */ > + > +int > +f (int x, int b) > +{ > + return x & ((1 << b) - 1); > +} > + > +/* { dg-final { scan-tree-dump-times "\\.UBSAN_CHECK_SUB" 1 "optimized" } } */ > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-vector-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-vector-1.c > new file mode 100644 > index 00000000000..51ba0b35334 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-vector-1.c > @@ -0,0 +1,24 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-optimized" } */ > +/* { dg-require-effective-target vect_int } */ > +/* { dg-require-effective-target vect_var_shift } */ > + > +typedef int v4si __attribute__ ((vector_size (16))); > +typedef unsigned int v4ui __attribute__ ((vector_size (16))); > + > +v4si > +f_signed (v4si x, v4si b) > +{ > + v4si one = { 1, 1, 1, 1 }; > + return x & ((one << b) - one); > +} > + > +v4ui > +f_unsigned (v4ui x, v4ui b) > +{ > + v4ui one = { 1, 1, 1, 1 }; > + return x & ((one << b) - one); > +} > + > +/* { dg-final { scan-tree-dump-not "\\{ 1, 1, 1, 1 \\} <<" "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "= ~" 2 "optimized" } } */ > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-vector-ubsan-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-vector-ubsan-1.c > new file mode 100644 > index 00000000000..9d9ec830ad7 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr71636-signed-vector-ubsan-1.c > @@ -0,0 +1,14 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -Wno-psabi -fsanitize=signed-integer-overflow -fno-sanitize=shift-base -fdump-tree-ubsan" } */ > + > +typedef int v4si __attribute__ ((vector_size (4 * sizeof (int)))); > + > +v4si > +f (v4si x, v4si b) > +{ > + v4si one = { 1, 1, 1, 1 }; > + v4si minus_one = { -1, -1, -1, -1 }; > + return x & ((one << b) + minus_one); > +} > + > +/* { dg-final { scan-tree-dump-times "\\.UBSAN_CHECK_ADD" 1 "ubsan" } } */ > -- > 2.50.1 (Apple Git-155) >