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

Author: Sviatoslav Peleshko <sviatoslav.peles...@globallogic.com>
Date:   Fri Nov  3 03:13:50 2023 +0200

nir/loop_analyze: Fix inverted condition handling in iterations calculation

In the tagged commit, we stopped actually inverting the condition, and
instead relied on the "invert_cond" flag. But we missed a few places
where this flag should've been handled too.

Also, add a few more tests to make sure this won't regress in the future.

Fixes: 99a7a664 ("nir/loop_analyze: Change invert_cond instead of changing the 
condition")
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/10012
Signed-off-by: Sviatoslav Peleshko <sviatoslav.peles...@globallogic.com>
Reviewed-by: Lionel Landwerlin <lionel.g.landwer...@intel.com>
Reviewed-by: Timothy Arceri <tarc...@itsqueeze.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26024>

---

 src/compiler/nir/nir_loop_analyze.c           | 43 +++++++++++++++++++++++----
 src/compiler/nir/tests/loop_analyze_tests.cpp | 41 +++++++++++++++++++++++++
 2 files changed, 79 insertions(+), 5 deletions(-)

diff --git a/src/compiler/nir/nir_loop_analyze.c 
b/src/compiler/nir/nir_loop_analyze.c
index b7114ca9a67..4c39de9d949 100644
--- a/src/compiler/nir/nir_loop_analyze.c
+++ b/src/compiler/nir/nir_loop_analyze.c
@@ -820,14 +820,46 @@ try_eval_const_alu(nir_const_value *dest, nir_alu_instr 
*alu,
    return true;
 }
 
+static nir_op
+invert_comparison_if_needed(nir_op alu_op, bool invert)
+{
+   if (!invert)
+      return alu_op;
+
+   switch (alu_op) {
+      case nir_op_fge:
+         return nir_op_flt;
+      case nir_op_ige:
+         return nir_op_ilt;
+      case nir_op_uge:
+         return nir_op_ult;
+      case nir_op_flt:
+         return nir_op_fge;
+      case nir_op_ilt:
+         return nir_op_ige;
+      case nir_op_ult:
+         return nir_op_uge;
+      case nir_op_feq:
+         return nir_op_fneu;
+      case nir_op_ieq:
+         return nir_op_ine;
+      case nir_op_fneu:
+         return nir_op_feq;
+      case nir_op_ine:
+         return nir_op_ieq;
+      default:
+         unreachable("Unsuported comparison!");
+   }
+}
+
 static int32_t
 get_iteration(nir_op cond_op, nir_const_value initial, nir_const_value step,
-              nir_const_value limit, unsigned bit_size,
+              nir_const_value limit, bool invert_cond, unsigned bit_size,
               unsigned execution_mode)
 {
    nir_const_value span, iter;
 
-   switch (cond_op) {
+   switch (invert_comparison_if_needed(cond_op, invert_cond)) {
    case nir_op_ine:
       /* In order for execution to be here, limit must be the same as initial.
        * Otherwise will_break_on_first_iteration would have returned false.
@@ -1060,8 +1092,8 @@ calculate_iterations(nir_def *basis, nir_def *limit_basis,
       assert(nir_src_bit_size(alu->src[0].src) ==
              nir_src_bit_size(alu->src[1].src));
 
-      iter_int = get_iteration(alu_op, initial, step, limit, bit_size,
-                               execution_mode);
+      iter_int = get_iteration(alu_op, initial, step, limit, invert_cond,
+                               bit_size, execution_mode);
       break;
    case nir_op_fmul:
       /* Detecting non-zero loop counts when the loop increment is floating
@@ -1087,7 +1119,8 @@ calculate_iterations(nir_def *basis, nir_def *limit_basis,
    if (iter_int < 0)
       return -1;
 
-   if (alu_op == nir_op_ine || alu_op == nir_op_fneu)
+   nir_op actual_alu_op = invert_comparison_if_needed(alu_op, invert_cond);
+   if (actual_alu_op == nir_op_ine || actual_alu_op == nir_op_fneu)
       return iter_int;
 
    /* An explanation from the GLSL unrolling pass:
diff --git a/src/compiler/nir/tests/loop_analyze_tests.cpp 
b/src/compiler/nir/tests/loop_analyze_tests.cpp
index 2735d4cbcd4..f7c3c41d750 100644
--- a/src/compiler/nir/tests/loop_analyze_tests.cpp
+++ b/src/compiler/nir/tests/loop_analyze_tests.cpp
@@ -284,6 +284,7 @@ COMPARE_REVERSE(ishl)
    }
 
 INOT_COMPARE(ilt_rev)
+INOT_COMPARE(ine)
 
 #define KNOWN_COUNT_TEST(_init_value, _cond_value, _incr_value, cond, incr, 
count) \
    TEST_F(nir_loop_analyze_test, incr ## _ ## cond ## _known_count_ ## count)  
  \
@@ -476,6 +477,26 @@ KNOWN_COUNT_TEST(0x00000000, 0x00000001, 0x00000001, uge, 
iadd, 1)
  */
 KNOWN_COUNT_TEST(0x00000000, 0x00000000, 0x00000001, ine, iadd, 1)
 
+/*    uint i = 0;
+ *    while (true) {
+ *       if (!(i != 6))
+ *          break;
+ *
+ *       i++;
+ *    }
+ */
+KNOWN_COUNT_TEST(0x00000000, 0x00000006, 0x00000001, inot_ine, iadd, 6)
+
+/*    uint i = 0;
+ *    while (true) {
+ *       i++;
+ *
+ *       if (!(i != 8))
+ *          break;
+ *    }
+ */
+KNOWN_COUNT_TEST_INVERT(0x00000000, 0x00000001, 0x00000008, inot_ine, iadd, 7)
+
 /*    uint i = 0;
  *    while (true) {
  *       if (i == 1)
@@ -486,6 +507,26 @@ KNOWN_COUNT_TEST(0x00000000, 0x00000000, 0x00000001, ine, 
iadd, 1)
  */
 KNOWN_COUNT_TEST(0x00000000, 0x00000001, 0x00000001, ieq, iadd, 1)
 
+/*    uint i = 0;
+ *    while (true) {
+ *       if (i == 6)
+ *          break;
+ *
+ *       i++;
+ *    }
+ */
+KNOWN_COUNT_TEST(0x00000000, 0x00000006, 0x00000001, ieq, iadd, 6)
+
+/*    uint i = 0;
+ *    while (true) {
+ *       i++;
+ *
+ *       if (i == 6)
+ *          break;
+ *    }
+ */
+KNOWN_COUNT_TEST_INVERT(0x00000000, 0x00000001, 0x00000006, ieq, iadd, 5)
+
 /*    float i = 0.0;
  *    while (true) {
  *       if (i != 0.0)

Reply via email to