Mesa (staging/19.2): nir/loop_analyze: Treat do{}while(false) loops as 0 iterations
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Wed Sep 11 15:38:32 UTC 2019
Module: Mesa
Branch: staging/19.2
Commit: ad3907216feca4a1f9e39411d6d3b193de54ec6b
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=ad3907216feca4a1f9e39411d6d3b193de54ec6b
Author: Danylo Piliaiev <danylo.piliaiev at globallogic.com>
Date: Tue Aug 20 18:48:33 2019 +0300
nir/loop_analyze: Treat do{}while(false) loops as 0 iterations
Loops like:
block block_0:
vec1 32 ssa_2 = load_const (0x00000020)
vec1 32 ssa_3 = load_const (0x00000001)
loop {
vec1 32 ssa_7 = phi block_0: ssa_3, block_4: ssa_9
vec1 1 ssa_8 = ige ssa_2, ssa_7
if ssa_8 {
break
} else {
}
vec1 32 ssa_9 = iadd ssa_7, ssa_1
}
Were treated as having more than 1 iteration and after unrolling
produced wrong results, however such loop will exit during
the first iteration if not unrolled.
So we check if loop will actually loop.
Fixes tests/shaders/glsl-fs-loop-while-false-02.shader_test
Signed-off-by: Danylo Piliaiev <danylo.piliaiev at globallogic.com>
Reviewed-by: Timothy Arceri <tarceri at itsqueeze.com>
(cherry picked from commit e71fc7f2387dc14d08b7b310c41d83aa7a84c3b4)
---
src/compiler/nir/nir_loop_analyze.c | 49 +++++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/src/compiler/nir/nir_loop_analyze.c b/src/compiler/nir/nir_loop_analyze.c
index 0ac04b82799..4689d2230af 100644
--- a/src/compiler/nir/nir_loop_analyze.c
+++ b/src/compiler/nir/nir_loop_analyze.c
@@ -648,6 +648,43 @@ get_iteration(nir_op cond_op, nir_const_value initial, nir_const_value step,
}
static bool
+will_break_on_first_iteration(nir_const_value step,
+ nir_alu_type induction_base_type,
+ unsigned trip_offset,
+ nir_op cond_op, unsigned bit_size,
+ nir_const_value initial,
+ nir_const_value limit,
+ bool limit_rhs, bool invert_cond)
+{
+ if (trip_offset == 1) {
+ nir_op add_op;
+ switch (induction_base_type) {
+ case nir_type_float:
+ add_op = nir_op_fadd;
+ break;
+ case nir_type_int:
+ case nir_type_uint:
+ add_op = nir_op_iadd;
+ break;
+ default:
+ unreachable("Unhandled induction variable base type!");
+ }
+
+ initial = eval_const_binop(add_op, bit_size, initial, step);
+ }
+
+ nir_const_value *src[2];
+ src[limit_rhs ? 0 : 1] = &initial;
+ src[limit_rhs ? 1 : 0] = &limit;
+
+ /* Evaluate the loop exit condition */
+ nir_const_value result;
+ nir_eval_const_opcode(cond_op, &result, 1, bit_size, src);
+
+ return invert_cond ? !result.b : result.b;
+}
+
+static bool
test_iterations(int32_t iter_int, nir_const_value step,
nir_const_value limit, nir_op cond_op, unsigned bit_size,
nir_alu_type induction_base_type,
@@ -741,6 +778,18 @@ calculate_iterations(nir_const_value initial, nir_const_value step,
assert(nir_src_bit_size(alu->src[0].src) ==
nir_src_bit_size(alu->src[1].src));
unsigned bit_size = nir_src_bit_size(alu->src[0].src);
+
+ /* get_iteration works under assumption that iterator will be
+ * incremented or decremented until it hits the limit,
+ * however if the loop condition is false on the first iteration
+ * get_iteration's assumption is broken. Handle such loops first.
+ */
+ if (will_break_on_first_iteration(step, induction_base_type, trip_offset,
+ alu_op, bit_size, initial,
+ limit, limit_rhs, invert_cond)) {
+ return 0;
+ }
+
int iter_int = get_iteration(alu_op, initial, step, limit, bit_size);
/* If iter_int is negative the loop is ill-formed or is the conditional is
More information about the mesa-commit
mailing list