i965: Handle CMP.nz ... 0 and MOV.nz similarly in cmod propagation.
authorKenneth Graunke <kenneth@whitecape.org>
Sat, 24 Jan 2015 12:16:54 +0000 (04:16 -0800)
committerKenneth Graunke <kenneth@whitecape.org>
Mon, 26 Jan 2015 18:13:18 +0000 (10:13 -0800)
"MOV.nz null src" and "CMP.nz null src 0" are equivalent instructions.

Previously, we deleted MOV.nz instructions when the instruction
generating the MOV's source also wrote the flag register (as the flag
register already contains the desired value).  However, we wouldn't
delete CMP.nz instructions that served the same purpose.

We also didn't attempt true cmod propagation on MOV.nz instructions,
while we would for the equivalent CMP.nz form.

This patch fixes both limitations, treating both forms equally.
CMP.nz instructions will now be deleted (helping the NIR backend),
and MOV.nz instructions will have their .nz propagated.

No changes in shader-db without NIR.  With NIR,

total instructions in shared programs: 6006153 -> 5969364 (-0.61%)
instructions in affected programs:     2087139 -> 2050350 (-1.76%)
helped:                                10704
HURT:                                  0
GAINED:                                2
LOST:                                  2

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Matt Turner <mattst88@gmail.com>
src/mesa/drivers/dri/i965/brw_fs_cmod_propagation.cpp

index ec9f812ea11440c996cda616bb366e40605218a3..c6384ab53cf129a773d8bf9712f21a25e26164e0 100644 (file)
@@ -69,8 +69,7 @@ opt_cmod_propagation_local(fs_visitor *v, bblock_t *block)
          continue;
 
       if (inst->opcode == BRW_OPCODE_MOV &&
-          (inst->conditional_mod != BRW_CONDITIONAL_NZ ||
-           inst->src[0].negate))
+          inst->conditional_mod != BRW_CONDITIONAL_NZ)
          continue;
 
       bool read_flag = false;
@@ -81,15 +80,20 @@ opt_cmod_propagation_local(fs_visitor *v, bblock_t *block)
                 scan_inst->dst.reg_offset != inst->src[0].reg_offset)
                break;
 
-            if (inst->opcode == BRW_OPCODE_MOV) {
-               if (!scan_inst->writes_flag())
-                  break;
-
+            /* If the instruction generating inst's source also wrote the
+             * flag, and inst is doing a simple .nz comparison, then inst
+             * is redundant - the appropriate value is already in the flag
+             * register.  Delete inst.
+             */
+            if (inst->conditional_mod == BRW_CONDITIONAL_NZ &&
+                !inst->src[0].negate &&
+                scan_inst->writes_flag()) {
                inst->remove(block);
                progress = true;
                break;
             }
 
+            /* Otherwise, try propagating the conditional. */
             enum brw_conditional_mod cond =
                inst->src[0].negate ? brw_swap_cmod(inst->conditional_mod)
                                    : inst->conditional_mod;