On Sat, Oct 3, 2026 at 1:13 AM Andrea Pinski
<[email protected]> wrote:
>
> There are 2 patterns that are similar in match.pd for changing into
> a smaller abs. One handles `abs((ext)a)` and one for `(trunc)abs((ext)a)`.
> The one with the truncate afterwards does not use absu for integer types
> which can introduce undefined behavior in some cases.
> So let's restrict the second one to non integral types as the first one
> will handle those always; the check for casting from unsigned is another
> difference but the casting from unsigned is handled by a different abs
> pattern for non-negative values.
>
> Bootstrapped and tested on x86_64-linux-gnu.
>
> PR tree-optimization/127689
>
> gcc/ChangeLog:
>
> * match.pd (`(trunc)abs((ext)a)`): Move right
> after `abs((ext)a)` pattern. Restrict to
> non integral types.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.dg/torture/pr127689-1.c: New test.
>
> Signed-off-by: Andrea Pinski <[email protected]>
> ---
> gcc/match.pd | 22 +++++++++---------
> gcc/testsuite/gcc.dg/torture/pr127689-1.c | 28 +++++++++++++++++++++++
> 2 files changed, 39 insertions(+), 11 deletions(-)
> create mode 100644 gcc/testsuite/gcc.dg/torture/pr127689-1.c
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 2d1161b860b..648bda9bf11 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -214,6 +214,17 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
> (convert (absu:utype @0)))))
>
> +/* (trunc)abs (extend x) --> abs (x) for non-integral types. */
> +(simplify
> + (convert (abs (convert@1 @0)))
> + (if (!ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
> + && !HONOR_SNANS (@1)
> + && types_match (type, TREE_TYPE (@0))
> + && element_precision (type) < element_precision (TREE_TYPE (@1))
> + && (!VECTOR_TYPE_P (type)
> + || target_supports_op_p (type, ABS_EXPR, optab_default)))
> + (abs @0)))
> +
> #if GIMPLE
> /* Optimize (X + (X >> (prec - 1))) ^ (X >> (prec - 1)) into abs (X). */
> (simplify
> @@ -10340,17 +10351,6 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> (IFN_COPYSIGN @0 { build_minus_one_cst (type); })
> (IFN_COPYSIGN @0 { build_one_cst (type); })))))
>
> -/* (trunc)abs (extend x) --> abs (x) */
> -(simplify
> - (convert (abs (convert@1 @0)))
> - (if (optimize
> - && !HONOR_SNANS (@1)
> - && types_match (type, TREE_TYPE (@0))
> - && element_precision (type) < element_precision (TREE_TYPE (@1))
> - && (!VECTOR_TYPE_P (type)
> - || target_supports_op_p (type, ABS_EXPR, optab_default)))
> - (abs @0)))
> -
> (for froms (BUILT_IN_FMAF BUILT_IN_FMA BUILT_IN_FMAL)
> tos (IFN_FMA IFN_FMA IFN_FMA)
> (simplify
> diff --git a/gcc/testsuite/gcc.dg/torture/pr127689-1.c
> b/gcc/testsuite/gcc.dg/torture/pr127689-1.c
> new file mode 100644
> index 00000000000..cc169744bf2
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/pr127689-1.c
> @@ -0,0 +1,28 @@
> +/* { dg-do run } */
> +/* { dg-additional-options "-fno-tree-forwprop" } */
> +/* PR tree-optimization/127689 */
> +
> +
> +__attribute__((noipa))void check(int v)
> +{
> + if (v != -4)
> + __builtin_exit(1);
> +}
> +int p;
> +signed char s, v;
> +signed char t = 0x80;
> +__attribute__((noipa))
> +void y(signed char w) {
> + int t1;
Pushed with a small update to the testcase (which I missed when I was
moving from godbolt to the testsuite; and then forgot to test the
testcase until right before pushing the commit).
Thanks,
Andrea
> + t1 = __builtin_abs(t1); //256, 0x80
> + p = t1;
> + s = p;
> + signed char t2 = t1; // -256, 0x80
> + t = t2 % 3; // -2
> + v = 2 * t; // -4
> + check(v);
> +}
> +int main()
> +{
> + y(0x80);
> +}
> --
> 2.34.1
>