summaryrefslogtreecommitdiffstats
path: root/src/glsl/loop_controls.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/glsl/loop_controls.cpp')
-rw-r--r--src/glsl/loop_controls.cpp106
1 files changed, 26 insertions, 80 deletions
diff --git a/src/glsl/loop_controls.cpp b/src/glsl/loop_controls.cpp
index ce05e09a6ab..a14ea6ba6be 100644
--- a/src/glsl/loop_controls.cpp
+++ b/src/glsl/loop_controls.cpp
@@ -183,9 +183,9 @@ loop_control_visitor::visit_leave(ir_loop *ir)
return visit_continue;
}
- /* Search the loop terminating conditions for one of the form 'i < c' where
- * i is a loop induction variable, c is a constant, and < is any relative
- * operator.
+ /* 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;
@@ -193,86 +193,32 @@ loop_control_visitor::visit_leave(ir_loop *ir)
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;
+ }
+
+ /* 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.
+ */
foreach_list(node, &ls->terminators) {
loop_terminator *t = (loop_terminator *) node;
- ir_if *if_stmt = t->ir;
-
- /* If-statements can be either 'if (expr)' or 'if (deref)'. We only care
- * about the former here.
- */
- ir_expression *cond = if_stmt->condition->as_expression();
- if (cond == NULL)
- continue;
-
- switch (cond->operation) {
- case ir_binop_less:
- case ir_binop_greater:
- case ir_binop_lequal:
- case ir_binop_gequal: {
- /* The expressions that we care about will either be of the form
- * 'counter < limit' or 'limit < counter'. Figure out which is
- * which.
- */
- ir_rvalue *counter = cond->operands[0]->as_dereference_variable();
- ir_constant *limit = cond->operands[1]->as_constant();
- enum ir_expression_operation cmp = cond->operation;
-
- if (limit == NULL) {
- counter = cond->operands[1]->as_dereference_variable();
- limit = cond->operands[0]->as_constant();
-
- switch (cmp) {
- case ir_binop_less: cmp = ir_binop_greater; break;
- case ir_binop_greater: cmp = ir_binop_less; break;
- case ir_binop_lequal: cmp = ir_binop_gequal; break;
- case ir_binop_gequal: cmp = ir_binop_lequal; break;
- default: assert(!"Should not get here.");
- }
- }
-
- if ((counter == NULL) || (limit == NULL))
- break;
-
- ir_variable *var = counter->variable_referenced();
-
- ir_rvalue *init = find_initial_value(ir, var);
-
- loop_variable *lv = ls->get(var);
- if (lv != NULL && lv->is_induction_var()) {
- const int iterations = calculate_iterations(init, limit,
- lv->increment,
- cmp);
- if (iterations >= 0) {
- /* If the new iteration count is lower than the previously
- * believed iteration count, then add a normative bound to
- * this loop.
- */
- if ((unsigned) iterations < max_iterations) {
- ir->normative_bound = iterations;
-
- max_iterations = iterations;
- }
-
- /* Remove the conditional break statement. The loop
- * controls are now set such that the exit condition will be
- * satisfied.
- */
- if_stmt->remove();
-
- assert(ls->num_loop_jumps > 0);
- ls->num_loop_jumps--;
-
- this->progress = true;
- }
-
- break;
- }
- break;
- }
- default:
- break;
- }
+ if (t->iterations < 0)
+ continue;
+
+ t->ir->remove();
+
+ assert(ls->num_loop_jumps > 0);
+ ls->num_loop_jumps--;
+
+ this->progress = true;
}
/* If we have proven the one of the loop exit conditions is satisifed before