i965: Add trivial dead code elimination in the new FS backend.
authorEric Anholt <eric@anholt.net>
Sun, 3 Oct 2010 22:15:18 +0000 (15:15 -0700)
committerEric Anholt <eric@anholt.net>
Mon, 4 Oct 2010 23:08:17 +0000 (16:08 -0700)
The glsl core should be handling most dead code issues for us, but we
generate some things in codegen that may not get used, like the 1/w
value or pixel deltas.  It seems a lot easier this way than trying to
work out up front whether we're going to use those values or not.

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

index 6106445fbb73931b4e165c821bea6b2e539955dc..472e6d06f62c5a92f22169d7f13c4c5c9a66c4ce 100644 (file)
@@ -455,6 +455,7 @@ public:
    void assign_regs();
    void assign_regs_trivial();
    void calculate_live_intervals();
+   bool dead_code_eliminate();
    bool virtual_grf_interferes(int a, int b);
    void generate_code();
    void generate_fb_write(fs_inst *inst);
@@ -2289,8 +2290,6 @@ fs_visitor::assign_regs()
    int class_count = 0;
    int aligned_pair_class = -1;
 
-   calculate_live_intervals();
-
    /* Set up the register classes.
     *
     * The base registers store a scalar value.  For texture samples,
@@ -2517,10 +2516,50 @@ fs_visitor::calculate_live_intervals()
       ip++;
    }
 
+   talloc_free(this->virtual_grf_def);
+   talloc_free(this->virtual_grf_use);
    this->virtual_grf_def = def;
    this->virtual_grf_use = use;
 }
 
+/**
+ * Must be called after calculate_live_intervales() to remove unused
+ * writes to registers -- register allocation will fail otherwise
+ * because something deffed but not used won't be considered to
+ * interfere with other regs.
+ */
+bool
+fs_visitor::dead_code_eliminate()
+{
+   bool progress = false;
+   int num_vars = this->virtual_grf_next;
+   bool dead[num_vars];
+
+   for (int i = 0; i < num_vars; i++) {
+      /* This would be ">=", but FS_OPCODE_DISCARD has a src == dst where
+       * it writes dst then reads it as src.
+       */
+      dead[i] = this->virtual_grf_def[i] > this->virtual_grf_use[i];
+
+      if (dead[i]) {
+        /* Mark off its interval so it won't interfere with anything. */
+        this->virtual_grf_def[i] = -1;
+        this->virtual_grf_use[i] = -1;
+      }
+   }
+
+   foreach_iter(exec_list_iterator, iter, this->instructions) {
+      fs_inst *inst = (fs_inst *)iter.get();
+
+      if (inst->dst.file == GRF && dead[inst->dst.reg]) {
+        inst->remove();
+        progress = true;
+      }
+   }
+
+   return progress;
+}
+
 bool
 fs_visitor::virtual_grf_interferes(int a, int b)
 {
@@ -2831,6 +2870,15 @@ brw_wm_fs_emit(struct brw_context *brw, struct brw_wm_compile *c)
       v.emit_fb_writes();
       v.assign_curb_setup();
       v.assign_urb_setup();
+
+      bool progress;
+      do {
+        progress = false;
+
+        v.calculate_live_intervals();
+        progress = v.dead_code_eliminate() || progress;
+      } while (progress);
+
       if (0)
         v.assign_regs_trivial();
       else