mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-22 11:20:11 +01:00
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@globallogic.com>
Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com>
This commit is contained in:
parent
84b3ef6a96
commit
e71fc7f238
1 changed files with 49 additions and 0 deletions
|
|
@ -647,6 +647,43 @@ get_iteration(nir_op cond_op, nir_const_value initial, nir_const_value step,
|
||||||
return iter_u64 > INT_MAX ? -1 : (int)iter_u64;
|
return iter_u64 > INT_MAX ? -1 : (int)iter_u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
static bool
|
||||||
test_iterations(int32_t iter_int, nir_const_value step,
|
test_iterations(int32_t iter_int, nir_const_value step,
|
||||||
nir_const_value limit, nir_op cond_op, unsigned bit_size,
|
nir_const_value limit, nir_op cond_op, unsigned bit_size,
|
||||||
|
|
@ -741,6 +778,18 @@ calculate_iterations(nir_const_value initial, nir_const_value step,
|
||||||
assert(nir_src_bit_size(alu->src[0].src) ==
|
assert(nir_src_bit_size(alu->src[0].src) ==
|
||||||
nir_src_bit_size(alu->src[1].src));
|
nir_src_bit_size(alu->src[1].src));
|
||||||
unsigned bit_size = nir_src_bit_size(alu->src[0].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);
|
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
|
/* If iter_int is negative the loop is ill-formed or is the conditional is
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue