diff options
Diffstat (limited to 'src/compiler/glsl/loop_analysis.cpp')
-rw-r--r-- | src/compiler/glsl/loop_analysis.cpp | 53 |
1 files changed, 25 insertions, 28 deletions
diff --git a/src/compiler/glsl/loop_analysis.cpp b/src/compiler/glsl/loop_analysis.cpp index 78279844dc8..2979e09433f 100644 --- a/src/compiler/glsl/loop_analysis.cpp +++ b/src/compiler/glsl/loop_analysis.cpp @@ -25,7 +25,7 @@ #include "loop_analysis.h" #include "ir_hierarchical_visitor.h" -static bool is_loop_terminator(ir_if *ir); +static void try_add_loop_terminator(loop_variable_state *ls, ir_if *ir); static bool all_expression_operands_are_loop_constant(ir_rvalue *, hash_table *); @@ -87,7 +87,7 @@ find_initial_value(ir_loop *loop, ir_variable *var) static int calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment, - enum ir_expression_operation op) + enum ir_expression_operation op, bool continue_from_then) { if (from == NULL || to == NULL || increment == NULL) return -1; @@ -154,8 +154,10 @@ calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment, ir_expression *const add = new(mem_ctx) ir_expression(ir_binop_add, mul->type, mul, from); - ir_expression *const cmp = + ir_expression *cmp = new(mem_ctx) ir_expression(op, glsl_type::bool_type, add, to); + if (continue_from_then) + cmp = new(mem_ctx) ir_expression(ir_unop_logic_not, cmp); ir_constant *const cmp_result = cmp->constant_expression_value(mem_ctx); @@ -306,12 +308,14 @@ loop_variable_state::insert(ir_variable *var) loop_terminator * -loop_variable_state::insert(ir_if *if_stmt) +loop_variable_state::insert(ir_if *if_stmt, bool continue_from_then) { void *mem_ctx = ralloc_parent(this); loop_terminator *t = new(mem_ctx) loop_terminator(); t->ir = if_stmt; + t->continue_from_then = continue_from_then; + this->terminators.push_tail(t); return t; @@ -468,10 +472,8 @@ loop_analysis::visit_leave(ir_loop *ir) ir_if *if_stmt = ((ir_instruction *) node)->as_if(); - if ((if_stmt != NULL) && is_loop_terminator(if_stmt)) - ls->insert(if_stmt); - else - break; + if (if_stmt != NULL) + try_add_loop_terminator(ls, if_stmt); } @@ -614,7 +616,7 @@ loop_analysis::visit_leave(ir_loop *ir) loop_variable *lv = ls->get(var); if (lv != NULL && lv->is_induction_var()) { t->iterations = calculate_iterations(init, limit, lv->increment, - cmp); + cmp, t->continue_from_then); if (incremented_before_terminator(ir, var, t->ir)) { t->iterations--; @@ -781,31 +783,26 @@ get_basic_induction_increment(ir_assignment *ir, hash_table *var_hash) /** - * Detect whether an if-statement is a loop terminating condition + * Detect whether an if-statement is a loop terminating condition, if so + * add it to the list of loop terminators. * * Detects if-statements of the form * - * (if (expression bool ...) (break)) + * (if (expression bool ...) (...then_instrs...break)) + * + * or + * + * (if (expression bool ...) ... (...else_instrs...break)) */ -bool -is_loop_terminator(ir_if *ir) +void +try_add_loop_terminator(loop_variable_state *ls, ir_if *ir) { - if (!ir->else_instructions.is_empty()) - return false; - - ir_instruction *const inst = - (ir_instruction *) ir->then_instructions.get_head(); - if (inst == NULL) - return false; - - if (inst->ir_type != ir_type_loop_jump) - return false; - - ir_loop_jump *const jump = (ir_loop_jump *) inst; - if (jump->mode != ir_loop_jump::jump_break) - return false; + ir_instruction *inst = (ir_instruction *) ir->then_instructions.get_tail(); + ir_instruction *else_inst = + (ir_instruction *) ir->else_instructions.get_tail(); - return true; + if (is_break(inst) || is_break(else_inst)) + ls->insert(ir, is_break(else_inst)); } |