summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGert Wollny <[email protected]>2017-12-07 13:51:22 +0100
committerBrian Paul <[email protected]>2018-01-24 10:23:00 -0700
commit51c0cee267206ae9de215b8e4f75c04a2fa251b2 (patch)
treef18a7f646b45f7838d64fdef9de7e066e7df593a
parent517e34c62f18c6067781370401d26c8162dfde4c (diff)
mesa/st/glsl_to_tgsi: Add tracking of indirect addressing registers
So far indirect addressing was not tracked to estimate the temporary life time, and it was not needed, because code to load the address registers was always emitted eliminating the reladdr* handles in the past glsl-to.tgsi stages. Now, with Mareks patch allowing any 1D register to be used for addressing on some hardware this changed, and the tracking becomes necessary. Because the registers have no direct indication on whether the reladdr* was already loaded into an address register, the temporaries in reladdr* are always tracked as reads. This may result in a slight over-estimation of the lifetime in the cases when the load to the address register was emitted. v2: no changes v3: Use debug_log variable instead of directly writing to std::err in debugging output. v6: fix indention and typos Reviewed-by: Brian Paul <[email protected]> Reviewed-by: Nicolai Hähnle <[email protected]> (v1) Signed-off-by: Gert Wollny <[email protected]>
-rw-r--r--src/mesa/state_tracker/st_glsl_to_tgsi_temprename.cpp108
1 files changed, 74 insertions, 34 deletions
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi_temprename.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi_temprename.cpp
index 76b3f43a590..3a00b337496 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi_temprename.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi_temprename.cpp
@@ -874,6 +874,69 @@ public:
}
};
+class access_recorder {
+public:
+ access_recorder(int _ntemps);
+ ~access_recorder();
+
+ void record_read(const st_src_reg& src, int line, prog_scope *scope);
+ void record_write(const st_dst_reg& src, int line, prog_scope *scope);
+
+ void get_required_lifetimes(struct lifetime *lifetimes);
+private:
+
+ int ntemps;
+ temp_access *acc;
+
+};
+
+access_recorder::access_recorder(int _ntemps):
+ ntemps(_ntemps)
+{
+ acc = new temp_access[ntemps];
+}
+
+access_recorder::~access_recorder()
+{
+ delete[] acc;
+}
+
+void access_recorder::record_read(const st_src_reg& src, int line,
+ prog_scope *scope)
+{
+ if (src.file == PROGRAM_TEMPORARY)
+ acc[src.index].record_read(line, scope, src.swizzle);
+
+ if (src.reladdr)
+ record_read(*src.reladdr, line, scope);
+ if (src.reladdr2)
+ record_read(*src.reladdr2, line, scope);
+}
+
+void access_recorder::record_write(const st_dst_reg& dst, int line,
+ prog_scope *scope)
+{
+ if (dst.file == PROGRAM_TEMPORARY)
+ acc[dst.index].record_write(line, scope, dst.writemask);
+
+ if (dst.reladdr)
+ record_read(*dst.reladdr, line, scope);
+ if (dst.reladdr2)
+ record_read(*dst.reladdr2, line, scope);
+}
+
+void access_recorder::get_required_lifetimes(struct lifetime *lifetimes)
+{
+ RENAME_DEBUG(debug_log << "========= lifetimes ==============\n");
+ for(int i = 0; i < ntemps; ++i) {
+ RENAME_DEBUG(debug_log<< setw(4) << i);
+ lifetimes[i] = acc[i].get_required_lifetime();
+ RENAME_DEBUG(debug_log << ": [" << lifetimes[i].begin << ", "
+ << lifetimes[i].end << "]\n");
+ }
+ RENAME_DEBUG(debug_log << "==================================\n\n");
+}
+
}
#ifndef NDEBUG
@@ -894,7 +957,6 @@ get_temp_registers_required_lifetimes(void *mem_ctx, exec_list *instructions,
int if_id = 1;
int switch_id = 0;
bool is_at_end = false;
- bool ok = true;
int n_scopes = 1;
/* Count scopes to allocate the needed space without the need for
@@ -912,7 +974,8 @@ get_temp_registers_required_lifetimes(void *mem_ctx, exec_list *instructions,
}
prog_scope_storage scopes(mem_ctx, n_scopes);
- temp_access *acc = new temp_access[ntemps];
+
+ access_recorder access(ntemps);
prog_scope *cur_scope = scopes.create(nullptr, outer_scope, 0, 0, line);
@@ -941,9 +1004,7 @@ get_temp_registers_required_lifetimes(void *mem_ctx, exec_list *instructions,
case TGSI_OPCODE_IF:
case TGSI_OPCODE_UIF: {
assert(num_inst_src_regs(inst) == 1);
- const st_src_reg& src = inst->src[0];
- if (src.file == PROGRAM_TEMPORARY)
- acc[src.index].record_read(line, cur_scope, src.swizzle);
+ access.record_read(inst->src[0], line, cur_scope);
cur_scope = scopes.create(cur_scope, if_branch, if_id++,
cur_scope->nesting_depth() + 1, line + 1);
break;
@@ -969,14 +1030,12 @@ get_temp_registers_required_lifetimes(void *mem_ctx, exec_list *instructions,
}
case TGSI_OPCODE_SWITCH: {
assert(num_inst_src_regs(inst) == 1);
- const st_src_reg& src = inst->src[0];
prog_scope *scope = scopes.create(cur_scope, switch_body, switch_id++,
cur_scope->nesting_depth() + 1, line);
/* We record the read only for the SWITCH statement itself, like it
* is used by the only consumer of TGSI_OPCODE_SWITCH in tgsi_exec.c.
*/
- if (src.file == PROGRAM_TEMPORARY)
- acc[src.index].record_read(line, cur_scope, src.swizzle);
+ access.record_read(inst->src[0], line, cur_scope);
cur_scope = scope;
break;
}
@@ -998,9 +1057,7 @@ get_temp_registers_required_lifetimes(void *mem_ctx, exec_list *instructions,
cur_scope : cur_scope->parent();
assert(num_inst_src_regs(inst) == 1);
- const st_src_reg& src = inst->src[0];
- if (src.file == PROGRAM_TEMPORARY)
- acc[src.index].record_read(line, switch_scope, src.swizzle);
+ access.record_read(inst->src[0], line, switch_scope);
/* Fall through to allocate the scope. */
}
@@ -1036,23 +1093,16 @@ get_temp_registers_required_lifetimes(void *mem_ctx, exec_list *instructions,
* Since this is not done, we have to bail out here and signal
* that no register merge will take place.
*/
- ok = false;
- goto out;
+ return false;
default: {
for (unsigned j = 0; j < num_inst_src_regs(inst); j++) {
- const st_src_reg& src = inst->src[j];
- if (src.file == PROGRAM_TEMPORARY)
- acc[src.index].record_read(line, cur_scope, src.swizzle);
+ access.record_read(inst->src[j], line, cur_scope);
}
for (unsigned j = 0; j < inst->tex_offset_num_offset; j++) {
- const st_src_reg& src = inst->tex_offsets[j];
- if (src.file == PROGRAM_TEMPORARY)
- acc[src.index].record_read(line, cur_scope, src.swizzle);
+ access.record_read(inst->tex_offsets[j], line, cur_scope);
}
for (unsigned j = 0; j < num_inst_dst_regs(inst); j++) {
- const st_dst_reg& dst = inst->dst[j];
- if (dst.file == PROGRAM_TEMPORARY)
- acc[dst.index].record_write(line, cur_scope, dst.writemask);
+ access.record_write(inst->dst[j], line, cur_scope);
}
}
}
@@ -1067,18 +1117,8 @@ get_temp_registers_required_lifetimes(void *mem_ctx, exec_list *instructions,
if (cur_scope->end() < 0)
cur_scope->set_end(line - 1);
- RENAME_DEBUG(debug_log << "========= lifetimes ==============\n");
- for(int i = 0; i < ntemps; ++i) {
- RENAME_DEBUG(debug_log << setw(4) << i);
- lifetimes[i] = acc[i].get_required_lifetime();
- RENAME_DEBUG(debug_log << ": [" << lifetimes[i].begin << ", "
- << lifetimes[i].end << "]\n");
- }
- RENAME_DEBUG(debug_log << "==================================\n\n");
-
-out:
- delete[] acc;
- return ok;
+ access.get_required_lifetimes(lifetimes);
+ return true;
}
/* Find the next register between [start, end) that has a life time starting