i965/fs: Add pass to rename registers to break live ranges.
authorKenneth Graunke <kenneth@whitecape.org>
Mon, 14 Apr 2014 22:01:37 +0000 (15:01 -0700)
committerMatt Turner <mattst88@gmail.com>
Fri, 15 Aug 2014 06:50:12 +0000 (23:50 -0700)
The pass breaks live ranges of virtual registers by allocating new
registers when it sees an assignment to a virtual GRF it's already seen
written.

total instructions in shared programs: 4337879 -> 4335014 (-0.07%)
instructions in affected programs:     343865 -> 341000 (-0.83%)
GAINED:                                46
LOST:                                  1

[mattst88]: Make pass not break in presence of control flow.
            invalidate_live_intervals() only if progress.
            Fix up delta_x/delta_y.

Reviewed-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Matt Turner <mattst88@gmail.com>
Reviewed-by: Connor Abbott <cwabbott0@gmail.com>
src/mesa/drivers/dri/i965/brw_fs.cpp
src/mesa/drivers/dri/i965/brw_fs.h

index 43aee66f4101108acc6fabdc0f458425dfbc9493..ed7a0bce8caee370502375d3cbc6ba2126ac87b7 100644 (file)
@@ -2055,6 +2055,72 @@ fs_visitor::opt_algebraic()
    return progress;
 }
 
+bool
+fs_visitor::opt_register_renaming()
+{
+   bool progress = false;
+   int depth = 0;
+
+   int remap[virtual_grf_count];
+   memset(remap, -1, sizeof(int) * virtual_grf_count);
+
+   foreach_in_list(fs_inst, inst, &this->instructions) {
+      if (inst->opcode == BRW_OPCODE_IF || inst->opcode == BRW_OPCODE_DO) {
+         depth++;
+      } else if (inst->opcode == BRW_OPCODE_ENDIF ||
+                 inst->opcode == BRW_OPCODE_WHILE) {
+         depth--;
+      }
+
+      /* Rewrite instruction sources. */
+      for (int i = 0; i < inst->sources; i++) {
+         if (inst->src[i].file == GRF &&
+             remap[inst->src[i].reg] != -1 &&
+             remap[inst->src[i].reg] != inst->src[i].reg) {
+            inst->src[i].reg = remap[inst->src[i].reg];
+            progress = true;
+         }
+      }
+
+      const int dst = inst->dst.reg;
+
+      if (depth == 0 &&
+          inst->dst.file == GRF &&
+          virtual_grf_sizes[inst->dst.reg] == 1 &&
+          !inst->is_partial_write()) {
+         if (remap[dst] == -1) {
+            remap[dst] = dst;
+         } else {
+            remap[dst] = virtual_grf_alloc(1);
+            inst->dst.reg = remap[dst];
+            progress = true;
+         }
+      } else if (inst->dst.file == GRF &&
+                 remap[dst] != -1 &&
+                 remap[dst] != dst) {
+         inst->dst.reg = remap[dst];
+         progress = true;
+      }
+   }
+
+   if (progress) {
+      invalidate_live_intervals();
+
+      for (unsigned i = 0; i < ARRAY_SIZE(delta_x); i++) {
+         if (delta_x[i].file == GRF && remap[delta_x[i].reg] != -1) {
+            delta_x[i].reg = remap[delta_x[i].reg];
+         }
+      }
+      for (unsigned i = 0; i < ARRAY_SIZE(delta_y); i++) {
+         if (delta_y[i].file == GRF && remap[delta_y[i].reg] != -1) {
+            delta_y[i].reg = remap[delta_y[i].reg];
+         }
+      }
+   }
+
+   return progress;
+}
+
 bool
 fs_visitor::compute_to_mrf()
 {
@@ -3080,6 +3146,7 @@ fs_visitor::run()
          OPT(dead_code_eliminate);
          OPT(opt_peephole_sel);
          OPT(dead_control_flow_eliminate, this);
+         OPT(opt_register_renaming);
          OPT(opt_saturate_propagation);
          OPT(register_coalesce);
          OPT(compute_to_mrf);
index a838e74d8b63367631fdab5740a2456632522b39..5aa0ca661fe3a760c42d0fc7a5ea501c9bc33cee 100644 (file)
@@ -339,6 +339,7 @@ public:
    bool opt_copy_propagate_local(void *mem_ctx, bblock_t *block,
                                  exec_list *acp);
    void opt_drop_redundant_mov_to_flags();
+   bool opt_register_renaming();
    bool register_coalesce();
    bool compute_to_mrf();
    bool dead_code_eliminate();