+static bool
+guess_loop_limit(loop_info_state *state, nir_const_value *limit_val,
+ nir_ssa_scalar basic_ind)
+{
+ unsigned min_array_size = 0;
+
+ nir_foreach_block_in_cf_node(block, &state->loop->cf_node) {
+ nir_foreach_instr(instr, block) {
+ if (instr->type != nir_instr_type_intrinsic)
+ continue;
+
+ nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
+
+ /* Check for arrays variably-indexed by a loop induction variable. */
+ if (intrin->intrinsic == nir_intrinsic_load_deref ||
+ intrin->intrinsic == nir_intrinsic_store_deref ||
+ intrin->intrinsic == nir_intrinsic_copy_deref) {
+
+ nir_loop_variable *array_idx = NULL;
+ unsigned array_size =
+ find_array_access_via_induction(state,
+ nir_src_as_deref(intrin->src[0]),
+ &array_idx);
+ if (array_idx && basic_ind.def == array_idx->def &&
+ (min_array_size == 0 || min_array_size > array_size)) {
+ /* Array indices are scalars */
+ assert(basic_ind.def->num_components == 1);
+ min_array_size = array_size;
+ }
+
+ if (intrin->intrinsic != nir_intrinsic_copy_deref)
+ continue;
+
+ array_size =
+ find_array_access_via_induction(state,
+ nir_src_as_deref(intrin->src[1]),
+ &array_idx);
+ if (array_idx && basic_ind.def == array_idx->def &&
+ (min_array_size == 0 || min_array_size > array_size)) {
+ /* Array indices are scalars */
+ assert(basic_ind.def->num_components == 1);
+ min_array_size = array_size;
+ }
+ }
+ }
+ }
+
+ if (min_array_size) {
+ *limit_val = nir_const_value_for_uint(min_array_size,
+ basic_ind.def->bit_size);
+ return true;
+ }
+
+ return false;
+}
+
+static bool
+try_find_limit_of_alu(nir_ssa_scalar limit, nir_const_value *limit_val,
+ nir_loop_terminator *terminator, loop_info_state *state)
+{
+ if (!nir_ssa_scalar_is_alu(limit))
+ return false;
+
+ nir_op limit_op = nir_ssa_scalar_alu_op(limit);
+ if (limit_op == nir_op_imin || limit_op == nir_op_fmin) {
+ for (unsigned i = 0; i < 2; i++) {
+ nir_ssa_scalar src = nir_ssa_scalar_chase_alu_src(limit, i);
+ if (nir_ssa_scalar_is_const(src)) {
+ *limit_val = nir_ssa_scalar_as_const_value(src);
+ terminator->exact_trip_count_unknown = true;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static nir_const_value
+eval_const_unop(nir_op op, unsigned bit_size, nir_const_value src0,
+ unsigned execution_mode)
+{
+ assert(nir_op_infos[op].num_inputs == 1);
+ nir_const_value dest;
+ nir_const_value *src[1] = { &src0 };
+ nir_eval_const_opcode(op, &dest, 1, bit_size, src, execution_mode);
+ return dest;
+}
+
+static nir_const_value
+eval_const_binop(nir_op op, unsigned bit_size,
+ nir_const_value src0, nir_const_value src1,
+ unsigned execution_mode)
+{
+ assert(nir_op_infos[op].num_inputs == 2);
+ nir_const_value dest;
+ nir_const_value *src[2] = { &src0, &src1 };
+ nir_eval_const_opcode(op, &dest, 1, bit_size, src, execution_mode);
+ return dest;
+}
+