[Mesa-dev] [PATCH 3/3] glsl_to_tgsi: Use mesa register allocator

Tom Stellard thomas.stellard at amd.com
Fri Jan 6 11:28:14 PST 2012


On Fri, 2012-01-06 at 20:15 +0100, Vincent Lejeune wrote:
> ---
>  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);
> +   }
> +

i < + 32
This looks like  a typo.

> +   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);
>  





More information about the mesa-dev mailing list