mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-20 12:10:36 +02:00
nir/loop_analyze: store nir_loop_induction_variable hash table in loop_info
No need to create a separate array. Reviewed-by: Rhys Perry <pendingchaos02@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33131>
This commit is contained in:
parent
f327ece9bf
commit
fbaabcfb0a
5 changed files with 213 additions and 250 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <assert.h>
|
||||
#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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <gtest/gtest.h>
|
||||
#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) \
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue