[gcc r17-2972] tree-optimization: Recognize add/sub absolute-value idiom [PR56223]
"Naveen H.S via Gcc-cvs" <[email protected]> Wed, 5 Aug 2026 07:54:05 +0000 (GMT)
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://gcc.gnu.org/g:36990bb0d14c4840d0250f000559d7a2a569fbc9 commit r17-2972-g36990bb0d14c4840d0250f000559d7a2a569fbc9 Author: Naveen <[email protected]> Date: Wed Aug 5 00:52:53 2026 -0700 tree-optimization: Recognize add/sub absolute-value idiom [PR56223] Recognize conditional addition and subtraction patterns equivalent to Y + abs (X) and Y - abs (X). For signed integral types, perform the addition or subtraction 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 perform 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. * gcc.dg/tree-ssa/pr56223-3.c: New test. * gcc.dg/tree-ssa/pr56223-4.c: New test. Signed-off-by: Naveen <[email protected]> Diff: --- gcc/match.pd | 48 +++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr56223-2.c | 63 ++++++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr56223-3.c | 25 +++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr56223-4.c | 25 +++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr56223.c | 86 +++++++++++++++++++++++++++++++ 5 files changed, 247 insertions(+) diff --git a/gcc/match.pd b/gcc/match.pd index d5160d87e304..2545d62b4ab4 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -7270,6 +7270,54 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) ) ) +/* X >=/> 0 ? Y + X : Y - X + X <=/< 0 ? Y - X : Y + X + same as Y + abs (X). + + X >=/> 0 ? Y - X : Y + X + X <=/< 0 ? Y + X : Y - X + same as Y - abs (X). + + Build the addition or subtraction in an unsigned type for integral + types so the replacement does not introduce signed overflow. */ + +#if GIMPLE +(for cmp (ge gt) + (simplify + (cond (cmp @0 integer_zerop) (plus:c @0 @1) (minus @1 @0)) + (if (!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)))))) + (simplify + (cond (cmp @0 integer_zerop) (minus @1 @0) (plus:c @0 @1)) + (if (!TYPE_UNSIGNED (type) + && !TYPE_OVERFLOW_TRAPS (type) + && !TYPE_OVERFLOW_SANITIZED (type)) + (with { tree utype = unsigned_type_for (type); } + (convert (minus:utype (convert:utype @1) + (absu:utype @0))))))) +(for cmp (le lt) + (simplify + (cond (cmp @0 integer_zerop) (minus @1 @0) (plus:c @0 @1)) + (if (!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)))))) + (simplify + (cond (cmp @0 integer_zerop) (plus:c @0 @1) (minus @1 @0)) + (if (!TYPE_UNSIGNED (type) + && !TYPE_OVERFLOW_TRAPS (type) + && !TYPE_OVERFLOW_SANITIZED (type)) + (with { tree utype = unsigned_type_for (type); } + (convert (minus:utype (convert:utype @1) + (absu:utype @0))))))) +#endif + /* -(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 000000000000..f03105683c44 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr56223-2.c @@ -0,0 +1,63 @@ +/* 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 +add_abs (int s, int x) +{ + if (x >= 0) + s += x; + else + s -= x; + return s; +} + +__attribute__ ((noipa)) int +sub_abs (int s, int x) +{ + if (x >= 0) + s -= x; + else + s += x; + return s; +} + +int +main (void) +{ + if (add_abs (10, 4) != 14) + __builtin_abort (); + + if (add_abs (10, -4) != 14) + __builtin_abort (); + + if (add_abs (INT_MIN, INT_MIN) != 0) + __builtin_abort (); + + if (add_abs (INT_MAX, 1) != INT_MIN) + __builtin_abort (); + + if (add_abs (0, INT_MIN) != INT_MIN) + __builtin_abort (); + + if (sub_abs (10, 4) != 6) + __builtin_abort (); + + if (sub_abs (10, -4) != 6) + __builtin_abort (); + + if (sub_abs (INT_MIN, INT_MIN) != 0) + __builtin_abort (); + + if (sub_abs (INT_MIN, 1) != INT_MAX) + __builtin_abort (); + + if (sub_abs (0, INT_MIN) != INT_MIN) + __builtin_abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr56223-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr56223-3.c new file mode 100644 index 000000000000..595a7df1b2fd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr56223-3.c @@ -0,0 +1,25 @@ +/* PR tree-optimization/56223 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftrapv -fdump-tree-phiopt2" } */ + +int +add_abs (int s, int x) +{ + if (x >= 0) + s += x; + else + s -= x; + return s; +} + +int +sub_abs (int s, int x) +{ + if (x >= 0) + s -= x; + else + s += x; + return s; +} + +/* { dg-final { scan-tree-dump-not "ABSU_EXPR" "phiopt2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr56223-4.c b/gcc/testsuite/gcc.dg/tree-ssa/pr56223-4.c new file mode 100644 index 000000000000..f17f84219d92 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr56223-4.c @@ -0,0 +1,25 @@ +/* PR tree-optimization/56223 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fsanitize=signed-integer-overflow -fdump-tree-phiopt2" } */ + +int +add_abs (int s, int x) +{ + if (x >= 0) + s += x; + else + s -= x; + return s; +} + +int +sub_abs (int s, int x) +{ + if (x >= 0) + s -= x; + else + s += x; + return s; +} + +/* { dg-final { scan-tree-dump-not "ABSU_EXPR" "phiopt2" } } */ 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 000000000000..9a7c94bfb75d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr56223.c @@ -0,0 +1,86 @@ +/* PR tree-optimization/56223 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-phiopt2" } */ + +int +add_ge (int s, int x) +{ + if (x >= 0) + s += x; + else + s -= x; + return s; +} + +int +add_gt (int s, int x) +{ + if (x > 0) + s += x; + else + s -= x; + return s; +} + +int +add_le (int s, int x) +{ + if (x <= 0) + s -= x; + else + s += x; + return s; +} + +int +add_lt (int s, int x) +{ + if (x < 0) + s -= x; + else + s += x; + return s; +} + +int +sub_ge (int s, int x) +{ + if (x >= 0) + s -= x; + else + s += x; + return s; +} + +int +sub_gt (int s, int x) +{ + if (x > 0) + s -= x; + else + s += x; + return s; +} + +int +sub_le (int s, int x) +{ + if (x <= 0) + s += x; + else + s -= x; + return s; +} + +int +sub_lt (int s, int x) +{ + if (x < 0) + s += x; + else + s -= x; + return s; +} + +/* { dg-final { scan-tree-dump-times "ABSU_EXPR" 8 "phiopt2" } } */ +/* { dg-final { scan-tree-dump-not "if " "phiopt2" } } */