On Sat, Sep 26, 2026 at 10:31 AM Dominic P <[email protected]> wrote: > > The ((X + C1) | (C2 - X)) < 0 fold from r17-4207 and its variants drop the > C2 - X or -X operand, which traps on overflow under -ftrapv: for > X = INT_MIN, ((X + 3) | -X) < 0 traps at -O0 but not at -O2. Do not > match when overflow traps. The ABS_EXPR form from r17-4207 already > requires TYPE_OVERFLOW_UNDEFINED.
I am trying to remember the rules here but I think what this might be doing is ok. -ftrapv and -fsanitize=undefined are fine to remove traps with optimizations turned on. The only issue would be remove the sanitization at -O0. Note we should have this documented somewhere instead of these undocumented rules too. Thanks, Andrea > > Bootstrapped and regression tested on x86_64-pc-linux-gnu. > > Assisted-by: Claude Opus 5 (Anthropic) > > gcc/ChangeLog: > > * match.pd (ior_range_test, ior_range_test_1, ior_range_test_0): > Do not match if overflow traps. > > gcc/testsuite/ChangeLog: > > * gcc.dg/tree-ssa/ior-range-test-4.c: New test. > > Signed-off-by: Dominic P <[email protected]> > --- > OK for trunk? > > gcc/match.pd | 6 +++++- > gcc/testsuite/gcc.dg/tree-ssa/ior-range-test-4.c | 14 ++++++++++++++ > 2 files changed, 19 insertions(+), 1 deletion(-) > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ior-range-test-4.c > > diff --git a/gcc/match.pd b/gcc/match.pd > index 688357f0ecd..862da998e62 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -5164,22 +5164,26 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (bit_ior:c@3 (plus@0 @4 INTEGER_CST@1) (minus INTEGER_CST@2 @4)) > (if (single_use (@3) > && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@0)) > + && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (@0)) > && wi::ge_p (wi::to_wide (@1) + wi::to_wide (@2), 0, SIGNED)))) > (match (ior_range_test_1 @0 @1) > (bit_ior:c@2 @0 (minus INTEGER_CST@1 @0)) > (if (single_use (@2) > && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@0)) > + && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (@0)) > && wi::ge_p (wi::to_wide (@1), 0, SIGNED)))) > (match (ior_range_test_1 @0 @1) > (bit_ior:c@2 (plus@0 @3 INTEGER_CST@1) (negate @3)) > (if (single_use (@2) > && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@0)) > + && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (@0)) > && wi::ge_p (wi::to_wide (@1), 0, SIGNED)))) > (match (ior_range_test_0 @0) > (bit_ior:c@1 @0 (negate @0)) > (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) > && single_use (@1) > - && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@0))))) > + && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@0)) > + && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (@0))))) > (for cmp (lt ge) > out (gt le) > (simplify > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ior-range-test-4.c > b/gcc/testsuite/gcc.dg/tree-ssa/ior-range-test-4.c > new file mode 100644 > index 00000000000..f9f0a1179b4 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/ior-range-test-4.c > @@ -0,0 +1,14 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -ftrapv -fdump-tree-optimized" } */ > +/* { dg-require-effective-target int32 } */ > + > +/* The subtraction and the negation can trap. */ > + > +int f1 (int x) { return ((x + 1) | (1 - x)) < 0; } > +int f2 (int x) { return (((x + 1) | (1 - x)) >> 31) & 1; } > +int f3 (int x) { return (x | (6 - x)) < 0; } > +int f4 (int x) { return ((x + 6) | -x) < 0; } > +int f5 (int x) { return (x | -x) < 0; } > +int f6 (int x) { return (unsigned) (x | -x) >> 31; } > + > +/* { dg-final { scan-tree-dump-times " \\| " 6 "optimized" } } */ > -- > 2.55.0 >
