From e27c88d8e6c9d18bfa793f884d02ce6011c4bdde Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sun, 3 Oct 2010 15:15:18 -0700 Subject: [PATCH] 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. --- src/mesa/drivers/dri/i965/brw_fs.cpp | 52 ++++++++++++++++++++++++++++++++++-- 1 file 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 6106445..472e6d0 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 -- 2.7.4