summaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2010-10-03 15:15:18 -0700
committerEric Anholt <[email protected]>2010-10-04 16:08:17 -0700
commite27c88d8e6c9d18bfa793f884d02ce6011c4bdde (patch)
tree81c15ee31a921f25e0d261b490ee28b32def6f65 /src/mesa/drivers
parent9faf64bc32cf7c1a06a302fff9f80d7e2e2685d5 (diff)
i965: Add trivial dead code elimination in the new FS backend.
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.
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.cpp52
1 files changed, 50 insertions, 2 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index 6106445fbb7..472e6d06f62 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -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