mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-21 15:50:11 +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();
|
&& ((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
|
ir_visitor_status
|
||||||
loop_unroll_visitor::visit_leave(ir_loop *ir)
|
loop_unroll_visitor::visit_leave(ir_loop *ir)
|
||||||
{
|
{
|
||||||
loop_variable_state *const ls = this->state->get(ir);
|
loop_variable_state *const ls = this->state->get(ir);
|
||||||
int iterations;
|
int iterations;
|
||||||
unsigned ir_count;
|
|
||||||
|
|
||||||
/* If we've entered a loop that hasn't been analyzed, something really,
|
/* If we've entered a loop that hasn't been analyzed, something really,
|
||||||
* really bad has happened.
|
* 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.
|
/* Don't try to unroll nested loops and loops with a huge body.
|
||||||
*/
|
*/
|
||||||
ir_count = 0;
|
loop_unroll_count count(&ir->body_instructions);
|
||||||
foreach_list(node, &ir->body_instructions) {
|
|
||||||
++ir_count;
|
|
||||||
|
|
||||||
/* If the loop body gets to huge, do not unroll. */
|
if (count.fail || count.nodes * iterations > (int)max_iterations * 5)
|
||||||
if (5*max_iterations < ir_count*iterations)
|
return visit_continue;
|
||||||
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)
|
if (ls->num_loop_jumps > 1)
|
||||||
return visit_continue;
|
return visit_continue;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue