From: Timothy Arceri Date: Tue, 5 Sep 2017 05:59:07 +0000 (+1000) Subject: glsl: don't drop instructions from unreachable terminators continue branch X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ab23b759f241a4e2247efa28bd28a5f20149c70b;p=mesa.git glsl: don't drop instructions from unreachable terminators continue branch These instructions will be executed on every iteration of the loop we cannot drop them. V2: - move removal of unreachable terminators from the terminator list to the same place they are removed from the IR as suggested by Nicolai. Reviewed-by: Nicolai Hähnle Tested-by: Dieter Nützel --- 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; } }