nir/loop_analyze: Change invert_cond instead of changing the condition
authorIan Romanick <ian.d.romanick@intel.com>
Wed, 15 Feb 2023 00:12:23 +0000 (16:12 -0800)
committerMarge Bot <emma+marge@anholt.net>
Thu, 6 Apr 2023 23:50:27 +0000 (23:50 +0000)
This ensures that scenarios like
nir_loop_analyze_test.iadd_inot_ilt_rev_known_count_5 don't regress in
the next commit. It also means we don't change float comparisons. These
are probably fine... but it still made me a little uneasy.

Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3445>

src/compiler/nir/nir_loop_analyze.c
src/compiler/nir/tests/loop_analyze_tests.cpp

index d998ec6..a439bcc 100644 (file)
@@ -1236,6 +1236,8 @@ find_trip_count(loop_info_state *state, unsigned execution_mode)
 
       nir_op alu_op = nir_ssa_scalar_alu_op(cond);
 
+      bool invert_cond = terminator->continue_from_then;
+
       bool limit_rhs;
       nir_ssa_scalar basic_ind = { NULL, 0 };
       nir_ssa_scalar limit;
@@ -1247,7 +1249,8 @@ find_trip_count(loop_info_state *state, unsigned execution_mode)
           * inverse of x or y (i.e. which ever contained the induction var) in
           * order to compute the trip count.
           */
-         alu_op = inverse_comparison(nir_ssa_scalar_alu_op(cond));
+         alu_op = nir_ssa_scalar_alu_op(cond);
+         invert_cond = !invert_cond;
          trip_count_known = false;
          terminator->exact_trip_count_unknown = true;
       }
@@ -1258,7 +1261,8 @@ find_trip_count(loop_info_state *state, unsigned execution_mode)
              */
             if (alu_op == nir_op_inot) {
                cond = nir_ssa_scalar_chase_alu_src(cond, 0);
-               alu_op = inverse_comparison(nir_ssa_scalar_alu_op(cond));
+               alu_op = nir_ssa_scalar_alu_op(cond);
+               invert_cond = !invert_cond;
             }
 
             get_induction_and_limit_vars(cond, &basic_ind,
@@ -1329,7 +1333,7 @@ find_trip_count(loop_info_state *state, unsigned execution_mode)
                                             nir_instr_as_alu(lv->update_src->src.parent_instr),
                                             cond,
                                             alu_op, limit_rhs,
-                                            terminator->continue_from_then,
+                                            invert_cond,
                                             execution_mode);
 
       /* Where we not able to calculate the iteration count */
index 1fdf10d..9b39a66 100644 (file)
@@ -918,6 +918,49 @@ COMPARE_REVERSE(ige)
 COMPARE_REVERSE(ult)
 COMPARE_REVERSE(uge)
 
+#define INOT_COMPARE(comp)                                              \
+   static nir_ssa_def *                                                 \
+   nir_inot_ ## comp (nir_builder *b, nir_ssa_def *x, nir_ssa_def *y)   \
+   {                                                                    \
+      return nir_inot(b, nir_ ## comp (b, x, y));                       \
+   }
+
+INOT_COMPARE(ilt_rev)
+
+#define KNOWN_COUNT_TEST(_init_value, _cond_value, _incr_value, cond, incr, count) \
+   TEST_F(nir_loop_analyze_test, incr ## _ ## cond ## _known_count_ ## count)    \
+   {                                                                    \
+      nir_loop *loop =                                                  \
+         loop_builder(&b, {.init_value = _init_value,                   \
+                           .cond_value = _cond_value,                   \
+                           .incr_value = _incr_value,                   \
+                           .cond_instr = nir_ ## cond,                  \
+                           .incr_instr = nir_ ## incr});                \
+                                                                        \
+      nir_validate_shader(b.shader, "input");                           \
+                                                                        \
+      nir_loop_analyze_impl(b.impl, nir_var_all, false);                \
+                                                                        \
+      ASSERT_NE((void *)0, loop->info);                                 \
+      EXPECT_NE((void *)0, loop->info->limiting_terminator);            \
+      EXPECT_EQ(count, loop->info->max_trip_count);                     \
+      EXPECT_TRUE(loop->info->exact_trip_count_known);                  \
+                                                                        \
+      EXPECT_EQ(2, loop->info->num_induction_vars);                     \
+      ASSERT_NE((void *)0, loop->info->induction_vars);                 \
+                                                                        \
+      const nir_loop_induction_variable *const ivars =                  \
+         loop->info->induction_vars;                                    \
+                                                                        \
+      for (unsigned i = 0; i < loop->info->num_induction_vars; i++) {   \
+         EXPECT_NE((void *)0, ivars[i].def);                            \
+         ASSERT_NE((void *)0, ivars[i].init_src);                       \
+         EXPECT_TRUE(nir_src_is_const(*ivars[i].init_src));             \
+         ASSERT_NE((void *)0, ivars[i].update_src);                     \
+         EXPECT_TRUE(nir_src_is_const(ivars[i].update_src->src));       \
+      }                                                                 \
+   }
+
 #define UNKNOWN_COUNT_TEST(_init_value, _cond_value, _incr_value, cond, incr) \
    TEST_F(nir_loop_analyze_test, incr ## _ ## cond ## _unknown_count)   \
    {                                                                    \
@@ -998,6 +1041,16 @@ COMPARE_REVERSE(uge)
       EXPECT_FALSE(loop->info->exact_trip_count_known);                 \
    }
 
+/*    uint i = 10;
+ *    while (true) {
+ *       if (!(5 < i))
+ *          break;
+ *
+ *       i += -1;
+ *    }
+ */
+KNOWN_COUNT_TEST(0x0000000a, 0x00000005, 0xffffffff, inot_ilt_rev, iadd, 5)
+
 /*    uint i = 0;
  *    while (true) {
  *       if (i != 0)