Module: Mesa Branch: main Commit: aa33ca0a52591961f8ae01dc253354462ed17c18 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=aa33ca0a52591961f8ae01dc253354462ed17c18
Author: Sviatoslav Peleshko <sviatoslav.peles...@globallogic.com> Date: Fri Nov 3 03:13:50 2023 +0200 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.peles...@globallogic.com> Reviewed-by: Lionel Landwerlin <lionel.g.landwer...@intel.com> Reviewed-by: Timothy Arceri <tarc...@itsqueeze.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26024> --- src/compiler/nir/nir_loop_analyze.c | 43 +++++++++++++++++++++++---- src/compiler/nir/tests/loop_analyze_tests.cpp | 41 +++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 5 deletions(-) diff --git a/src/compiler/nir/nir_loop_analyze.c b/src/compiler/nir/nir_loop_analyze.c index b7114ca9a67..4c39de9d949 100644 --- a/src/compiler/nir/nir_loop_analyze.c +++ b/src/compiler/nir/nir_loop_analyze.c @@ -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: diff --git a/src/compiler/nir/tests/loop_analyze_tests.cpp b/src/compiler/nir/tests/loop_analyze_tests.cpp index 2735d4cbcd4..f7c3c41d750 100644 --- a/src/compiler/nir/tests/loop_analyze_tests.cpp +++ b/src/compiler/nir/tests/loop_analyze_tests.cpp @@ -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)