diff options
-rw-r--r-- | src/compiler/glsl/loop_analysis.h | 7 | ||||
-rw-r--r-- | src/compiler/glsl/loop_unroll.cpp | 28 |
2 files changed, 27 insertions, 8 deletions
diff --git a/src/compiler/glsl/loop_analysis.h b/src/compiler/glsl/loop_analysis.h index 8f824046945..99b6bf75638 100644 --- a/src/compiler/glsl/loop_analysis.h +++ b/src/compiler/glsl/loop_analysis.h @@ -34,6 +34,13 @@ extern class loop_state * analyze_loop_variables(exec_list *instructions); +static inline bool +is_break(ir_instruction *ir) +{ + return ir != NULL && ir->ir_type == ir_type_loop_jump && + ((ir_loop_jump *) ir)->is_break(); +} + extern bool unroll_loops(exec_list *instructions, loop_state *ls, diff --git a/src/compiler/glsl/loop_unroll.cpp b/src/compiler/glsl/loop_unroll.cpp index 7eea439454b..358cbf10af4 100644 --- a/src/compiler/glsl/loop_unroll.cpp +++ b/src/compiler/glsl/loop_unroll.cpp @@ -53,13 +53,6 @@ public: } /* anonymous namespace */ -static bool -is_break(ir_instruction *ir) -{ - return ir != NULL && ir->ir_type == ir_type_loop_jump - && ((ir_loop_jump *) ir)->is_break(); -} - class loop_unroll_count : public ir_hierarchical_visitor { public: int nodes; @@ -333,16 +326,35 @@ loop_unroll_visitor::visit_leave(ir_loop *ir) * bound, then that terminates the loop, so we don't even need the limiting * terminator. */ - foreach_in_list(loop_terminator, t, &ls->terminators) { + foreach_in_list_safe(loop_terminator, t, &ls->terminators) { if (t->iterations < 0) continue; + exec_list *branch_instructions; if (t != ls->limiting_terminator) { + ir_instruction *ir_if_last = (ir_instruction *) + t->ir->then_instructions.get_tail(); + if (is_break(ir_if_last)) { + branch_instructions = &t->ir->else_instructions; + } else { + branch_instructions = &t->ir->then_instructions; + assert(is_break((ir_instruction *) + t->ir->else_instructions.get_tail())); + } + + exec_list copy_list; + copy_list.make_empty(); + clone_ir_list(ir, ©_list, branch_instructions); + + t->ir->insert_before(©_list); t->ir->remove(); assert(ls->num_loop_jumps > 0); ls->num_loop_jumps--; + /* Also remove it from the terminator list */ + t->remove(); + this->progress = true; } } |