i965: Improve compute-to-mrf.
authorEric Anholt <eric@anholt.net>
Thu, 18 Nov 2010 07:03:50 +0000 (15:03 +0800)
committerEric Anholt <eric@anholt.net>
Sat, 20 Nov 2010 03:54:11 +0000 (19:54 -0800)
We were skipping it if the instruction producing the value we were
going to compute-to-mrf used its result reg as a source reg.  This
meant that the typical "write interpolated color to fragment color" or
"texture from interpolated texcoord" shader didn't compute-to-MRF.
Just don't check for the interference cases until after we've checked
if this is the instruction we wanted to compute-to-MRF.

Improves nexuiz high-settings performance on my laptop 0.48% +- 0.08%
(n=3).

src/mesa/drivers/dri/i965/brw_fs.cpp

index 1b2989f46ec3ea0471cc11a6adbd5d6c68b64b9a..76794fa414b81ef119194dc8a866eecfac62019f 100644 (file)
@@ -2963,55 +2963,10 @@ fs_visitor::compute_to_mrf()
       /* Found a move of a GRF to a MRF.  Let's see if we can go
        * rewrite the thing that made this GRF to write into the MRF.
        */
-      bool found = false;
       fs_inst *scan_inst;
       for (scan_inst = (fs_inst *)inst->prev;
           scan_inst->prev != NULL;
           scan_inst = (fs_inst *)scan_inst->prev) {
-        /* We don't handle flow control here.  Most computation of
-         * values that end up in MRFs are shortly before the MRF
-         * write anyway.
-         */
-        if (scan_inst->opcode == BRW_OPCODE_DO ||
-            scan_inst->opcode == BRW_OPCODE_WHILE ||
-            scan_inst->opcode == BRW_OPCODE_ENDIF) {
-           break;
-        }
-
-        /* You can't read from an MRF, so if someone else reads our
-         * MRF's source GRF that we wanted to rewrite, that stops us.
-         */
-        bool interfered = false;
-        for (int i = 0; i < 3; i++) {
-           if (scan_inst->src[i].file == GRF &&
-               scan_inst->src[i].reg == inst->src[0].reg &&
-               scan_inst->src[i].reg_offset == inst->src[0].reg_offset) {
-              interfered = true;
-           }
-        }
-        if (interfered)
-           break;
-
-        if (scan_inst->dst.file == MRF &&
-            scan_inst->dst.hw_reg == inst->dst.hw_reg) {
-           /* Somebody else wrote our MRF here, so we can't can't
-            * compute-to-MRF before that.
-            */
-           break;
-        }
-
-        if (scan_inst->mlen > 0) {
-           /* Found a SEND instruction, which means that there are
-            * live values in MRFs from base_mrf to base_mrf +
-            * scan_inst->mlen - 1.  Don't go pushing our MRF write up
-            * above it.
-            */
-           if (inst->dst.hw_reg >= scan_inst->base_mrf &&
-               inst->dst.hw_reg < scan_inst->base_mrf + scan_inst->mlen) {
-              break;
-           }
-        }
-
         if (scan_inst->dst.file == GRF &&
             scan_inst->dst.reg == inst->src[0].reg) {
            /* Found the last thing to write our reg we want to turn
@@ -3053,18 +3008,59 @@ fs_visitor::compute_to_mrf()
 
            if (scan_inst->dst.reg_offset == inst->src[0].reg_offset) {
               /* Found the creator of our MRF's source value. */
-              found = true;
+              scan_inst->dst.file = MRF;
+              scan_inst->dst.hw_reg = inst->dst.hw_reg;
+              scan_inst->saturate |= inst->saturate;
+              inst->remove();
+              progress = true;
+           }
+           break;
+        }
+
+        /* We don't handle flow control here.  Most computation of
+         * values that end up in MRFs are shortly before the MRF
+         * write anyway.
+         */
+        if (scan_inst->opcode == BRW_OPCODE_DO ||
+            scan_inst->opcode == BRW_OPCODE_WHILE ||
+            scan_inst->opcode == BRW_OPCODE_ENDIF) {
+           break;
+        }
+
+        /* You can't read from an MRF, so if someone else reads our
+         * MRF's source GRF that we wanted to rewrite, that stops us.
+         */
+        bool interfered = false;
+        for (int i = 0; i < 3; i++) {
+           if (scan_inst->src[i].file == GRF &&
+               scan_inst->src[i].reg == inst->src[0].reg &&
+               scan_inst->src[i].reg_offset == inst->src[0].reg_offset) {
+              interfered = true;
+           }
+        }
+        if (interfered)
+           break;
+
+        if (scan_inst->dst.file == MRF &&
+            scan_inst->dst.hw_reg == inst->dst.hw_reg) {
+           /* Somebody else wrote our MRF here, so we can't can't
+            * compute-to-MRF before that.
+            */
+           break;
+        }
+
+        if (scan_inst->mlen > 0) {
+           /* Found a SEND instruction, which means that there are
+            * live values in MRFs from base_mrf to base_mrf +
+            * scan_inst->mlen - 1.  Don't go pushing our MRF write up
+            * above it.
+            */
+           if (inst->dst.hw_reg >= scan_inst->base_mrf &&
+               inst->dst.hw_reg < scan_inst->base_mrf + scan_inst->mlen) {
               break;
            }
         }
       }
-      if (found) {
-        scan_inst->dst.file = MRF;
-        scan_inst->dst.hw_reg = inst->dst.hw_reg;
-        scan_inst->saturate |= inst->saturate;
-        inst->remove();
-        progress = true;
-      }
    }
 
    return progress;