mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-21 13:40:16 +01:00
glsl: Refine the loop instruction counting.
Before, we were only counting top-level instructions. But if we have an assignment of a giant expression tree (such as the ones eventually generated by glsl-fs-unroll), we were counting the same as an assignment of a variable deref. glsl-fs-unroll-explosion now fails in a reasonable amount of time on i965 because the unrolling didn't go ridiculously far. Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
parent
7f1cbf12bc
commit
be5f27a84d
1 changed files with 35 additions and 11 deletions
|
|
@ -50,13 +50,44 @@ is_break(ir_instruction *ir)
|
|||
&& ((ir_loop_jump *) ir)->is_break();
|
||||
}
|
||||
|
||||
class loop_unroll_count : public ir_hierarchical_visitor {
|
||||
public:
|
||||
int nodes;
|
||||
bool fail;
|
||||
|
||||
loop_unroll_count(exec_list *list)
|
||||
{
|
||||
nodes = 0;
|
||||
fail = false;
|
||||
|
||||
run(list);
|
||||
}
|
||||
|
||||
virtual ir_visitor_status visit_enter(ir_assignment *ir)
|
||||
{
|
||||
nodes++;
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
virtual ir_visitor_status visit_enter(ir_expression *ir)
|
||||
{
|
||||
nodes++;
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
virtual ir_visitor_status visit_enter(ir_loop *ir)
|
||||
{
|
||||
fail = true;
|
||||
return visit_continue;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
ir_visitor_status
|
||||
loop_unroll_visitor::visit_leave(ir_loop *ir)
|
||||
{
|
||||
loop_variable_state *const ls = this->state->get(ir);
|
||||
int iterations;
|
||||
unsigned ir_count;
|
||||
|
||||
/* If we've entered a loop that hasn't been analyzed, something really,
|
||||
* really bad has happened.
|
||||
|
|
@ -81,17 +112,10 @@ loop_unroll_visitor::visit_leave(ir_loop *ir)
|
|||
|
||||
/* Don't try to unroll nested loops and loops with a huge body.
|
||||
*/
|
||||
ir_count = 0;
|
||||
foreach_list(node, &ir->body_instructions) {
|
||||
++ir_count;
|
||||
loop_unroll_count count(&ir->body_instructions);
|
||||
|
||||
/* If the loop body gets to huge, do not unroll. */
|
||||
if (5*max_iterations < ir_count*iterations)
|
||||
if (count.fail || count.nodes * iterations > (int)max_iterations * 5)
|
||||
return visit_continue;
|
||||
/* Do not unroll loops with child loop nodes. */
|
||||
if (((ir_instruction *) node)->as_loop())
|
||||
return visit_continue;
|
||||
}
|
||||
|
||||
if (ls->num_loop_jumps > 1)
|
||||
return visit_continue;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue