Mesa (master): i965: Avoid generating MOVs for most ir_assignment handling.

Kenneth Graunke kwg at kemper.freedesktop.org
Mon Aug 29 11:40:29 PDT 2011


Module: Mesa
Branch: master
Commit: dc7f449d1ac53a66e6efb56ccf2a5953418a26ca
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=dc7f449d1ac53a66e6efb56ccf2a5953418a26ca

Author: Kenneth Graunke <kenneth at whitecape.org>
Date:   Fri Aug 26 12:24:43 2011 -0700

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 at whitecape.org>
Signed-off-by: Eric Anholt <eric at anholt.net>

---

 src/mesa/drivers/dri/i965/brw_fs.h           |    5 +++
 src/mesa/drivers/dri/i965/brw_fs_visitor.cpp |   43 ++++++++++++++++++++++++++
 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 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..cc6c569 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);
    }



More information about the mesa-commit mailing list