Mesa (master): i965: Be more aggressive in tracking live/ dead intervals within loops.

Eric Anholt anholt at kemper.freedesktop.org
Thu Oct 21 23:55:57 UTC 2010


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

Author: Eric Anholt <eric at anholt.net>
Date:   Thu Oct 21 16:54:03 2010 -0700

i965: Be more aggressive in tracking live/dead intervals within loops.

Fixes glsl-fs-convolution-2, which was blowing up due to the array
access insanity getting at the uniform values within the loop.  Each
temporary was considered live across the whole loop.

---

 src/mesa/drivers/dri/i965/brw_fs.cpp |   54 +++++++++++++++++++++++++--------
 1 files changed, 41 insertions(+), 13 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index aa945c9..174f622 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -2441,6 +2441,7 @@ fs_visitor::calculate_live_intervals()
    int *use = talloc_array(mem_ctx, int, num_vars);
    int loop_depth = 0;
    int loop_start = 0;
+   int bb_header_ip = 0;
 
    for (int i = 0; i < num_vars; i++) {
       def[i] = 1 << 30;
@@ -2458,12 +2459,8 @@ fs_visitor::calculate_live_intervals()
 	 loop_depth--;
 
 	 if (loop_depth == 0) {
-	    /* FINISHME:
-	     *
-	     * Patches up any vars marked for use within the loop as
-	     * live until the end.  This is conservative, as there
-	     * will often be variables defined and used inside the
-	     * loop but dead at the end of the loop body.
+	    /* Patches up the use of vars marked for being live across
+	     * the whole loop.
 	     */
 	    for (int i = 0; i < num_vars; i++) {
 	       if (use[i] == loop_start) {
@@ -2472,22 +2469,53 @@ fs_visitor::calculate_live_intervals()
 	    }
 	 }
       } else {
-	 int eip = ip;
-
-	 if (loop_depth)
-	    eip = loop_start;
-
 	 for (unsigned int i = 0; i < 3; i++) {
 	    if (inst->src[i].file == GRF && inst->src[i].reg != 0) {
-	       use[inst->src[i].reg] = MAX2(use[inst->src[i].reg], eip);
+	       int reg = inst->src[i].reg;
+
+	       if (!loop_depth || (this->virtual_grf_sizes[reg] == 1 &&
+				   def[reg] >= bb_header_ip)) {
+		  use[reg] = ip;
+	       } else {
+		  def[reg] = MIN2(loop_start, def[reg]);
+		  use[reg] = loop_start;
+
+		  /* Nobody else is going to go smash our start to
+		   * later in the loop now, because def[reg] now
+		   * points before the bb header.
+		   */
+	       }
 	    }
 	 }
 	 if (inst->dst.file == GRF && inst->dst.reg != 0) {
-	    def[inst->dst.reg] = MIN2(def[inst->dst.reg], eip);
+	    int reg = inst->dst.reg;
+
+	    if (!loop_depth || (this->virtual_grf_sizes[reg] == 1 &&
+				!inst->predicated)) {
+	       def[reg] = MIN2(def[reg], ip);
+	    } else {
+	       def[reg] = MIN2(def[reg], loop_start);
+	    }
 	 }
       }
 
       ip++;
+
+      /* Set the basic block header IP.  This is used for determining
+       * if a complete def of single-register virtual GRF in a loop
+       * dominates a use in the same basic block.  It's a quick way to
+       * reduce the live interval range of most register used in a
+       * loop.
+       */
+      if (inst->opcode == BRW_OPCODE_IF ||
+	  inst->opcode == BRW_OPCODE_ELSE ||
+	  inst->opcode == BRW_OPCODE_ENDIF ||
+	  inst->opcode == BRW_OPCODE_DO ||
+	  inst->opcode == BRW_OPCODE_WHILE ||
+	  inst->opcode == BRW_OPCODE_BREAK ||
+	  inst->opcode == BRW_OPCODE_CONTINUE) {
+	 bb_header_ip = ip;
+      }
    }
 
    talloc_free(this->virtual_grf_def);




More information about the mesa-commit mailing list