On Tue, Jun 16, 2026 at 10:44 PM Naveen <[email protected]> wrote: > > The patch adds simplifications for the pattern where a sign-bit check and a > lower-bits check are combined with a bitwise or logical AND/OR: > > (1) ((signed)A >= 0) &/&& ((A & INT_MAX) != 0) --> (signed)A > 0 > (2) ((signed)A < 0) |/|| ((A & INT_MAX) == 0) --> (signed)A <= 0 > > Both patterns arise naturally from code that separately tests the sign > bit and the magnitude of an unsigned integer. The combined expression > is equivalent to a single signed comparison, and the simplification > eliminates the intermediate BIT_AND_EXPR mask as well as the weaker > comparison operator. > > Bootstrapped and tested on aarch64-linux-gnu.
Ok. > > gcc/ChangeLog: > PR tree-optimization/112390 > * match.pd: Add simplifications for combined sign-bit and > magnitude checks: > ((signed)A >= 0) &/&& ((A & INT_MAX) != 0) -> (signed)A > 0 > ((signed)A < 0) |/|| ((A & INT_MAX) == 0) -> (signed)A <= 0 > > gcc/testsuite/ChangeLog: > PR tree-optimization/112390 > * gcc.dg/pr112390.c: New test. > * gcc.dg/pr112390_bitint.c: New test. > > Signed-off-by: Naveen <[email protected]> > --- > gcc/match.pd | 16 +++++ > gcc/testsuite/gcc.dg/pr112390.c | 93 ++++++++++++++++++++++++++ > gcc/testsuite/gcc.dg/pr112390_bitint.c | 20 ++++++ > 3 files changed, 129 insertions(+) > create mode 100644 gcc/testsuite/gcc.dg/pr112390.c > create mode 100644 gcc/testsuite/gcc.dg/pr112390_bitint.c > > diff --git a/gcc/match.pd b/gcc/match.pd > index 475939a0b63..ea3b270b3ff 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -1730,6 +1730,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (convert (bit_and (negate (convert:utype { pmop[0]; })) > (convert:utype @1))))))) > > +/* (signed)A >= 0 && (A & INT_MAX) != 0 --> (signed)A > 0 > + (signed)A < 0 || (A & INT_MAX) == 0 --> (signed)A <= 0 */ > +(for op (bit_and truth_and bit_ior truth_or) > + signop (ge ge lt lt) > + maskop (ne ne eq eq) > + resop (gt gt le le) > + (simplify > + (op:c > + (signop (nop_convert?@2 @0) integer_zerop) > + (maskop (bit_and @0 INTEGER_CST@3) integer_zerop)) > + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) > + && !TYPE_UNSIGNED (TREE_TYPE (@2)) > + && wi::eq_p (wi::to_wide (@3), > + wi::max_value (TYPE_PRECISION (TREE_TYPE (@0)), SIGNED))) > + (resop @2 { build_zero_cst (TREE_TYPE (@2)); })))) > + > /* X % Y is smaller than Y. */ > (for cmp (lt ge) > (simplify > diff --git a/gcc/testsuite/gcc.dg/pr112390.c b/gcc/testsuite/gcc.dg/pr112390.c > new file mode 100644 > index 00000000000..e28bfca4639 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pr112390.c > @@ -0,0 +1,93 @@ > +/* PR tree-optimization/112390 */ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-optimized" } */ > + > +#include <limits.h> > + > +int f32_bitand(unsigned int a) > +{ > + return ((int)a >= 0) & ((a & (unsigned)INT_MAX) != 0); > +} > + > +int f32_truthand(unsigned int a) > +{ > + return ((int)a >= 0) && ((a & (unsigned)INT_MAX) != 0); > +} > + > +int f32_bitior(unsigned int a) > +{ > + return ((int)a < 0) | ((a & (unsigned)INT_MAX) == 0); > +} > + > +int f32_truthor(unsigned int a) > +{ > + return ((int)a < 0) || ((a & (unsigned)INT_MAX) == 0); > +} > + > +int f32s_bitand(int a) > +{ > + return (a >= 0) & ((a & INT_MAX) != 0); > +} > + > +int f32s_truthand(int a) > +{ > + return (a >= 0) && ((a & INT_MAX) != 0); > +} > + > +int f32s_bitior(int a) > +{ > + return (a < 0) | ((a & INT_MAX) == 0); > +} > + > +int f32s_truthor(int a) > +{ > + return (a < 0) || ((a & INT_MAX) == 0); > +} > + > +int f64_bitand(unsigned long long a) > +{ > + return ((long long)a >= 0) & ((a & (unsigned long long)LLONG_MAX) != 0); > +} > + > +int f64_truthand(unsigned long long a) > +{ > + return ((long long)a >= 0) && ((a & (unsigned long long)LLONG_MAX) != 0); > +} > + > +int f64_bitior(unsigned long long a) > +{ > + return ((long long)a < 0) | ((a & (unsigned long long)LLONG_MAX) == 0); > +} > + > +int f64_truthor(unsigned long long a) > +{ > + return ((long long)a < 0) || ((a & (unsigned long long)LLONG_MAX) == 0); > +} > + > +int f64s_bitand(long long a) > +{ > + return (a >= 0) & ((a & LLONG_MAX) != 0); > +} > + > +int f64s_truthand(long long a) > +{ > + return (a >= 0) && ((a & LLONG_MAX) != 0); > +} > + > +int f64s_bitior(long long a) > +{ > + return (a < 0) | ((a & LLONG_MAX) == 0); > +} > + > +int f64s_truthor(long long a) > +{ > + return (a < 0) || ((a & LLONG_MAX) == 0); > +} > + > +/* { dg-final { scan-tree-dump-times ">= 0" 0 "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "< 0" 0 "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "BIT_AND_EXPR" 0 "optimized" } } */ > +/* { dg-final { scan-tree-dump-not "bit_and" "optimized" } } */ > +/* { dg-final { scan-tree-dump-not "bit_ior" "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "> 0" 8 "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "<= 0" 8 "optimized" } } */ > diff --git a/gcc/testsuite/gcc.dg/pr112390_bitint.c > b/gcc/testsuite/gcc.dg/pr112390_bitint.c > new file mode 100644 > index 00000000000..764be94b72b > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pr112390_bitint.c > @@ -0,0 +1,20 @@ > +/* PR tree-optimization/112390 - _BitInt variants */ > +/* { dg-do compile { target bitint } } */ > +/* { dg-options "-O2 -fdump-tree-optimized" } */ > + > +int fbit11_ior(unsigned _BitInt(11) a) > +{ > + signed _BitInt(11) sa = (signed _BitInt(11))a; > + return (sa < 0) | ((a & 1023wb) == 0); > +} > + > +int fbit11_and(unsigned _BitInt(11) a) > +{ > + signed _BitInt(11) sa = (signed _BitInt(11))a; > + return (sa >= 0) & ((a & 1023wb) != 0); > +} > + > +/* { dg-final { scan-tree-dump-not "bit_and" "optimized" } } */ > +/* { dg-final { scan-tree-dump-not "bit_ior" "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "> 0" 1 "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "<= 0" 1 "optimized" } } */ > -- > 2.34.1 >
