i965/fs: Compact the virtual GRF arrays.
authorKenneth Graunke <kenneth@whitecape.org>
Fri, 2 Nov 2012 05:04:50 +0000 (22:04 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Sun, 4 Nov 2012 03:28:57 +0000 (20:28 -0700)
During code generation, we create tons of temporary variables, many of
which get immediately killed and are never used.  Later optimization and
analysis passes, such as compute_live_intervals, loop over all the
virtual GRFs.  By compacting them, we can save a lot of overhead.

Reduces compilation time in L4D2's largest fragment shader from 10.2
seconds to 5.2 seconds (50%).  Drops compute_live_variables() from
10-12% of another game's startup time to 8%.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
src/mesa/drivers/dri/i965/brw_fs.cpp
src/mesa/drivers/dri/i965/brw_fs.h

index 56cb447fafeab981e0f2948c32fa3215d161198b..777879e1241cf9cc1f93f7a1a70e768cc42f540a 100644 (file)
@@ -1102,6 +1102,64 @@ fs_visitor::split_virtual_grfs()
    this->live_intervals_valid = false;
 }
 
+/**
+ * Remove unused virtual GRFs and compact the virtual_grf_* arrays.
+ *
+ * During code generation, we create tons of temporary variables, many of
+ * which get immediately killed and are never used again.  Yet, in later
+ * optimization and analysis passes, such as compute_live_intervals, we need
+ * to loop over all the virtual GRFs.  Compacting them can save a lot of
+ * overhead.
+ */
+void
+fs_visitor::compact_virtual_grfs()
+{
+   /* Mark which virtual GRFs are used, and count how many. */
+   int remap_table[this->virtual_grf_count];
+   memset(remap_table, -1, sizeof(remap_table));
+
+   foreach_list(node, &this->instructions) {
+      const fs_inst *inst = (const fs_inst *) node;
+
+      if (inst->dst.file == GRF)
+         remap_table[inst->dst.reg] = 0;
+
+      for (int i = 0; i < 3; i++) {
+         if (inst->src[i].file == GRF)
+            remap_table[inst->src[i].reg] = 0;
+      }
+   }
+
+   /* Compact the GRF arrays. */
+   int new_index = 0;
+   for (int i = 0; i < this->virtual_grf_count; i++) {
+      if (remap_table[i] != -1) {
+         remap_table[i] = new_index;
+         virtual_grf_sizes[new_index] = virtual_grf_sizes[i];
+         if (live_intervals_valid) {
+            virtual_grf_use[new_index] = virtual_grf_use[i];
+            virtual_grf_def[new_index] = virtual_grf_def[i];
+         }
+         ++new_index;
+      }
+   }
+
+   this->virtual_grf_count = new_index;
+
+   /* Patch all the instructions to use the newly renumbered registers */
+   foreach_list(node, &this->instructions) {
+      fs_inst *inst = (fs_inst *) node;
+
+      if (inst->dst.file == GRF)
+         inst->dst.reg = remap_table[inst->dst.reg];
+
+      for (int i = 0; i < 3; i++) {
+         if (inst->src[i].file == GRF)
+            inst->src[i].reg = remap_table[inst->src[i].reg];
+      }
+   }
+}
+
 bool
 fs_visitor::remove_dead_constants()
 {
@@ -1860,6 +1918,8 @@ fs_visitor::run()
       do {
         progress = false;
 
+         compact_virtual_grfs();
+
         progress = remove_duplicate_mrf_writes() || progress;
 
         progress = opt_algebraic() || progress;
index 0b2681d6cdd8de8346f0faa7b0fc5e02b2c4d7de..13662bb8836a19660e35441763364e6eac8759d4 100644 (file)
@@ -240,6 +240,7 @@ public:
    int choose_spill_reg(struct ra_graph *g);
    void spill_reg(int spill_reg);
    void split_virtual_grfs();
+   void compact_virtual_grfs();
    void setup_pull_constants();
    void calculate_live_intervals();
    bool opt_algebraic();