PR tree-optimization/88575 - Use relations when simplifying MIN and MAX.

Message ID e554794b-f9c6-47e3-ae77-fbd60753d5d4@redhat.com
State New
Headers
Series PR tree-optimization/88575 - Use relations when simplifying MIN and MAX. |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-arm fail Patch failed to apply
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 fail Patch failed to apply

Commit Message

Andrew MacLeod Jan. 10, 2025, 9:43 p.m. UTC
  This should have been done a while ago.

The call to simplify MIN and MAX was guarded by a check for INTEGRAL, so 
I removed that as the code was already generalized to work with any type.

And no attempt was being made to pass in a relation... so I query for a 
relation between op0 and op1, and pass it to fold_range. And then all 
the right things happen.

I see Jeff fixed PR 110199 in DOM.   I copied the tests from that and 
created the same tests to test that
   a) EVRP is removing all the MIN_EXPR and MAX_EXPRs
   b) Added a float version of the tests with -ffast-math  to show its 
also working with floats.

Bootstraps on x86_64-pc-linux-gnu with no regressions.  OK for trunk?

Andrew

PS.    The same patch will not work on gcc-14, but the code could be 
ported if we wanted to.  Presumably DOM is getting the integral 
versions, so it would only be floats we would be new to handling.

gcc-13 is more challenging, but I think the infrastructure is there for 
the integer version. I dont think we have the proper float support yet. 
   But if DOM is already doing it from Jeffs patch, I'm not sure it matters.
  

Comments

Jeff Law Jan. 10, 2025, 11:22 p.m. UTC | #1
On 1/10/25 2:43 PM, Andrew MacLeod wrote:
> This should have been done a while ago.
Funny I said kind of the same thing when I did the DOM variant for 
integral types a little while back.

> 
> The call to simplify MIN and MAX was guarded by a check for INTEGRAL, so 
> I removed that as the code was already generalized to work with any type.
> 
> And no attempt was being made to pass in a relation... so I query for a 
> relation between op0 and op1, and pass it to fold_range. And then all 
> the right things happen.
> 
> I see Jeff fixed PR 110199 in DOM.   I copied the tests from that and 
> created the same tests to test that
>    a) EVRP is removing all the MIN_EXPR and MAX_EXPRs
>    b) Added a float version of the tests with -ffast-math  to show its 
> also working with floats.
> 
> Bootstraps on x86_64-pc-linux-gnu with no regressions.  OK for trunk?
OK.



> 
> Andrew
> 
> PS.    The same patch will not work on gcc-14, but the code could be 
> ported if we wanted to.  Presumably DOM is getting the integral 
> versions, so it would only be floats we would be new to handling.
I don't think it's worth backporting to gcc-13 or gcc-14.  It's a pretty 
minor missed optimization in my mind.


jeff
  

Patch

From fd4a9e3a3a9ab8cc4c728a0e64463755ccf39ed8 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Fri, 10 Jan 2025 13:33:01 -0500
Subject: [PATCH] Use relations when simplifying MIN and MAX.

Query for known relations between the operands, and pass that to
fold_range to help simplify MIN and MAX relations.
Make it type agnostic as well.

Adapt testcases from DOM to EVRP (e suffix) and test floats (f suffix).

	PR tree-optimization/88575
	gcc/
	* vr-values.cc (simplify_using_ranges::fold_cond_with_ops): Query
	relation between op0 and op1 and utilize it.
	(simplify_using_ranges::simplify): Do not eliminate float checks.

	gcc/testsuite/
	gcc.dg/tree-ssa/minmax-27.c: Disable VRP.
	gcc.dg/tree-ssa/minmax-27e.c: New.
	gcc.dg/tree-ssa/minmax-27f.c: New.
	gcc.dg/tree-ssa/minmax-28.c: Disable VRP.
	gcc.dg/tree-ssa/minmax-28e.c: New.
	gcc.dg/tree-ssa/minmax-2fe.c: New.
---
 gcc/testsuite/gcc.dg/tree-ssa/minmax-27.c  |   2 +-
 gcc/testsuite/gcc.dg/tree-ssa/minmax-27e.c | 118 +++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/minmax-27f.c | 118 +++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/minmax-28.c  |   2 +-
 gcc/testsuite/gcc.dg/tree-ssa/minmax-28e.c | 117 ++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/minmax-28f.c | 117 ++++++++++++++++++++
 gcc/vr-values.cc                           |  13 ++-
 7 files changed, 481 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/minmax-27e.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/minmax-27f.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/minmax-28e.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/minmax-28f.c

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-27.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-27.c
index 4b94203b0d0..a99af6eb521 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/minmax-27.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-27.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-dom2" } */
+/* { dg-options "-O2 -fdump-tree-dom2 -fno-tree-vrp" } */
 
 
 int min1(int a, int b)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-27e.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-27e.c
new file mode 100644
index 00000000000..8498ffd2017
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-27e.c
@@ -0,0 +1,118 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+
+int min1(int a, int b)
+{
+    if (a <= b)
+        return a < b ? a : b;
+    return 0;
+}
+
+int min2(int a, int b)
+{
+    if (a <= b)
+        return a > b ? b : a;
+    return 0;
+}
+
+int min3(int a, int b)
+{
+    if (a < b)
+        return a < b ? a : b;
+    return 0;
+}
+
+int min4(int a, int b)
+{
+    if (a < b)
+        return a > b ? b : a;
+    return 0;
+}
+
+int min5(int a, int b)
+{
+    if (a <= b)
+        return a <= b ? a : b;
+    return 0;
+}
+
+int min6(int a, int b)
+{
+    if (a <= b)
+        return a >= b ? b : a;
+    return 0;
+}
+
+int min7(int a, int b)
+{
+    if (a < b)
+        return a <= b ? a : b;
+    return 0;
+}
+
+int min8(int a, int b)
+{
+    if (b > a)
+        return a >= b ? b : a;
+    return 0;
+}
+
+int min9(int a, int b)
+{
+    if (b >= a)
+        return a < b ? a : b;
+    return 0;
+}
+
+int min10(int a, int b)
+{
+    if (b >= a)
+        return a > b ? b : a;
+    return 0;
+}
+
+int min11(int a, int b)
+{
+    if (b > a)
+        return a < b ? a : b;
+    return 0;
+}
+
+int min12(int a, int b)
+{
+    if (b > a)
+        return a > b ? b : a;
+    return 0;
+}
+
+int min13(int a, int b)
+{
+    if (b >= a)
+        return a <= b ? a : b;
+    return 0;
+}
+
+int min14(int a, int b)
+{
+    if (b >= a)
+        return a >= b ? b : a;
+    return 0;
+}
+
+int min15(int a, int b)
+{
+    if (b > a)
+        return a <= b ? a : b;
+    return 0;
+}
+
+int min16(int a, int b)
+{
+    if (b > a)
+        return a >= b ? b : a;
+    return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "MIN_EXPR" "evrp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-27f.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-27f.c
new file mode 100644
index 00000000000..63398d4495f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-27f.c
@@ -0,0 +1,118 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -ffast-math -fdump-tree-evrp" } */
+
+
+float min1(float a, float b)
+{
+    if (a <= b)
+        return a < b ? a : b;
+    return 0.0;
+}
+
+float min2(float a, float b)
+{
+    if (a <= b)
+        return a > b ? b : a;
+    return 0.0;
+}
+
+float min3(float a, float b)
+{
+    if (a < b)
+        return a < b ? a : b;
+    return 0.0;
+}
+
+float min4(float a, float b)
+{
+    if (a < b)
+        return a > b ? b : a;
+    return 0.0;
+}
+
+float min5(float a, float b)
+{
+    if (a <= b)
+        return a <= b ? a : b;
+    return 0.0;
+}
+
+float min6(float a, float b)
+{
+    if (a <= b)
+        return a >= b ? b : a;
+    return 0.0;
+}
+
+float min7(float a, float b)
+{
+    if (a < b)
+        return a <= b ? a : b;
+    return 0.0;
+}
+
+float min8(float a, float b)
+{
+    if (b > a)
+        return a >= b ? b : a;
+    return 0.0;
+}
+
+float min9(float a, float b)
+{
+    if (b >= a)
+        return a < b ? a : b;
+    return 0.0;
+}
+
+float min10(float a, float b)
+{
+    if (b >= a)
+        return a > b ? b : a;
+    return 0.0;
+}
+
+float min11(float a, float b)
+{
+    if (b > a)
+        return a < b ? a : b;
+    return 0.0;
+}
+
+float min12(float a, float b)
+{
+    if (b > a)
+        return a > b ? b : a;
+    return 0.0;
+}
+
+float min13(float a, float b)
+{
+    if (b >= a)
+        return a <= b ? a : b;
+    return 0.0;
+}
+
+float min14(float a, float b)
+{
+    if (b >= a)
+        return a >= b ? b : a;
+    return 0.0;
+}
+
+float min15(float a, float b)
+{
+    if (b > a)
+        return a <= b ? a : b;
+    return 0.0;
+}
+
+float min16(float a, float b)
+{
+    if (b > a)
+        return a >= b ? b : a;
+    return 0.0;
+}
+
+/* { dg-final { scan-tree-dump-not "MIN_EXPR" "evrp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-28.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-28.c
index 732126d7449..aa5598a292f 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/minmax-28.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-28.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-dom2" } */
+/* { dg-options "-O2 -fdump-tree-dom2 -fno-tree-vrp" } */
 
 int max1(int a, int b)
 {
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-28e.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-28e.c
new file mode 100644
index 00000000000..5d11f2d72f6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-28e.c
@@ -0,0 +1,117 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+int max1(int a, int b)
+{
+    if (a <= b)
+        return a < b ? b : a;
+    return 0;
+}
+
+int max2(int a, int b)
+{
+    if (a <= b)
+        return a > b ? a : b;
+    return 0;
+}
+
+int max3(int a, int b)
+{
+    if (a < b)
+        return a < b ? b : a;
+    return 0;
+}
+
+int max4(int a, int b)
+{
+    if (a < b)
+        return a > b ? a : b;
+    return 0;
+}
+
+int max5(int a, int b)
+{
+    if (a <= b)
+        return a <= b ? b : a;
+    return 0;
+}
+
+int max6(int a, int b)
+{
+    if (a <= b)
+        return a >= b ? a : b;
+    return 0;
+}
+
+int max7(int a, int b)
+{
+    if (a < b)
+        return a <= b ? b : a;
+    return 0;
+}
+
+int max8(int a, int b)
+{
+    if (b > a)
+        return a >= b ? a : b;
+    return 0;
+}
+
+int max9(int a, int b)
+{
+    if (b >= a)
+        return a < b ? b : a;
+    return 0;
+}
+
+int max10(int a, int b)
+{
+    if (b >= a)
+        return a > b ? a : b;
+    return 0;
+}
+
+int max11(int a, int b)
+{
+    if (b > a)
+        return a < b ? b : a;
+    return 0;
+}
+
+int max12(int a, int b)
+{
+    if (b > a)
+        return a > b ? a : b;
+    return 0;
+}
+
+int max13(int a, int b)
+{
+    if (b >= a)
+        return a <= b ? b : a;
+    return 0;
+}
+
+int max14(int a, int b)
+{
+    if (b >= a)
+        return a >= b ? a : b;
+    return 0;
+}
+
+int max15(int a, int b)
+{
+    if (b > a)
+        return a <= b ? b : a;
+    return 0;
+}
+
+int max16(int a, int b)
+{
+    if (b > a)
+        return a >= b ? a : b;
+    return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "MAX_EXPR" "evrp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-28f.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-28f.c
new file mode 100644
index 00000000000..f37d3c39468
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-28f.c
@@ -0,0 +1,117 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -ffast-math -fdump-tree-evrp" } */
+
+float max1(float a, float b)
+{
+    if (a <= b)
+        return a < b ? b : a;
+    return 0.0;
+}
+
+float max2(float a, float b)
+{
+    if (a <= b)
+        return a > b ? a : b;
+    return 0.0;
+}
+
+float max3(float a, float b)
+{
+    if (a < b)
+        return a < b ? b : a;
+    return 0.0;
+}
+
+float max4(float a, float b)
+{
+    if (a < b)
+        return a > b ? a : b;
+    return 0.0;
+}
+
+float max5(float a, float b)
+{
+    if (a <= b)
+        return a <= b ? b : a;
+    return 0.0;
+}
+
+float max6(float a, float b)
+{
+    if (a <= b)
+        return a >= b ? a : b;
+    return 0.0;
+}
+
+float max7(float a, float b)
+{
+    if (a < b)
+        return a <= b ? b : a;
+    return 0.0;
+}
+
+float max8(float a, float b)
+{
+    if (b > a)
+        return a >= b ? a : b;
+    return 0.0;
+}
+
+float max9(float a, float b)
+{
+    if (b >= a)
+        return a < b ? b : a;
+    return 0.0;
+}
+
+float max10(float a, float b)
+{
+    if (b >= a)
+        return a > b ? a : b;
+    return 0.0;
+}
+
+float max11(float a, float b)
+{
+    if (b > a)
+        return a < b ? b : a;
+    return 0.0;
+}
+
+float max12(float a, float b)
+{
+    if (b > a)
+        return a > b ? a : b;
+    return 0.0;
+}
+
+float max13(float a, float b)
+{
+    if (b >= a)
+        return a <= b ? b : a;
+    return 0.0;
+}
+
+float max14(float a, float b)
+{
+    if (b >= a)
+        return a >= b ? a : b;
+    return 0.0;
+}
+
+float max15(float a, float b)
+{
+    if (b > a)
+        return a <= b ? b : a;
+    return 0.0;
+}
+
+float max16(float a, float b)
+{
+    if (b > a)
+        return a >= b ? a : b;
+    return 0.0;
+}
+
+/* { dg-final { scan-tree-dump-not "MAX_EXPR" "evrp" } } */
+
diff --git a/gcc/vr-values.cc b/gcc/vr-values.cc
index 18e8e5865db..ed590138fe8 100644
--- a/gcc/vr-values.cc
+++ b/gcc/vr-values.cc
@@ -318,7 +318,14 @@  simplify_using_ranges::fold_cond_with_ops (enum tree_code code,
 
   int_range<1> res;
   range_op_handler handler (code);
-  if (handler && handler.fold_range (res, boolean_type_node, r0, r1))
+
+  // Find any relation between op0 and op1 and pass it to fold_range.
+  relation_kind rel = VREL_VARYING;
+  if (gimple_range_ssa_p (op0) && gimple_range_ssa_p (op1))
+    rel = query->relation ().query (s, op0, op1);
+
+  if (handler && handler.fold_range (res, boolean_type_node, r0, r1,
+				     relation_trio::op1_op2 (rel)))
     {
       if (res == range_true ())
 	return boolean_true_node;
@@ -1977,9 +1984,7 @@  simplify_using_ranges::simplify (gimple_stmt_iterator *gsi)
 
 	case MIN_EXPR:
 	case MAX_EXPR:
-	  if (INTEGRAL_TYPE_P (TREE_TYPE (rhs1)))
-	    return simplify_min_or_max_using_ranges (gsi, stmt);
-	  break;
+	  return simplify_min_or_max_using_ranges (gsi, stmt);
 
 	case RSHIFT_EXPR:
 	  {
-- 
2.45.0