On 01/16/2015 08:15 AM, Matt Turner wrote: > From: Ian Romanick <ian.d.roman...@intel.com> > > Some shaders end up with code that looks something like: > > if (some_condition) > result = 1.0; > else > result = 0.0; > > This pass converts those if-statements to > > result = float(some_condition); > > total instructions in shared programs: 5934568 -> 5921818 (-0.21%) > instructions in affected programs: 723433 -> 710683 (-1.76%) > GAINED: 26 > LOST: 7
I was getting really different results here... on my more recent version (that should produce the same IR), I was getting basically the reverse lost / gained. The other results were about the same. I updated both Mesa and shader-db, and I'm not able to do a full shader-db run now. At semi-arbitrary points in the run I get Exception: Only shader 0 found. shaders/closed/unreal4/sun-temple/180.shader_test If I run that shader_test by hand, I get multiple shader emitted. I'm using the older run.py... is it possible that's broken? Anyway... I pushed an updated branch as bool-optimizations-v2. I was trying to get results on 33619be and bab3b1d. I know the latter duplicates one of the NIR optimizations, but with the former patch it gave some nice gains. > 12 vertex shaders contain loops that we were now able to unroll. > Since their instruction count deltas are not representative of this > change, I've removed them from the stats. > > Reviewed-by: Matt Turner <matts...@gmail.com> > --- > idr: Want to put an S-o-b on this? > > src/glsl/Makefile.sources | 1 + > src/glsl/glsl_parser_extras.cpp | 1 + > src/glsl/ir_optimization.h | 1 + > src/glsl/opt_if_to_bool_cast.cpp | 178 > +++++++++++++++++++++++++++++++++++++++ > 4 files changed, 181 insertions(+) > create mode 100644 src/glsl/opt_if_to_bool_cast.cpp > > diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources > index 006e947..61de09b 100644 > --- a/src/glsl/Makefile.sources > +++ b/src/glsl/Makefile.sources > @@ -162,6 +162,7 @@ LIBGLSL_FILES = \ > $(GLSL_SRCDIR)/opt_flip_matrices.cpp \ > $(GLSL_SRCDIR)/opt_function_inlining.cpp \ > $(GLSL_SRCDIR)/opt_if_simplification.cpp \ > + $(GLSL_SRCDIR)/opt_if_to_bool_cast.cpp \ > $(GLSL_SRCDIR)/opt_minmax.cpp \ > $(GLSL_SRCDIR)/opt_noop_swizzle.cpp \ > $(GLSL_SRCDIR)/opt_rebalance_tree.cpp \ > diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp > index 6d18cd4..c96b6c9 100644 > --- a/src/glsl/glsl_parser_extras.cpp > +++ b/src/glsl/glsl_parser_extras.cpp > @@ -1603,6 +1603,7 @@ do_common_optimization(exec_list *ir, bool linked, > progress = do_structure_splitting(ir) || progress; > } > progress = do_if_simplification(ir) || progress; > + progress = optimize_if_to_bool_cast(ir) || progress; > progress = opt_flatten_nested_if_blocks(ir) || progress; > progress = do_copy_propagation(ir) || progress; > progress = do_copy_propagation_elements(ir) || progress; > diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h > index 34e0b4b..4dbbd7c 100644 > --- a/src/glsl/ir_optimization.h > +++ b/src/glsl/ir_optimization.h > @@ -131,6 +131,7 @@ void optimize_dead_builtin_variables(exec_list > *instructions, > enum ir_variable_mode other); > > bool lower_vertex_id(gl_shader *shader); > +bool optimize_if_to_bool_cast(exec_list *instructions); > > ir_rvalue * > compare_index_block(exec_list *instructions, ir_variable *index, > diff --git a/src/glsl/opt_if_to_bool_cast.cpp > b/src/glsl/opt_if_to_bool_cast.cpp > new file mode 100644 > index 0000000..32c1f99 > --- /dev/null > +++ b/src/glsl/opt_if_to_bool_cast.cpp > @@ -0,0 +1,178 @@ > +/* > + * Copyright © 2014 Intel Corporation > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the next > + * paragraph) shall be included in all copies or substantial portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER > + * DEALINGS IN THE SOFTWARE. > + */ > + > +/** > + * \file opt_if_to_bool_cast.cpp > + * Optimize certain if-statements to just casts from the condition > + * > + * Some shaders end up with code that looks something like: > + * > + * if (some_condition) > + * result = 1.0; > + * else > + * result = 0.0; > + * > + * This pass converts those if-statements to > + * > + * result = float(some_condition); > + */ > + > +#include "main/imports.h" > +#include "ir.h" > +#include "ir_builder.h" > +#include "program/prog_instruction.h" > + > +using namespace ir_builder; > + > +namespace { > + > +class ir_if_to_bool_cast_visitor : public ir_hierarchical_visitor { > +public: > + ir_if_to_bool_cast_visitor() > + : progress(false) > + { > + /* empty */ > + } > + > + ir_visitor_status visit_leave(ir_if *); > + > + bool progress; > +}; > + > +} /* unnamed namespace */ > + > +bool > +optimize_if_to_bool_cast(exec_list *instructions) > +{ > + ir_if_to_bool_cast_visitor v; > + > + v.run(instructions); > + return v.progress; > +} > + > +ir_visitor_status > +ir_if_to_bool_cast_visitor::visit_leave(ir_if *ir) > +{ > + /* Both the then-block and the else-block must contain a single > instruction > + * that is an assignment. > + */ > + ir_instruction *const then_inst = > + (ir_instruction *) ir->then_instructions.get_head(); > + if (then_inst == NULL > + || !then_inst->next->is_tail_sentinel() > + || then_inst->ir_type != ir_type_assignment) > + return visit_continue; > + > + ir_instruction *const else_inst = > + (ir_instruction *) ir->else_instructions.get_head(); > + if (else_inst == NULL > + || !else_inst->next->is_tail_sentinel() > + || else_inst->ir_type != ir_type_assignment) > + return visit_continue; > + > + /* That assignment must have the same write-mask and have the same LHS. > + */ > + ir_assignment *const then_assign = then_inst->as_assignment(); > + ir_assignment *const else_assign = else_inst->as_assignment(); > + > + assert(then_assign != NULL); > + assert(else_assign != NULL); > + > + if (then_assign->write_mask != else_assign->write_mask > + || then_assign->condition != NULL > + || else_assign->condition != NULL) > + return visit_continue; > + > + if (!then_assign->lhs->equals(else_assign->lhs)) > + return visit_continue; > + > + /* The RHS of the then-assignment must be 1, and the RHS of the > + * else-assignment must be 0. Or vice-versa. > + */ > + ir_constant *const then_rhs = then_assign->rhs->as_constant(); > + ir_constant *const else_rhs = else_assign->rhs->as_constant(); > + > + if (then_rhs == NULL || else_rhs == NULL) > + return visit_continue; > + > + if (then_rhs->is_zero()) { > + if (!else_rhs->is_one() && !else_rhs->is_negative_one()) > + return visit_continue; > + } else if (else_rhs->is_zero()) { > + if (!then_rhs->is_one() && !then_rhs->is_negative_one()) > + return visit_continue; > + } else { > + return visit_continue; > + } > + > + /* Generate the RHS of the new assignment. Note that if the old code > + * looked like > + * > + * x = (cond) ? 0.0 : 1.0; > + * > + * we have to generate > + * > + * x = float(!cond); > + */ > + ir_rvalue *const cond = then_rhs->is_zero() > + ? logic_not(ir->condition) : ir->condition; > + > + ir_rvalue *rhs = NULL; > + > + switch (then_rhs->type->base_type) { > + case GLSL_TYPE_UINT: > + rhs = i2u(b2i(cond)); > + break; > + case GLSL_TYPE_INT: > + rhs = b2i(cond); > + break; > + case GLSL_TYPE_FLOAT: > + rhs = b2f(cond); > + break; > + case GLSL_TYPE_BOOL: > + rhs = cond; > + break; > + default: > + unreachable("invalid base type"); > + } > + > + /* If the non-zero value was -1, negate the result of the b2[uif] > + * operation. > + */ > + if (then_rhs->is_negative_one() || else_rhs->is_negative_one()) > + rhs = neg(rhs); > + > + const unsigned size = _mesa_bitcount(then_assign->write_mask); > + > + assert(size >= 1 && size <= 4); > + > + ir_assignment *const a = assign(then_assign->lhs, > + swizzle(rhs, SWIZZLE_XXXX, size), > + then_assign->write_mask); > + > + ir->insert_before(a); > + ir->remove(); > + progress = true; > + > + return visit_continue; > + } > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev