return -1;
if (!iter->type->is_integer()) {
+ const ir_expression_operation op = iter->type->is_double()
+ ? ir_unop_d2i : ir_unop_f2i;
ir_rvalue *cast =
- new(mem_ctx) ir_expression(ir_unop_f2i, glsl_type::int_type, iter,
- NULL);
+ new(mem_ctx) ir_expression(op, glsl_type::int_type, iter, NULL);
iter = cast->constant_expression_value();
}
const int bias[] = { -1, 0, 1 };
bool valid_loop = false;
- for (unsigned i = 0; i < Elements(bias); i++) {
- iter = (increment->type->is_integer())
- ? new(mem_ctx) ir_constant(iter_value + bias[i])
- : new(mem_ctx) ir_constant(float(iter_value + bias[i]));
+ for (unsigned i = 0; i < ARRAY_SIZE(bias); i++) {
+ /* Increment may be of type int, uint or float. */
+ switch (increment->type->base_type) {
+ case GLSL_TYPE_INT:
+ iter = new(mem_ctx) ir_constant(iter_value + bias[i]);
+ break;
+ case GLSL_TYPE_UINT:
+ iter = new(mem_ctx) ir_constant(unsigned(iter_value + bias[i]));
+ break;
+ case GLSL_TYPE_FLOAT:
+ iter = new(mem_ctx) ir_constant(float(iter_value + bias[i]));
+ break;
+ case GLSL_TYPE_DOUBLE:
+ iter = new(mem_ctx) ir_constant(double(iter_value + bias[i]));
+ break;
+ default:
+ unreachable("Unsupported type for loop iterator.");
+ }
ir_expression *const mul =
new(mem_ctx) ir_expression(ir_binop_mul, increment->type, iter,
return visit_continue;
}
- /* Figure out how many times the loop will run based on the iteration count
- * annotations made by loop analysis, and give the loop a normative bound
- * if possible.
- */
- unsigned max_iterations =
- ls->max_iterations < 0 ? INT_MAX : ls->max_iterations;
-
- if (ir->normative_bound >= 0)
- max_iterations = ir->normative_bound;
-
- /* If the limiting terminator has a lower iteration count than we'd
- * previously inferred for this loop, then make the new iteration count the
- * normative bound for this loop.
- */
- if (ls->limiting_terminator != NULL &&
- (unsigned) ls->limiting_terminator->iterations < max_iterations) {
- ir->normative_bound = ls->limiting_terminator->iterations;
- max_iterations = ls->limiting_terminator->iterations;
+ if (ls->limiting_terminator != NULL) {
+ /* If the limiting terminator has an iteration count of zero, then we've
+ * proven that the loop cannot run, so delete it.
+ */
+ int iterations = ls->limiting_terminator->iterations;
+ if (iterations == 0) {
+ ir->remove();
+ this->progress = true;
+ return visit_continue;
+ }
}
/* Remove the conditional break statements associated with all terminators
- * that are associated with a fixed iteration count; the normative bound
- * will take care of terminating the loop.
+ * that are associated with a fixed iteration count, except for the one
+ * associated with the limiting terminator--that one needs to stay, since
+ * it terminates the loop. Exception: if the loop still has a normative
+ * bound, then that terminates the loop, so we don't even need the limiting
+ * terminator.
*/
- foreach_list(node, &ls->terminators) {
- loop_terminator *t = (loop_terminator *) node;
-
+ foreach_in_list(loop_terminator, t, &ls->terminators) {
if (t->iterations < 0)
continue;
- t->ir->remove();
+ if (t != ls->limiting_terminator) {
+ t->ir->remove();
- assert(ls->num_loop_jumps > 0);
- ls->num_loop_jumps--;
+ assert(ls->num_loop_jumps > 0);
+ ls->num_loop_jumps--;
- this->progress = true;
+ this->progress = true;
+ }
}
- /* If we have proven the one of the loop exit conditions is satisifed before
- * running the loop once, remove the loop.
- */
- if (max_iterations == 0)
- ir->remove();
- else
- ls->max_iterations = max_iterations;
-
return visit_continue;
}