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
>

Reply via email to