diff options
author | Eric Anholt <[email protected]> | 2010-10-03 15:15:18 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2010-10-04 16:08:17 -0700 |
commit | e27c88d8e6c9d18bfa793f884d02ce6011c4bdde (patch) | |
tree | 81c15ee31a921f25e0d261b490ee28b32def6f65 /src/mesa | |
parent | 9faf64bc32cf7c1a06a302fff9f80d7e2e2685d5 (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')
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs.cpp | 52 |
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 |