[Mesa-dev] [PATCH 4/5] i965/fs: Do more register coalescing by using the interference graph.
Eric Anholt
eric at anholt.net
Tue May 8 17:59:38 PDT 2012
By using the live variables code for determining interference, we can
handle coalescing in the presence of control flow, which the other
register coalescing path couldn't.
Total instructions: 207184 -> 206990
74/1246 programs affected (5.9%)
33993 -> 33799 instructions in affected programs (0.6% reduction)
There is a newerth shader that loses out, because of some extra MOVs
that now get their dead-code nature obscured by coalescing. This
should be fixed by doing better at dead code elimination.
---
src/mesa/drivers/dri/i965/brw_fs.cpp | 61 ++++++++++++++++++++++++++++++++++
src/mesa/drivers/dri/i965/brw_fs.h | 1 +
2 files changed, 62 insertions(+)
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index a723cd8..0fe97dd 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -1218,6 +1218,66 @@ fs_visitor::dead_code_eliminate()
return progress;
}
+/**
+ * Implements a second type of register coalescing: This one checks if
+ * the two regs involved in a raw move don't interfere, in which case
+ * they can both by stored in the same place and the MOV removed.
+ */
+bool
+fs_visitor::register_coalesce_2()
+{
+ bool progress = false;
+
+ calculate_live_intervals();
+
+ foreach_list_safe(node, &this->instructions) {
+ fs_inst *inst = (fs_inst *)node;
+
+ if (inst->opcode != BRW_OPCODE_MOV ||
+ inst->predicated ||
+ inst->saturate ||
+ inst->src[0].file != GRF ||
+ inst->src[0].negate ||
+ inst->src[0].abs ||
+ inst->src[0].smear != -1 ||
+ inst->dst.file != GRF ||
+ inst->dst.type != inst->src[0].type ||
+ virtual_grf_sizes[inst->src[0].reg] != 1 ||
+ virtual_grf_interferes(inst->dst.reg, inst->src[0].reg)) {
+ continue;
+ }
+
+ int reg_from = inst->src[0].reg;
+ assert(inst->src[0].reg_offset == 0);
+ int reg_to = inst->dst.reg;
+ int reg_to_offset = inst->dst.reg_offset;
+
+ foreach_list_safe(node, &this->instructions) {
+ fs_inst *scan_inst = (fs_inst *)node;
+
+ if (scan_inst->dst.file == GRF &&
+ scan_inst->dst.reg == reg_from) {
+ scan_inst->dst.reg = reg_to;
+ scan_inst->dst.reg_offset = reg_to_offset;
+ }
+ for (int i = 0; i < 3; i++) {
+ if (scan_inst->src[i].file == GRF &&
+ scan_inst->src[i].reg == reg_from) {
+ scan_inst->src[i].reg = reg_to;
+ scan_inst->src[i].reg_offset = reg_to_offset;
+ }
+ }
+ }
+
+ inst->remove();
+ live_intervals_valid = false;
+ progress = true;
+ continue;
+ }
+
+ return progress;
+}
+
bool
fs_visitor::register_coalesce()
{
@@ -1683,6 +1743,7 @@ fs_visitor::run()
progress = opt_algebraic() || progress;
progress = opt_copy_propagate() || progress;
progress = register_coalesce() || progress;
+ progress = register_coalesce_2() || progress;
progress = compute_to_mrf() || progress;
progress = dead_code_eliminate() || progress;
} while (progress);
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index 8ae855e..ae4656b 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -513,6 +513,7 @@ public:
bool opt_copy_propagate_local(void *mem_ctx, fs_bblock *block,
exec_list *acp);
bool register_coalesce();
+ bool register_coalesce_2();
bool compute_to_mrf();
bool dead_code_eliminate();
bool remove_dead_constants();
--
1.7.10
More information about the mesa-dev
mailing list