[Mesa-dev] [PATCH 3/3] glsl_to_tgsi: Use mesa register allocator
Vincent Lejeune
vljn at ovi.com
Fri Jan 6 11:15:26 PST 2012
---
src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 156 +++++++++++++--------------
1 files changed, 75 insertions(+), 81 deletions(-)
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index e0013f1..2f752d6 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -55,6 +55,7 @@ extern "C" {
#include "program/program.h"
#include "program/prog_parameter.h"
#include "program/sampler.h"
+#include "program/register_allocate.h"
#include "pipe/p_compiler.h"
#include "pipe/p_context.h"
@@ -834,7 +835,6 @@ public:
void remove_output_reads(gl_register_file type);
void simplify_cmp(void);
- void rename_temp_register(int index, int new_index);
int get_first_temp_read(int index);
int get_first_temp_write(int index);
int get_last_temp_read(int index);
@@ -843,8 +843,7 @@ public:
void copy_propagate(void);
void eliminate_dead_code(void);
int eliminate_dead_code_advanced(void);
- void merge_registers(void);
- void renumber_registers(void);
+ void regalloc(void);
void renumber_temp_regs(unsigned*);
void *mem_ctx;
@@ -3419,27 +3418,6 @@ glsl_to_tgsi_visitor::simplify_cmp(void)
delete [] tempWrites;
}
-/* Replaces all references to a temporary register index with another index. */
-void
-glsl_to_tgsi_visitor::rename_temp_register(int index, int new_index)
-{
- foreach_iter(exec_list_iterator, iter, this->instructions) {
- glsl_to_tgsi_instruction *inst = (glsl_to_tgsi_instruction *)iter.get();
- unsigned j;
-
- for (j=0; j < num_inst_src_regs(inst->op); j++) {
- if (inst->src[j].file == PROGRAM_TEMPORARY &&
- inst->src[j].index == index) {
- inst->src[j].index = new_index;
- }
- }
-
- if (inst->dst.file == PROGRAM_TEMPORARY && inst->dst.index == index) {
- inst->dst.index = new_index;
- }
- }
-}
-
int
glsl_to_tgsi_visitor::get_first_temp_read(int index)
{
@@ -3943,73 +3921,92 @@ glsl_to_tgsi_visitor::eliminate_dead_code_advanced(void)
return removed;
}
-/* Merges temporary registers together where possible to reduce the number of
+struct interval {
+ int first_line;
+ int last_line;
+};
+
+static bool
+overlap(const interval &a, const interval &b)
+{
+ return MIN2(a.last_line, b.last_line) > MAX2(a.first_line, b.first_line);
+}
+
+/* Merges temporary registers together where possible to reduce the number of
* registers needed to run a program.
- *
- * Produces optimal code only after copy propagation and dead code elimination
+ *
+ * Produces optimal code only after copy propagation and dead code elimination
* have been run. */
void
-glsl_to_tgsi_visitor::merge_registers(void)
+glsl_to_tgsi_visitor::regalloc(void)
{
- int *last_reads = rzalloc_array(mem_ctx, int, this->next_temp);
- int *first_writes = rzalloc_array(mem_ctx, int, this->next_temp);
+ unsigned total_temps = store.temp_amount();
+ unsigned first_non_array_temp = store.temp_array_amount() + 1;
+ unsigned allocable_regs = total_temps - first_non_array_temp;
+ struct interval *live_interval = rzalloc_array(mem_ctx,struct interval,allocable_regs);
int i, j;
-
+
/* Read the indices of the last read and first write to each temp register
- * into an array so that we don't have to traverse the instruction list as
+ * into an array so that we don't have to traverse the instruction list as
* much. */
- for (i=0; i < this->next_temp; i++) {
- last_reads[i] = get_last_temp_read(i);
- first_writes[i] = get_first_temp_write(i);
+ for (i=0; i < allocable_regs; i++) {
+ live_interval[i].last_line = get_last_temp_read(i + first_non_array_temp);
+ live_interval[i].first_line = get_first_temp_write(i + first_non_array_temp);
}
-
- /* Start looking for registers with non-overlapping usages that can be
- * merged together. */
- for (i=0; i < this->next_temp; i++) {
- /* Don't touch unused registers. */
- if (last_reads[i] < 0 || first_writes[i] < 0) continue;
-
- for (j=0; j < this->next_temp; j++) {
- /* Don't touch unused registers. */
- if (last_reads[j] < 0 || first_writes[j] < 0) continue;
-
- /* We can merge the two registers if the first write to j is after or
- * in the same instruction as the last read from i. Note that the
- * register at index i will always be used earlier or at the same time
- * as the register at index j. */
- if (first_writes[i] <= first_writes[j] &&
- last_reads[i] <= first_writes[j])
- {
- rename_temp_register(j, i); /* Replace all references to j with i.*/
-
- /* Update the first_writes and last_reads arrays with the new
- * values for the merged register index, and mark the newly unused
- * register index as such. */
- last_reads[i] = last_reads[j];
- first_writes[j] = -1;
- last_reads[j] = -1;
+
+ struct ra_regs *regs = ra_alloc_reg_set(MAX_TEMPS);
+ unsigned temp_class = ra_alloc_reg_class(regs);
+
+ for (i = 0; i < + 32; i++) {
+ ra_class_add_reg(regs,temp_class,i);
+ }
+
+ ra_set_finalize(regs);
+
+ struct ra_graph *graph = ra_alloc_interference_graph(regs,total_temps - first_non_array_temp + 1);
+
+ for (i = 0; i < first_non_array_temp; i++) {
+ ra_set_node_class(graph,i,temp_class);
+ }
+
+
+ for (i = 0; i < allocable_regs; i++) {
+ for (j = i + 1; j < allocable_regs; j++) {
+ if (overlap(live_interval[i],live_interval[j]))
+ ra_add_node_interference(graph,i,j);
+ }
+ }
+
+ if (!ra_allocate_no_spills(graph)) {
+ printf("UNABLE TO ALLOCATE REGS\n");
+ }
+
+
+ foreach_iter(exec_list_iterator, iter, this->instructions) {
+ glsl_to_tgsi_instruction *inst = (glsl_to_tgsi_instruction *)iter.get();
+ unsigned j;
+
+ for (j=0; j < num_inst_src_regs(inst->op); j++) {
+ if (inst->src[j].file == PROGRAM_TEMPORARY) {
+ unsigned index = inst->src[j].index;
+ if (index >= first_non_array_temp)
+ inst->src[j].index = ra_get_node_reg(graph, index - first_non_array_temp) + first_non_array_temp;
}
}
+
+ if (inst->dst.file == PROGRAM_TEMPORARY) {
+ unsigned index = inst->dst.index;
+ if (index >= first_non_array_temp)
+ inst->dst.index = ra_get_node_reg(graph, index - first_non_array_temp) + first_non_array_temp;
+ }
}
-
- ralloc_free(last_reads);
- ralloc_free(first_writes);
+
+ ralloc_free(graph);
+ ralloc_free(regs);
}
-/* Reassign indices to temporary registers by reusing unused indices created
- * by optimization passes. */
-void
-glsl_to_tgsi_visitor::renumber_registers(void)
void glsl_to_tgsi_visitor::renumber_temp_regs(unsigned *reindex_table)
{
- int i = 0;
- int new_index = 0;
-
- for (i=0; i < this->next_temp; i++) {
- if (get_first_temp_read(i) < 0) continue;
- if (i != new_index)
- rename_temp_register(i, new_index);
- new_index++;
foreach_iter(exec_list_iterator, iter, this->instructions) {
glsl_to_tgsi_instruction *inst = (glsl_to_tgsi_instruction *)iter.get();
unsigned j;
@@ -4026,8 +4023,6 @@ void glsl_to_tgsi_visitor::renumber_temp_regs(unsigned *reindex_table)
inst->dst.index = reindex_table[index];
}
}
-
- this->next_temp = new_index;
}
/**
@@ -5286,10 +5281,9 @@ get_mesa_program(struct gl_context *ctx,
*/
if (!v->indirect_addr_temps) {
v->eliminate_dead_code();
- v->merge_registers();
- v->renumber_registers();
}
-
+ v->regalloc();
+
/* Write the END instruction. */
v->emit(NULL, TGSI_OPCODE_END);
--
1.7.7
More information about the mesa-dev
mailing list