diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index c37e1390a99..2f46815a812 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -3214,13 +3214,16 @@ typedef struct { } nir_loop_terminator; typedef struct { - /* Induction variable. */ + /* SSA def of the phi-node associated with this induction variable. */ + nir_def *basis; + + /* SSA def of the increment of the induction variable. */ nir_def *def; - /* Init statement with only uniform. */ + /* Init statement */ nir_src *init_src; - /* Update statement with only uniform. */ + /* Update statement */ nir_alu_src *update_src; } nir_loop_induction_variable; @@ -3254,9 +3257,8 @@ typedef struct { /* A list of loop_terminators terminating this loop. */ struct list_head loop_terminator_list; - /* array of induction variables for this loop */ - nir_loop_induction_variable *induction_vars; - unsigned num_induction_vars; + /* hash table of induction variables for this loop */ + struct hash_table *induction_vars; } nir_loop_info; typedef enum { diff --git a/src/compiler/nir/nir_inline_uniforms.c b/src/compiler/nir/nir_inline_uniforms.c index c5411319708..b9add68fd39 100644 --- a/src/compiler/nir/nir_inline_uniforms.c +++ b/src/compiler/nir/nir_inline_uniforms.c @@ -40,6 +40,7 @@ * (uniforms must be lowered to load_ubo before calling this) */ +#include "util/hash_table.h" #include "nir_builder.h" #include "nir_loop_analyze.h" @@ -182,42 +183,40 @@ is_induction_variable(const nir_src *src, int component, nir_loop_info *info, assert(component < src->ssa->num_components); /* Return true for induction variable (ie. i in for loop) */ - for (int i = 0; i < info->num_induction_vars; i++) { - nir_loop_induction_variable *var = info->induction_vars + i; - if (var->def == src->ssa) { - /* Induction variable should have constant initial value (ie. i = 0), - * constant update value (ie. i++) and constant end condition - * (ie. i < 10), so that we know the exact loop count for unrolling - * the loop. - * - * Add uniforms need to be inlined for this induction variable's - * initial and update value to be constant, for example: - * - * for (i = init; i < count; i += step) - * - * We collect uniform "init" and "step" here. - */ - if (var->init_src) { - if (!nir_collect_src_uniforms(var->init_src, component, - uni_offsets, num_offsets, - max_num_bo, max_offset)) - return false; - } + struct hash_entry *entry = _mesa_hash_table_search(info->induction_vars, src->ssa); + if (!entry) + return false; - if (var->update_src) { - nir_alu_src *alu_src = var->update_src; - if (!nir_collect_src_uniforms(&alu_src->src, - alu_src->swizzle[component], - uni_offsets, num_offsets, - max_num_bo, max_offset)) - return false; - } - - return true; - } + nir_loop_induction_variable *var = entry->data; + /* Induction variable should have constant initial value (ie. i = 0), + * constant update value (ie. i++) and constant end condition + * (ie. i < 10), so that we know the exact loop count for unrolling + * the loop. + * + * Add uniforms need to be inlined for this induction variable's + * initial and update value to be constant, for example: + * + * for (i = init; i < count; i += step) + * + * We collect uniform "init" and "step" here. + */ + if (var->init_src) { + if (!nir_collect_src_uniforms(var->init_src, component, + uni_offsets, num_offsets, + max_num_bo, max_offset)) + return false; } - return false; + if (var->update_src) { + nir_alu_src *alu_src = var->update_src; + if (!nir_collect_src_uniforms(&alu_src->src, + alu_src->swizzle[component], + uni_offsets, num_offsets, + max_num_bo, max_offset)) + return false; + } + + return true; } void diff --git a/src/compiler/nir/nir_loop_analyze.c b/src/compiler/nir/nir_loop_analyze.c index ccd122872ae..3ef0d9d8436 100644 --- a/src/compiler/nir/nir_loop_analyze.c +++ b/src/compiler/nir/nir_loop_analyze.c @@ -27,41 +27,19 @@ #include "nir.h" #include "nir_constant_expressions.h" -typedef struct nir_loop_variable { - /* The ssa_def associated with this info */ - nir_def *def; - - /* Could be a basic_induction if following uniforms are inlined */ - nir_src *init_src; - nir_alu_src *update_src; - - /** - * SSA def of the phi-node associated with this induction variable. - * - * Every loop induction variable has an associated phi node in the loop - * header. This may point to the same SSA def as \c def. If, however, \c def - * is the increment of the induction variable, this will point to the SSA - * def being incremented. - */ - nir_def *basis; -} nir_loop_variable; - typedef struct { /* The loop we store information for */ nir_loop *loop; - /* Loop_variable for all ssa_defs in function */ - struct hash_table *loop_vars; - nir_variable_mode indirect_mask; bool force_unroll_sampler_indirect; } loop_info_state; -static nir_loop_variable * +static nir_loop_induction_variable * get_loop_var(nir_def *value, loop_info_state *state) { - struct hash_entry *entry = _mesa_hash_table_search(state->loop_vars, value); + struct hash_entry *entry = _mesa_hash_table_search(state->loop->info->induction_vars, value); if (entry) return entry->data; else @@ -244,6 +222,8 @@ is_only_uniform_src(nir_src *src) static bool compute_induction_information(loop_info_state *state) { + bool progress = false; + /* We are only interested in checking phis for the basic induction * variable case as its simple to detect. All basic induction variables * have a phi node @@ -251,19 +231,8 @@ compute_induction_information(loop_info_state *state) nir_block *header = nir_loop_first_block(state->loop); nir_block *preheader = nir_block_cf_tree_prev(header); - /* There can be at most 2 induction vars per phi. */ - unsigned num_phis = 0; - nir_foreach_phi(phi, header) - num_phis++; - - nir_loop_info *info = state->loop->info; - info->induction_vars = reralloc(info, info->induction_vars, - nir_loop_induction_variable, - num_phis * 2); - info->num_induction_vars = 0; - nir_foreach_phi(phi, header) { - nir_loop_variable var = { .basis = &phi->def }; + nir_loop_induction_variable var = { .basis = &phi->def }; nir_foreach_phi_src(phi_src, phi) { nir_def *src = phi_src->src.ssa; @@ -324,28 +293,17 @@ compute_induction_information(loop_info_state *state) if (var.update_src && var.init_src && is_only_uniform_src(var.init_src)) { - /* Insert induction variables into hash table. */ - nir_loop_variable *induction_var = ralloc(state, nir_loop_variable); + /* Insert induction variable into hash table. */ + struct hash_table *vars = state->loop->info->induction_vars; + nir_loop_induction_variable *induction_var = ralloc(vars, nir_loop_induction_variable); *induction_var = var; - _mesa_hash_table_insert(state->loop_vars, induction_var->def, induction_var); - _mesa_hash_table_insert(state->loop_vars, induction_var->basis, induction_var); - - /* record induction variables into nir_loop_info */ - nir_loop_induction_variable *ivar; - ivar = &info->induction_vars[info->num_induction_vars++]; - ivar->def = var.basis; - ivar->init_src = var.init_src; - ivar->update_src = var.update_src; - ivar = &info->induction_vars[info->num_induction_vars++]; - ivar->def = var.def; - ivar->init_src = var.init_src; - ivar->update_src = var.update_src; - /* don't overflow */ - assert(info->num_induction_vars <= num_phis * 2); + _mesa_hash_table_insert(vars, induction_var->def, induction_var); + _mesa_hash_table_insert(vars, induction_var->basis, induction_var); + progress = true; } } - return info->num_induction_vars != 0; + return progress; } static bool @@ -416,13 +374,13 @@ find_loop_terminators(loop_info_state *state) static unsigned find_array_access_via_induction(loop_info_state *state, nir_deref_instr *deref, - nir_loop_variable **array_index_out) + nir_loop_induction_variable **array_index_out) { for (nir_deref_instr *d = deref; d; d = nir_deref_instr_parent(d)) { if (d->deref_type != nir_deref_type_array) continue; - nir_loop_variable *array_index = get_loop_var(d->arr.index.ssa, state); + nir_loop_induction_variable *array_index = get_loop_var(d->arr.index.ssa, state); if (!array_index) continue; @@ -460,7 +418,7 @@ guess_loop_limit(loop_info_state *state) intrin->intrinsic == nir_intrinsic_store_deref || intrin->intrinsic == nir_intrinsic_copy_deref) { - nir_loop_variable *array_idx = NULL; + nir_loop_induction_variable *array_idx = NULL; unsigned array_size = find_array_access_via_induction(state, nir_src_as_deref(intrin->src[0]), @@ -1013,8 +971,8 @@ get_induction_and_limit_vars(nir_scalar cond, lhs = nir_scalar_chase_alu_src(cond, 0); rhs = nir_scalar_chase_alu_src(cond, 1); - nir_loop_variable *src0_lv = get_loop_var(lhs.def, state); - nir_loop_variable *src1_lv = get_loop_var(rhs.def, state); + nir_loop_induction_variable *src0_lv = get_loop_var(lhs.def, state); + nir_loop_induction_variable *src1_lv = get_loop_var(rhs.def, state); if (src0_lv) { *ind = lhs; @@ -1199,7 +1157,7 @@ find_trip_count(loop_info_state *state, unsigned execution_mode, * Thats all thats needed to calculate the trip-count */ - nir_loop_variable *lv = get_loop_var(basic_ind.def, state); + nir_loop_induction_variable *lv = get_loop_var(basic_ind.def, state); /* The basic induction var might be a vector but, because we guarantee * earlier that the phi source has a scalar swizzle, we can take the @@ -1414,13 +1372,13 @@ initialize_loop_info_state(nir_loop *loop, void *mem_ctx, nir_function_impl *impl) { loop_info_state *state = rzalloc(mem_ctx, loop_info_state); - state->loop_vars = _mesa_pointer_hash_table_create(mem_ctx); state->loop = loop; if (loop->info) ralloc_free(loop->info); loop->info = rzalloc(loop, nir_loop_info); + loop->info->induction_vars = _mesa_pointer_hash_table_create(loop->info); list_inithead(&loop->info->loop_terminator_list); diff --git a/src/compiler/nir/nir_validate.c b/src/compiler/nir/nir_validate.c index 98a1e492234..7a6a89d8d45 100644 --- a/src/compiler/nir/nir_validate.c +++ b/src/compiler/nir/nir_validate.c @@ -27,6 +27,7 @@ #include #include "c11/threads.h" +#include "util/hash_table.h" #include "util/simple_mtx.h" #include "nir.h" #include "nir_xfb_info.h" @@ -1870,13 +1871,19 @@ validate_loop_info(nir_function_impl *impl, validate_state *state) validate_assert(state, are_loop_terminators_equal(a, b)); } - validate_assert(state, loop->info->num_induction_vars == md->num_induction_vars); - for (unsigned i = 0; i < MIN2(loop->info->num_induction_vars, md->num_induction_vars); i++) { - nir_loop_induction_variable *a = &loop->info->induction_vars[i]; - nir_loop_induction_variable *b = &md->induction_vars[i]; - validate_assert(state, a->def == b->def); - validate_assert(state, a->init_src == b->init_src); - validate_assert(state, a->update_src == b->update_src); + validate_assert(state, _mesa_hash_table_num_entries(loop->info->induction_vars) == + _mesa_hash_table_num_entries(md->induction_vars)); + hash_table_foreach(loop->info->induction_vars, var) { + struct hash_entry *prev_var = _mesa_hash_table_search(md->induction_vars, var->key); + validate_assert(state, prev_var != NULL); + if (prev_var) { + nir_loop_induction_variable *a = var->data; + nir_loop_induction_variable *b = prev_var->data; + validate_assert(state, a->basis == b->basis); + validate_assert(state, a->def == b->def); + validate_assert(state, a->init_src == b->init_src); + validate_assert(state, a->update_src == b->update_src); + } } } diff --git a/src/compiler/nir/tests/loop_analyze_tests.cpp b/src/compiler/nir/tests/loop_analyze_tests.cpp index 815e65e4617..54c3d189545 100644 --- a/src/compiler/nir/tests/loop_analyze_tests.cpp +++ b/src/compiler/nir/tests/loop_analyze_tests.cpp @@ -20,6 +20,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ +#include "util/hash_table.h" #include #include "nir.h" #include "nir_builder.h" @@ -263,20 +264,20 @@ TEST_F(nir_loop_analyze_test, one_iteration_fneu) EXPECT_TRUE(loop->info->exact_trip_count_known); /* Loop should have an induction variable for ssa_5 and ssa_4. */ - EXPECT_EQ(2, loop->info->num_induction_vars); ASSERT_NE((void *)0, loop->info->induction_vars); + EXPECT_EQ(2, _mesa_hash_table_num_entries(loop->info->induction_vars)); - /* The def field should not be NULL. The init_src field should point to a - * load_const. The update_src field should point to a load_const. + /* The basis and def fields should not be NULL. The init_src field should + * point to a load_const. The update_src field should point to a load_const. */ - 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)); + hash_table_foreach(loop->info->induction_vars, entry) { + nir_loop_induction_variable *ivar = (nir_loop_induction_variable *)entry->data; + EXPECT_NE((void *)0, ivar->basis); + EXPECT_NE((void *)0, ivar->def); + ASSERT_NE((void *)0, ivar->init_src); + EXPECT_TRUE(nir_src_is_const(*ivar->init_src)); + ASSERT_NE((void *)0, ivar->update_src); + EXPECT_TRUE(nir_src_is_const(ivar->update_src->src)); } } @@ -328,112 +329,109 @@ CMP_MIN(ilt, imax) CMP_MIN_REV(ilt, imin) INOT_COMPARE(ilt_imin_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, \ - .use_unknown_init_value = false, \ - .invert_exit_condition_and_continue_branch = false}); \ - \ - 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 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, \ + .use_unknown_init_value = false, \ + .invert_exit_condition_and_continue_branch = false }); \ + \ + 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); \ + \ + ASSERT_NE((void *)0, loop->info->induction_vars); \ + EXPECT_EQ(2, _mesa_hash_table_num_entries(loop->info->induction_vars)); \ + \ + hash_table_foreach(loop->info->induction_vars, entry) { \ + nir_loop_induction_variable *ivar = (nir_loop_induction_variable *)entry->data; \ + EXPECT_NE((void *)0, ivar->basis); \ + EXPECT_NE((void *)0, ivar->def); \ + ASSERT_NE((void *)0, ivar->init_src); \ + EXPECT_TRUE(nir_src_is_const(*ivar->init_src)); \ + ASSERT_NE((void *)0, ivar->update_src); \ + EXPECT_TRUE(nir_src_is_const(ivar->update_src->src)); \ + } \ } #define INEXACT_COUNT_TEST_UNKNOWN_INIT(_cond_value, _incr_value, cond, incr, count, invert) \ - TEST_F(nir_loop_analyze_test, incr ## _ ## cond ## _inexact_count_ ## count ## _invert_ ## invert) \ - { \ - nir_loop *loop = \ - loop_builder(&b, {.init_value = 0, \ - .cond_value = _cond_value, \ - .incr_value = _incr_value, \ - .cond_instr = nir_ ## cond, \ - .incr_instr = nir_ ## incr, \ - .use_unknown_init_value = true, \ - .invert_exit_condition_and_continue_branch = invert }); \ - \ - 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_FALSE(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_FALSE(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)); \ - } \ + TEST_F(nir_loop_analyze_test, incr##_##cond##_inexact_count_##count##_invert_##invert) \ + { \ + nir_loop *loop = \ + loop_builder(&b, { .init_value = 0, \ + .cond_value = _cond_value, \ + .incr_value = _incr_value, \ + .cond_instr = nir_##cond, \ + .incr_instr = nir_##incr, \ + .use_unknown_init_value = true, \ + .invert_exit_condition_and_continue_branch = invert }); \ + \ + 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_FALSE(loop->info->exact_trip_count_known); \ + \ + ASSERT_NE((void *)0, loop->info->induction_vars); \ + EXPECT_EQ(2, _mesa_hash_table_num_entries(loop->info->induction_vars)); \ + \ + hash_table_foreach(loop->info->induction_vars, entry) { \ + nir_loop_induction_variable *ivar = (nir_loop_induction_variable *)entry->data; \ + EXPECT_NE((void *)0, ivar->basis); \ + EXPECT_NE((void *)0, ivar->def); \ + ASSERT_NE((void *)0, ivar->init_src); \ + EXPECT_FALSE(nir_src_is_const(*ivar->init_src)); \ + ASSERT_NE((void *)0, ivar->update_src); \ + EXPECT_TRUE(nir_src_is_const(ivar->update_src->src)); \ + } \ } -#define INEXACT_COUNT_TEST(_init_value, _cond_value, _incr_value, cond, incr, count) \ - TEST_F(nir_loop_analyze_test, incr ## _ ## cond ## _inexact_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, \ - .use_unknown_init_value = false, \ - .invert_exit_condition_and_continue_branch = false}); \ - \ - 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_FALSE(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 INEXACT_COUNT_TEST(_init_value, _cond_value, _incr_value, cond, incr, count) \ + TEST_F(nir_loop_analyze_test, incr##_##cond##_inexact_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, \ + .use_unknown_init_value = false, \ + .invert_exit_condition_and_continue_branch = false }); \ + \ + 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_FALSE(loop->info->exact_trip_count_known); \ + \ + ASSERT_NE((void *)0, loop->info->induction_vars); \ + EXPECT_EQ(2, _mesa_hash_table_num_entries(loop->info->induction_vars)); \ + \ + hash_table_foreach(loop->info->induction_vars, entry) { \ + nir_loop_induction_variable *ivar = (nir_loop_induction_variable *)entry->data; \ + EXPECT_NE((void *)0, ivar->basis); \ + EXPECT_NE((void *)0, ivar->def); \ + ASSERT_NE((void *)0, ivar->init_src); \ + EXPECT_TRUE(nir_src_is_const(*ivar->init_src)); \ + ASSERT_NE((void *)0, ivar->update_src); \ + EXPECT_TRUE(nir_src_is_const(ivar->update_src->src)); \ + } \ } #define UNKNOWN_COUNT_TEST(_init_value, _cond_value, _incr_value, cond, incr) \ @@ -481,37 +479,36 @@ INOT_COMPARE(ilt_imin_rev) } #define KNOWN_COUNT_TEST_INVERT(_init_value, _incr_value, _cond_value, cond, incr, count) \ - TEST_F(nir_loop_analyze_test, incr ## _ ## cond ## _known_count_invert_ ## count) \ - { \ - nir_loop *loop = \ - loop_builder_invert(&b, {.init_value = _init_value, \ - .incr_value = _incr_value, \ - .cond_value = _cond_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)); \ - } \ + TEST_F(nir_loop_analyze_test, incr##_##cond##_known_count_invert_##count) \ + { \ + nir_loop *loop = \ + loop_builder_invert(&b, { .init_value = _init_value, \ + .incr_value = _incr_value, \ + .cond_value = _cond_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); \ + \ + ASSERT_NE((void *)0, loop->info->induction_vars); \ + EXPECT_EQ(2, _mesa_hash_table_num_entries(loop->info->induction_vars)); \ + \ + hash_table_foreach(loop->info->induction_vars, entry) { \ + nir_loop_induction_variable *ivar = (nir_loop_induction_variable *)entry->data; \ + EXPECT_NE((void *)0, ivar->basis); \ + EXPECT_NE((void *)0, ivar->def); \ + ASSERT_NE((void *)0, ivar->init_src); \ + EXPECT_TRUE(nir_src_is_const(*ivar->init_src)); \ + ASSERT_NE((void *)0, ivar->update_src); \ + EXPECT_TRUE(nir_src_is_const(ivar->update_src->src)); \ + } \ } #define UNKNOWN_COUNT_TEST_INVERT(_init_value, _incr_value, _cond_value, cond, incr) \