diff options
author | Paul Berry <[email protected]> | 2013-11-28 14:40:19 -0800 |
---|---|---|
committer | Paul Berry <[email protected]> | 2013-12-09 10:54:56 -0800 |
commit | ffc29120c402551fe9a7fa36e8ee5476bad27738 (patch) | |
tree | 5ec4ccaa2c464f9f60c938eeacdaf70b7c6a61d4 /src/glsl/loop_controls.cpp | |
parent | 4bbf6d1d2b20bccd784a326f33bdb860032db361 (diff) |
glsl/loops: Move some analysis from loop_controls to loop_analysis.
Previously, the sole responsibility of loop_analysis was to find all
the variables referenced in the loop that are either loop constant or
induction variables, and find all of the simple if statements that
might terminate the loop. The remainder of the analysis necessary to
determine how many times a loop executed was performed by
loop_controls.
This patch makes loop_analysis also responsible for determining the
number of iterations after which each loop terminator will terminate
the loop, and for figuring out which terminator will terminate the
loop first (I'm calling this the "limiting terminator").
This will allow loop unrolling to make use of information that was
previously only visible from loop_controls, namely the identity of the
limiting terminator.
Reviewed-by: Ian Romanick <[email protected]>
Diffstat (limited to 'src/glsl/loop_controls.cpp')
-rw-r--r-- | src/glsl/loop_controls.cpp | 106 |
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 |