X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Fopt_if_simplification.cpp;h=db59b131dbc219ad3c61d45fc1e8a81ed2a713bf;hb=f25d94084ce3225e803c07672c359a4e553b0e08;hp=618bacfecf17ea2a6cc4666af2bdfa67a207e64d;hpb=df883eb1575a740bf91e01cbe2eaa4dbc1f9f154;p=mesa.git diff --git a/src/glsl/opt_if_simplification.cpp b/src/glsl/opt_if_simplification.cpp index 618bacfecf1..db59b131dbc 100644 --- a/src/glsl/opt_if_simplification.cpp +++ b/src/glsl/opt_if_simplification.cpp @@ -25,11 +25,14 @@ * \file opt_if_simplification.cpp * * Moves constant branches of if statements out to the surrounding - * instruction stream. + * instruction stream, and inverts if conditionals to avoid empty + * "then" blocks. */ #include "ir.h" +namespace { + class ir_if_simplification_visitor : public ir_hierarchical_visitor { public: ir_if_simplification_visitor() @@ -38,10 +41,23 @@ public: } ir_visitor_status visit_leave(ir_if *); + ir_visitor_status visit_enter(ir_assignment *); bool made_progress; }; +} /* unnamed namespace */ + +/* We only care about the top level "if" instructions, so don't + * descend into expressions. + */ +ir_visitor_status +ir_if_simplification_visitor::visit_enter(ir_assignment *ir) +{ + (void) ir; + return visit_continue_with_parent; +} + bool do_if_simplification(exec_list *instructions) { @@ -55,6 +71,14 @@ do_if_simplification(exec_list *instructions) ir_visitor_status ir_if_simplification_visitor::visit_leave(ir_if *ir) { + /* If the if statement has nothing on either side, remove it. */ + if (ir->then_instructions.is_empty() && + ir->else_instructions.is_empty()) { + ir->remove(); + this->made_progress = true; + return visit_continue; + } + /* FINISHME: Ideally there would be a way to note that the condition results * FINISHME: in a constant before processing both of the other subtrees. * FINISHME: This can probably be done with some flags, but it would take @@ -78,6 +102,30 @@ ir_if_simplification_visitor::visit_leave(ir_if *ir) } ir->remove(); this->made_progress = true; + return visit_continue; + } + + /* Turn: + * + * if (cond) { + * } else { + * do_work(); + * } + * + * into : + * + * if (!cond) + * do_work(); + * + * which avoids control flow for "else" (which is usually more + * expensive than normal operations), and the "not" can usually be + * folded into the generation of "cond" anyway. + */ + if (ir->then_instructions.is_empty()) { + ir->condition = new(ralloc_parent(ir->condition)) + ir_expression(ir_unop_logic_not, ir->condition); + ir->else_instructions.move_nodes_to(&ir->then_instructions); + this->made_progress = true; } return visit_continue;