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. --- src/compiler/glsl/loop_analysis.h | 7 +++++++ 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 8f82404694..99b6bf7563 100644 --- a/src/compiler/glsl/loop_analysis.h +++ b/src/compiler/glsl/loop_analysis.h @@ -27,20 +27,27 @@ #include "ir.h" #include "util/hash_table.h" /** * Analyze and classify all variables used in all loops in the instruction list */ 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, const struct gl_shader_compiler_options *options); /** * Tracking for all variables used in a loop */ class loop_variable_state : public exec_node { diff --git a/src/compiler/glsl/loop_unroll.cpp b/src/compiler/glsl/loop_unroll.cpp index 7eea439454..358cbf10af 100644 --- a/src/compiler/glsl/loop_unroll.cpp +++ b/src/compiler/glsl/loop_unroll.cpp @@ -46,27 +46,20 @@ public: void splice_post_if_instructions(ir_if *ir_if, exec_list *splice_dest); loop_state *state; bool progress; const struct gl_shader_compiler_options *options; }; } /* 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; bool unsupported_variable_indexing; bool array_indexed_by_induction_var_with_exact_iterations; /* If there are nested loops, the node count will be inaccurate. */ bool nested_loop; loop_unroll_count(exec_list *list, loop_variable_state *ls, const struct gl_shader_compiler_options *options) @@ -326,30 +319,49 @@ loop_unroll_visitor::visit_leave(ir_loop *ir) } } /* Remove the conditional break statements associated with all terminators * that are associated with a fixed iteration count, except for the one * associated with the limiting terminator--that one needs to stay, since * it terminates the loop. Exception: if the loop still has a normative * 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; } } if (ls->limiting_terminator == NULL) { ir_instruction *last_ir = (ir_instruction *) ir->body_instructions.get_tail(); /* If a loop has no induction variable and the last instruction is * a break, unroll the loop with a count of 1. This is the classic -- 2.13.5 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev