From dc7f449d1ac53a66e6efb56ccf2a5953418a26ca Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Fri, 26 Aug 2011 12:24:43 -0700 Subject: [PATCH] i965: Avoid generating MOVs for most ir_assignment handling. 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 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 Signed-off-by: Eric Anholt --- src/mesa/drivers/dri/i965/brw_fs.h | 5 +++ src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 43 ++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h index e22d3d31d76..a06949e9deb 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 e054366a558..cc6c56983fe 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp @@ -495,6 +495,42 @@ 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 || + last_rhs_inst->force_uncompressed || + last_rhs_inst->force_sechalf || + !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 +541,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); }