Module: Mesa
Branch: main
Commit: fc1ebc67b12978e1e580159560b69f8c7fb667a5
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=fc1ebc67b12978e1e580159560b69f8c7fb667a5

Author: Rhys Perry <pendingchao...@gmail.com>
Date:   Fri Dec  1 19:56:25 2023 +0000

nir/loop_analyze: support umin and {u,i,f}max

Signed-off-by: Rhys Perry <pendingchao...@gmail.com>
Acked-by: Timothy Arceri <tarc...@itsqueeze.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26225>

---

 src/compiler/nir/nir_loop_analyze.c           | 20 ++++++++++++++++----
 src/compiler/nir/tests/loop_analyze_tests.cpp | 11 +++++++++++
 2 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/src/compiler/nir/nir_loop_analyze.c 
b/src/compiler/nir/nir_loop_analyze.c
index 3fb21441f24..8146070e941 100644
--- a/src/compiler/nir/nir_loop_analyze.c
+++ b/src/compiler/nir/nir_loop_analyze.c
@@ -675,11 +675,19 @@ static nir_op invert_comparison_if_needed(nir_op alu_op, 
bool invert);
 
 /* Returns whether "limit_op(a, b) alu_op c" is equivalent to "(a alu_op c) || 
(b alu_op c)". */
 static bool
-is_min_compatible(nir_op limit_op, nir_op alu_op, bool limit_rhs, bool 
invert_cond)
+is_minmax_compatible(nir_op limit_op, nir_op alu_op, bool limit_rhs, bool 
invert_cond)
 {
+   bool is_max;
    switch (limit_op) {
    case nir_op_imin:
    case nir_op_fmin:
+   case nir_op_umin:
+      is_max = false;
+      break;
+   case nir_op_imax:
+   case nir_op_fmax:
+   case nir_op_umax:
+      is_max = true;
       break;
    default:
       return false;
@@ -690,15 +698,19 @@ is_min_compatible(nir_op limit_op, nir_op alu_op, bool 
limit_rhs, bool invert_co
 
    /* Comparisons we can split are:
     * - min(a, b) < c
+    * - c < max(a, b)
+    * - max(a, b) >= c
     * - c >= min(a, b)
     */
    switch (invert_comparison_if_needed(alu_op, invert_cond)) {
    case nir_op_ilt:
    case nir_op_flt:
-      return !limit_rhs;
+   case nir_op_ult:
+      return (!limit_rhs && !is_max) || (limit_rhs && is_max);
    case nir_op_ige:
    case nir_op_fge:
-      return limit_rhs;
+   case nir_op_uge:
+      return (!limit_rhs && is_max) || (limit_rhs && !is_max);
    default:
       return false;
    }
@@ -713,7 +725,7 @@ try_find_limit_of_alu(nir_scalar limit, nir_const_value 
*limit_val, nir_op alu_o
       return false;
 
    nir_op limit_op = nir_scalar_alu_op(limit);
-   if (is_min_compatible(limit_op, alu_op, !terminator->induction_rhs, 
invert_cond)) {
+   if (is_minmax_compatible(limit_op, alu_op, !terminator->induction_rhs, 
invert_cond)) {
       for (unsigned i = 0; i < 2; i++) {
          nir_scalar src = nir_scalar_chase_alu_src(limit, i);
          if (nir_scalar_is_const(src)) {
diff --git a/src/compiler/nir/tests/loop_analyze_tests.cpp 
b/src/compiler/nir/tests/loop_analyze_tests.cpp
index acd574bad54..b9a2c5e0a67 100644
--- a/src/compiler/nir/tests/loop_analyze_tests.cpp
+++ b/src/compiler/nir/tests/loop_analyze_tests.cpp
@@ -305,6 +305,7 @@ CMP_MIN_REV(ige, imin)
 CMP_MIN(ige, fmin)
 CMP_MIN(uge, imin)
 CMP_MIN(ilt, imin)
+CMP_MIN(ilt, imax)
 CMP_MIN_REV(ilt, imin)
 INOT_COMPARE(ilt_imin_rev)
 
@@ -1603,3 +1604,13 @@ UNKNOWN_COUNT_TEST(0x00000008, 0x00000004, 0xffffffff, 
ige_imin_rev, iadd)
  *    }
  */
 UNKNOWN_COUNT_TEST(0x00000008, 0x00000004, 0xffffffff, ilt_imin, iadd)
+
+/*    int i = 8;
+ *    while (true) {
+ *       if (i < imax(vertex_id, 4))
+ *          break;
+ *
+ *       i--;
+ *    }
+ */
+INEXACT_COUNT_TEST(0x00000008, 0x00000004, 0xffffffff, ilt_imax, iadd, 5)

Reply via email to