match: Optimize A > B ? ABS(A) : B to MAX(A, B) when B >= 0 [PR116700]

When B is known to be non-negative and A > B, A must be positive,
so ABS(A) == A.  The whole expression (A > B ? ABS(A) : B) then
simplifies to MAX(A, B).  This is caught at -O2 via VRP, but at
-O1 phiopt1 produces ABS_EXPR and no later pass simplifies it.

	PR tree-optimization/116700

gcc/ChangeLog:

	* match.pd: (A > B ? ABS(A) : B -> MAX(A, B)): New pattern
	for non-negative B.

gcc/testsuite/ChangeLog:

	* gcc.dg/pr116700.c: New test.
	* gcc.dg/tree-ssa/phi-opt-48.c: New test.

Signed-off-by: Avinal Kumar <avinal.xlvii@gmail.com>
This commit is contained in:
Avinal Kumar
2026-05-02 23:32:23 +05:30
committed by Andrew Pinski
parent 1e59a869af
commit e0c4c4cb02
3 changed files with 47 additions and 0 deletions

View File

@@ -7276,6 +7276,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (INTEGRAL_TYPE_P (type))
@3))
/* A > B ? ABS(A) : B -> MAX(A, B) when B is non-negative.
When A > B >= 0, A is positive so ABS(A) = A = MAX(A, B).
When A <= B, the result is B = MAX(A, B). */
(for cmp (gt ge)
(simplify
(cond (cmp:c @0 tree_expr_nonnegative_p@1) (abs @0) @1)
(if (INTEGRAL_TYPE_P (type))
(max @0 @1))))
/* (X + 1) > Y ? -X : 1 simplifies to X >= Y ? -X : 1 when
X is unsigned, as when X + 1 overflows, X is -1, so -X == 1. */
(simplify

View File

@@ -0,0 +1,13 @@
/* PR tree-optimization/116700 */
/* { dg-do compile } */
/* { dg-options "-O1 -fdump-tree-phiopt1" } */
int f(unsigned char a, int b, int c)
{
int t = a;
if (c > t) t = (c > 0 ? c : -c);
return t;
}
/* { dg-final { scan-tree-dump "MAX_EXPR" "phiopt1" } } */
/* { dg-final { scan-tree-dump-not "ABS_EXPR" "phiopt1" } } */

View File

@@ -0,0 +1,25 @@
/* { dg-do compile } */
/* { dg-options "-O1 -fdump-tree-phiopt1" } */
/* Test that (A > B) ? ABS(A) : B is simplified to MAX(A, B)
when B is known to be non-negative. */
int f(unsigned char a, int b, int c)
{
int t = a;
if (c > t)
t = (c > 0 ? c : -c);
return t;
}
int f1(unsigned char a, int b, int c)
{
int t = a;
if (c > t) return (c > 0 ? c : -c);
return t;
}
/* Both functions should be converted to MAX_EXPR by phiopt1. */
/* { dg-final { scan-tree-dump-times "MAX_EXPR" 2 "phiopt1" } } */
/* { dg-final { scan-tree-dump-not "ABS_EXPR" "phiopt1" } } */
/* { dg-final { scan-tree-dump-not "if " "phiopt1" } } */