summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4.cpp60
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4.h1
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4_emit.cpp1
3 files changed, 62 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_vec4.cpp b/src/mesa/drivers/dri/i965/brw_vec4.cpp
index 2941729c4a0..e0b643242a3 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4.cpp
@@ -865,4 +865,64 @@ vec4_visitor::opt_compute_to_mrf()
return progress;
}
+/**
+ * Splits virtual GRFs requesting more than one contiguous physical register.
+ *
+ * We initially create large virtual GRFs for temporary structures, arrays,
+ * and matrices, so that the dereference visitor functions can add reg_offsets
+ * to work their way down to the actual member being accessed.
+ *
+ * Unlike in the FS visitor, though, we have no SEND messages that return more
+ * than 1 register. We also don't do any array access in register space,
+ * which would have required contiguous physical registers. Thus, all those
+ * large virtual GRFs can be split up into independent single-register virtual
+ * GRFs, making allocation and optimization easier.
+ */
+void
+vec4_visitor::split_virtual_grfs()
+{
+ int num_vars = this->virtual_grf_count;
+ int new_virtual_grf[num_vars];
+
+ memset(new_virtual_grf, 0, sizeof(new_virtual_grf));
+
+ /* Allocate new space for split regs. Note that the virtual
+ * numbers will be contiguous.
+ */
+ for (int i = 0; i < num_vars; i++) {
+ if (this->virtual_grf_sizes[i] == 1)
+ continue;
+
+ new_virtual_grf[i] = virtual_grf_alloc(1);
+ for (int j = 2; j < this->virtual_grf_sizes[i]; j++) {
+ int reg = virtual_grf_alloc(1);
+ assert(reg == new_virtual_grf[i] + j - 1);
+ (void) reg;
+ }
+ this->virtual_grf_sizes[i] = 1;
+ }
+
+ foreach_list(node, &this->instructions) {
+ vec4_instruction *inst = (vec4_instruction *)node;
+
+ if (inst->dst.file == GRF &&
+ new_virtual_grf[inst->dst.reg] &&
+ inst->dst.reg_offset != 0) {
+ inst->dst.reg = (new_virtual_grf[inst->dst.reg] +
+ inst->dst.reg_offset - 1);
+ inst->dst.reg_offset = 0;
+ }
+ for (int i = 0; i < 3; i++) {
+ if (inst->src[i].file == GRF &&
+ new_virtual_grf[inst->src[i].reg] &&
+ inst->src[i].reg_offset != 0) {
+ inst->src[i].reg = (new_virtual_grf[inst->src[i].reg] +
+ inst->src[i].reg_offset - 1);
+ inst->src[i].reg_offset = 0;
+ }
+ }
+ }
+ this->live_intervals_valid = false;
+}
+
} /* namespace brw */
diff --git a/src/mesa/drivers/dri/i965/brw_vec4.h b/src/mesa/drivers/dri/i965/brw_vec4.h
index dce3c89575d..4fdede3ab26 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4.h
+++ b/src/mesa/drivers/dri/i965/brw_vec4.h
@@ -323,6 +323,7 @@ public:
void split_uniform_registers();
void pack_uniform_registers();
void calculate_live_intervals();
+ void split_virtual_grfs();
bool dead_code_eliminate();
bool virtual_grf_interferes(int a, int b);
bool opt_copy_propagation();
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_emit.cpp b/src/mesa/drivers/dri/i965/brw_vec4_emit.cpp
index 5a941d90c30..479b0a607aa 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_emit.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_emit.cpp
@@ -794,6 +794,7 @@ vec4_visitor::run()
move_uniform_array_access_to_pull_constants();
pack_uniform_registers();
move_push_constants_to_pull_constants();
+ split_virtual_grfs();
bool progress;
do {