This is a port of vec4_visitor::try_rewrite_rhs_to_dst to fs_visitor. Not only is this technique less invasive and more robust, it also generates better code. Over and above the previous technique, this reduced instruction count in shader-db:
With all FS optimizations (register coalescing and such) disabled, this reduced instruction count by 6.23% on average and 36% in the best case. With optimizations left enabled, it still reduced instruction count by 0.28% on average and 1.4% in the best case. In no case did this technique result in more code than the prior method. Signed-off-by: Kenneth Graunke <kenn...@whitecape.org> --- src/mesa/drivers/dri/i965/brw_fs.h | 5 +++ src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 40 ++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 0 deletions(-) Tested for piglit regressions on Sandybridge GT2. None to be found. diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h index e22d3d3..a06949e 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.h +++ b/src/mesa/drivers/dri/i965/brw_fs.h @@ -515,6 +515,11 @@ public: void emit_color_write(int index, int first_color_mrf, fs_reg color); void emit_fb_writes(); + bool try_rewrite_rhs_to_dst(ir_assignment *ir, + fs_reg dst, + fs_reg src, + fs_inst *pre_rhs_inst, + fs_inst *last_rhs_inst); void emit_assignment_writes(fs_reg &l, fs_reg &r, const glsl_type *type, bool predicated); diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp index e054366..4418f58 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp @@ -495,6 +495,39 @@ fs_visitor::emit_assignment_writes(fs_reg &l, fs_reg &r, } } +/* If the RHS processing resulted in an instruction generating a + * temporary value, and it would be easy to rewrite the instruction to + * generate its result right into the LHS instead, do so. This ends + * up reliably removing instructions where it can be tricky to do so + * later without real UD chain information. + */ +bool +fs_visitor::try_rewrite_rhs_to_dst(ir_assignment *ir, + fs_reg dst, + fs_reg src, + fs_inst *pre_rhs_inst, + fs_inst *last_rhs_inst) +{ + if (pre_rhs_inst == last_rhs_inst) + return false; /* No instructions generated to work with. */ + + /* Only attempt if we're doing a direct assignment. */ + if (ir->condition || + !(ir->lhs->type->is_scalar() || + (ir->lhs->type->is_vector() && + ir->write_mask == (1 << ir->lhs->type->vector_elements) - 1))) + return false; + + /* Make sure the last instruction generated our source reg. */ + if (last_rhs_inst->predicated || !src.equals(&last_rhs_inst->dst)) + return false; + + /* Success! Rewrite the instruction. */ + last_rhs_inst->dst = dst; + + return true; +} + void fs_visitor::visit(ir_assignment *ir) { @@ -505,12 +538,19 @@ fs_visitor::visit(ir_assignment *ir) ir->lhs->accept(this); l = this->result; + fs_inst *pre_rhs_inst = (fs_inst *) this->instructions.get_tail(); + ir->rhs->accept(this); r = this->result; + fs_inst *last_rhs_inst = (fs_inst *) this->instructions.get_tail(); + assert(l.file != BAD_FILE); assert(r.file != BAD_FILE); + if (try_rewrite_rhs_to_dst(ir, l, r, pre_rhs_inst, last_rhs_inst)) + return; + if (ir->condition) { emit_bool_to_cond_code(ir->condition); } -- 1.7.6 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev