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.peleshko@globallogic.com>
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26024>
This commit is contained in:

committed by
Marge Bot

parent
385b81c8c2
commit
aa33ca0a52
@@ -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:
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user