diff --git a/src/compiler/nir/nir_loop_analyze.c b/src/compiler/nir/nir_loop_analyze.c index d998ec6f019..a439bcc19db 100644 --- a/src/compiler/nir/nir_loop_analyze.c +++ b/src/compiler/nir/nir_loop_analyze.c @@ -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 */ diff --git a/src/compiler/nir/tests/loop_analyze_tests.cpp b/src/compiler/nir/tests/loop_analyze_tests.cpp index 1fdf10df595..9b39a6653f9 100644 --- a/src/compiler/nir/tests/loop_analyze_tests.cpp +++ b/src/compiler/nir/tests/loop_analyze_tests.cpp @@ -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)