]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
match: Optimize `A > B ? ABS(A) : B` to `MAX(A, B)` when B >= 0 [PR116700]
authorAvinal Kumar <avinal.xlvii@gmail.com>
Sat, 2 May 2026 18:02:23 +0000 (23:32 +0530)
committerAndrew Pinski <andrew.pinski@oss.qualcomm.com>
Mon, 4 May 2026 02:57:44 +0000 (19:57 -0700)
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>
gcc/match.pd
gcc/testsuite/gcc.dg/pr116700.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/phi-opt-48.c [new file with mode: 0644]

index dd9efb82c59dc215ce8b7b3d43a79dbbbd04b0c2..7db8ce7580f3fd4e25da75c1cf32d755ee6848ae 100644 (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
diff --git a/gcc/testsuite/gcc.dg/pr116700.c b/gcc/testsuite/gcc.dg/pr116700.c
new file mode 100644 (file)
index 0000000..a523882
--- /dev/null
@@ -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" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-48.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-48.c
new file mode 100644 (file)
index 0000000..596d7e2
--- /dev/null
@@ -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" } } */