AMD General > -----Original Message----- > From: Naveen <[email protected]> > Sent: 14 July 2026 12:24 > To: [email protected] > Subject: [PATCH] tree-optimization: Recognize add/sub absolute-value idiom > [PR56223] > > Caution: This message originated from an External Source. Use proper > caution when opening attachments, clicking links, or responding. > > > PHI-OPT fails to simplify conditional accumulation of an absolute value: > if (x >= 0) > y += x; > else > y -= x; > > For signed integral types, perform the addition in the corresponding unsigned > type and convert the result back to the original type. This avoids introducing > signed overflow and preserves wrapping semantics including when X is > TYPE_MIN_VALUE. Do not apply the transformation when signed overflow > traps or is sanitized. > > gcc/ChangeLog: > PR tree-optimization/56223 > * match.pd (X >=/> 0 ? Y + X : Y - X): New simplification. > (X <=/< 0 ? Y - X : Y + X): Likewise. > > gcc/testsuite/ChangeLog: > PR tree-optimization/56223 > * gcc.dg/tree-ssa/pr56223.c: New test. > * gcc.dg/tree-ssa/pr56223-2.c: New test. > > Signed-off-by: Naveen <[email protected]> > --- > gcc/match.pd | 35 +++++++++++++++++ > gcc/testsuite/gcc.dg/tree-ssa/pr56223-2.c | 39 +++++++++++++++++++ > gcc/testsuite/gcc.dg/tree-ssa/pr56223.c | 46 +++++++++++++++++++++++ > 3 files changed, 120 insertions(+) > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr56223-2.c > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr56223.c It will be good to included negative testcases for signed overflow trap or is sanitized. > > diff --git a/gcc/match.pd b/gcc/match.pd index d1a12c35ed3..70005a6fda2 > 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -7243,6 +7243,41 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > ) > ) > > + > + /* X >=/> 0 ? Y + X : Y - X same as Y + abs (X). > + Build the addition in an unsigned type for integral types so the > + replacement does not introduce signed overflow. */ (for cmp (ge > + gt) (simplify > + (cond (cmp @0 integer_zerop) (plus:c @0 @1) (minus @1 @0)) > + (if (INTEGRAL_TYPE_P (type) > + && types_match (type, @0) > + && types_match (type, @1) > + && !TYPE_UNSIGNED (type) > + && !TYPE_OVERFLOW_TRAPS (type) > + && !TYPE_OVERFLOW_SANITIZED (type)) > + (with { > + tree utype = unsigned_type_for (type); > + } > + (convert (plus:utype (convert:utype @1) (absu:utype @0))))))) > + > + /* X <=/< 0 ? Y - X : Y + X same as Y + abs (X). > + Build the addition in an unsigned type for integral types so the > + replacement does not introduce signed overflow. */ (for cmp (le > + lt) (simplify > + (cond (cmp @0 integer_zerop) (minus @1 @0) (plus:c @0 @1)) > + (if (INTEGRAL_TYPE_P (type) > + && types_match (type, @0) > + && types_match (type, @1) Can you check if the type checks for @0 and @1 are redundant here? A GIMPLE binary op requires operands and result to share one type hence it could be guaranteed that both already share the same type and we need not to check for both. > + && !TYPE_UNSIGNED (type) > + && !TYPE_OVERFLOW_TRAPS (type) > + && !TYPE_OVERFLOW_SANITIZED (type)) > + (with { > + tree utype = unsigned_type_for (type); > + } > + (convert (plus:utype (convert:utype @1) (absu:utype @0))))))) > + > /* -(type)!A -> (type)A - 1. */ > (simplify > (negate (convert?:s (logical_inverted_value:s @0))) diff --git > a/gcc/testsuite/gcc.dg/tree-ssa/pr56223-2.c b/gcc/testsuite/gcc.dg/tree- > ssa/pr56223-2.c > new file mode 100644 > index 00000000000..76ce731ad76 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr56223-2.c > @@ -0,0 +1,39 @@ > +/* PR tree-optimization/56223 */ > +/* Verify wrapping and INT_MIN behavior of the ABSU-based replacement. > +*/ > +/* { dg-do run } */ > +/* { dg-options "-O2 -fwrapv" } */ > + > +#define INT_MAX __INT_MAX__ > +#define INT_MIN (-INT_MAX - 1) > + > +__attribute__((noipa)) int > +f (int s, int x) > +{ > + if (x >= 0) > + s += x; > + else > + s -= x; > + return s; > +} > + > +int > +main (void) > +{ > + if (f (10, 4) != 14) > + __builtin_abort (); > + > + if (f (10, -4) != 14) > + __builtin_abort (); > + > + if (f (INT_MIN, INT_MIN) != 0) > + __builtin_abort (); > + > + if (f (INT_MAX, 1) != INT_MIN) > + __builtin_abort (); > + > + if (f (0, INT_MIN) != INT_MIN) > + __builtin_abort (); > + > + return 0; > +} > + > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr56223.c > b/gcc/testsuite/gcc.dg/tree- > ssa/pr56223.c > new file mode 100644 > index 00000000000..36e3c50f2d4 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr56223.c > @@ -0,0 +1,46 @@ > +/* PR tree-optimization/56223 */ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-phiopt2" } */ > + > +int > +f_ge (int s, int x) > +{ > + if (x >= 0) > + s += x; > + else > + s -= x; > + return s; > +} > + > +int > +f_gt (int s, int x) > +{ > + if (x > 0) > + s += x; > + else > + s -= x; > + return s; > +} > + > +int > +f_le (int s, int x) > +{ > + if (x <= 0) > + s -= x; > + else > + s += x; > + return s; > +} > + > +int > +f_lt (int s, int x) > +{ > + if (x < 0) > + s -= x; > + else > + s += x; > + return s; > +} > + > +/* { dg-final { scan-tree-dump-times "ABSU_EXPR" 4 "phiopt2" } } */ > +/* { dg-final { scan-tree-dump-not "if " "phiopt2" } } */ > -- > 2.34.1
Thx Dipesh
