summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth Graunke <kenneth@whitecape.org>2011-08-26 12:24:43 -0700
committerKenneth Graunke <kenneth@whitecape.org>2011-08-29 11:39:41 -0700
commitdc7f449d1ac53a66e6efb56ccf2a5953418a26ca (patch)
treedb651ac317ceb717e00fbef62a0a3f3d3dbb3982
parentd28a3bd4bf25157aff5379a003bbf4a66157ed06 (diff)
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 <kenneth@whitecape.org> Signed-off-by: Eric Anholt <eric@anholt.net>
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.h5
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_visitor.cpp43
2 files changed, 48 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index e22d3d31d7..a06949e9de 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 e054366a55..cc6c56983f 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);
}