diff --git a/.pick_status.json b/.pick_status.json index e22da8dc2f7..719d8fc0bc1 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -733,7 +733,7 @@ "description": "nir/loop_analyze: Fix get_iteration for nir_op_fneu", "nominated": true, "nomination_type": 1, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": "6772a17acc8ee90f9398348251a4455f988208fd" }, diff --git a/src/compiler/nir/nir_loop_analyze.c b/src/compiler/nir/nir_loop_analyze.c index 4fd192489ef..d9eca46f765 100644 --- a/src/compiler/nir/nir_loop_analyze.c +++ b/src/compiler/nir/nir_loop_analyze.c @@ -779,10 +779,27 @@ get_iteration(nir_op cond_op, nir_const_value initial, nir_const_value step, execution_mode); break; + case nir_op_fneu: + /* In order for execution to be here, limit must be the same as initial. + * Otherwise will_break_on_first_iteration would have returned false. + * If step is zero, the loop is infinite. Otherwise the loop will + * execute once. + * + * This is a little more tricky for floating point since X-Y might still + * be X even if Y is not zero. Instead check that (initial + step) != + * initial. + */ + span = eval_const_binop(nir_op_fadd, bit_size, initial, step, + execution_mode); + iter = eval_const_binop(nir_op_feq, bit_size, initial, + span, execution_mode); + + /* return (initial + step) == initial ? -1 : 1 */ + return iter.b ? -1 : 1; + case nir_op_fge: case nir_op_flt: case nir_op_feq: - case nir_op_fneu: span = eval_const_binop(nir_op_fsub, bit_size, limit, initial, execution_mode); iter = eval_const_binop(nir_op_fdiv, bit_size, span, @@ -953,6 +970,9 @@ calculate_iterations(nir_const_value initial, nir_const_value step, if (iter_int < 0) return -1; + if (alu_op == nir_op_ine || alu_op == nir_op_fneu) + return iter_int; + /* An explanation from the GLSL unrolling pass: * * Make sure that the calculated number of iterations satisfies the exit