https://gcc.gnu.org/g:d8164f4da406c5061075472961b3c448604eb686
commit r17-4852-gd8164f4da406c5061075472961b3c448604eb686 Author: Andrea Pinski <[email protected]> Date: Fri Oct 2 05:36:15 2026 -0700 match: Fix `(convert)abs((convert)a)` pattern for integer overflow [PR127689] 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]> Diff: --- gcc/match.pd | 22 +++++++++++----------- gcc/testsuite/gcc.dg/torture/pr127689-1.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/gcc/match.pd b/gcc/match.pd index 2d1161b860b2..648bda9bf11f 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 000000000000..28c92d516712 --- /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 = w; + 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); +}
