From 8833f53e659e079e7ab74bb9197f9b44b1eeefe0 Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Wed, 10 Nov 2010 21:34:18 -0800 Subject: r300/compiler: Enable rename_reg pass for r500 cards In addition, the rename_reg pass has been rewritten to use rc_get_readers(). --- .../drivers/dri/r300/compiler/radeon_rename_regs.c | 93 ++++------------------ 1 file changed, 15 insertions(+), 78 deletions(-) (limited to 'src/mesa/drivers/dri/r300/compiler/radeon_rename_regs.c') diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_rename_regs.c b/src/mesa/drivers/dri/r300/compiler/radeon_rename_regs.c index 60e228be5b..87ec3dca06 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_rename_regs.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_rename_regs.c @@ -34,99 +34,36 @@ #include "radeon_compiler.h" #include "radeon_dataflow.h" -struct reg_rename { - int old_index; - int new_index; - int temp_index; -}; - -static void rename_reg(void * data, struct rc_instruction * inst, - rc_register_file * file, unsigned int * index) -{ - struct reg_rename *r = data; - - if(r->old_index == *index && *file == RC_FILE_TEMPORARY) { - *index = r->new_index; - } - else if(r->new_index == *index && *file == RC_FILE_TEMPORARY) { - *index = r->temp_index; - } -} - -static void rename_all( - struct radeon_compiler *c, - struct rc_instruction * start, - unsigned int old, - unsigned int new, - unsigned int temp) -{ - struct rc_instruction * inst; - struct reg_rename r; - r.old_index = old; - r.new_index = new; - r.temp_index = temp; - for(inst = start; inst != &c->Program.Instructions; - inst = inst->Next) { - rc_remap_registers(inst, rename_reg, &r); - } -} - /** * This function renames registers in an attempt to get the code close to * SSA form. After this function has completed, most of the register are only - * written to one time, with a few exceptions. For example, this block of code - * will not be modified by this function: - * Mov Temp[0].x Const[0].x - * Mov Temp[0].y Const[0].y - * Basically, destination registers will be renamed if: - * 1. There have been no previous writes to that register - * or - * 2. If the instruction is writting to the exact components (no more, no less) - * of a register that has been written to by previous instructions. + * written to one time, with a few exceptions. * * This function assumes all the instructions are still of type * RC_INSTRUCTION_NORMAL. */ void rc_rename_regs(struct radeon_compiler *c, void *user) { - unsigned int cur_index = 0; - unsigned int icount; + unsigned int new_index, i; struct rc_instruction * inst; - unsigned int * masks; - - /* The number of instructions in the program is also the maximum - * number of temp registers that could potentially be used. */ - icount = rc_recompute_ips(c); - masks = memory_pool_malloc(&c->Pool, icount * sizeof(unsigned int)); - memset(masks, 0, icount * sizeof(unsigned int)); + struct rc_reader_data reader_data; for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) { - const struct rc_opcode_info * info; - unsigned int old_index, temp_index; - struct rc_dst_register * dst; - if(inst->Type != RC_INSTRUCTION_NORMAL) { - rc_error(c, "%s only works with normal instructions.", - __FUNCTION__); - return; - } - dst = &inst->U.I.DstReg; - info = rc_get_opcode_info(inst->U.I.Opcode); - if(!info->HasDstReg || dst->File != RC_FILE_TEMPORARY) { + + if (inst->U.I.DstReg.File != RC_FILE_TEMPORARY) continue; + + rc_get_readers(c, inst, &reader_data, NULL, NULL, NULL); + + if (reader_data.Abort || reader_data.ReaderCount == 0) + continue; + + new_index = rc_find_free_temporary(c); + reader_data.Writer->U.I.DstReg.Index = new_index; + for(i = 0; i < reader_data.ReaderCount; i++) { + reader_data.Readers[i].U.Src->Index = new_index; } - if(dst->Index >= icount || !masks[dst->Index] || - masks[dst->Index] == dst->WriteMask) { - old_index = dst->Index; - /* We need to set dst->Index here so get free temporary - * will work. */ - dst->Index = cur_index++; - temp_index = rc_find_free_temporary(c); - rename_all(c, inst->Next, old_index, - dst->Index, temp_index); - } - assert(dst->Index < icount); - masks[dst->Index] |= dst->WriteMask; } } -- cgit v1.2.3 From 1b6ed809729dd3adee4adfa87c227bbd98d9f23a Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Fri, 12 Nov 2010 00:59:13 -0800 Subject: r300/compiler: Add a more efficient version of rc_find_free_temporary() --- .../drivers/dri/r300/compiler/radeon_program.c | 104 ++++++++++++++++----- .../drivers/dri/r300/compiler/radeon_program.h | 11 +++ .../drivers/dri/r300/compiler/radeon_rename_regs.c | 18 +++- 3 files changed, 110 insertions(+), 23 deletions(-) (limited to 'src/mesa/drivers/dri/r300/compiler/radeon_rename_regs.c') diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program.c b/src/mesa/drivers/dri/r300/compiler/radeon_program.c index 14dade9be7..d7bedc5729 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program.c @@ -30,6 +30,7 @@ #include #include "radeon_compiler.h" +#include "radeon_dataflow.h" /** @@ -91,37 +92,98 @@ struct rc_src_register lmul_swizzle(unsigned int swizzle, struct rc_src_register return tmp; } -unsigned int rc_find_free_temporary(struct radeon_compiler * c) +struct get_used_temporaries_data { + unsigned char * Used; + unsigned int UsedLength; +}; + +static void get_used_temporaries_cb( + void * userdata, + struct rc_instruction * inst, + rc_register_file file, + unsigned int index, + unsigned int mask) { - char used[RC_REGISTER_MAX_INDEX]; - unsigned int i; - struct rc_instruction * rcinst; + struct get_used_temporaries_data * d = userdata; - memset(used, 0, sizeof(used)); + if (file != RC_FILE_TEMPORARY) + return; - for (rcinst = c->Program.Instructions.Next; rcinst != &c->Program.Instructions; rcinst = rcinst->Next) { - const struct rc_sub_instruction *inst = &rcinst->U.I; - const struct rc_opcode_info *opcode = rc_get_opcode_info(inst->Opcode); - unsigned int k; + if (index >= d->UsedLength) + return; - for (k = 0; k < opcode->NumSrcRegs; k++) { - if (inst->SrcReg[k].File == RC_FILE_TEMPORARY) - used[inst->SrcReg[k].Index] = 1; - } + d->Used[index] |= mask; +} - if (opcode->HasDstReg) { - if (inst->DstReg.File == RC_FILE_TEMPORARY) - used[inst->DstReg.Index] = 1; - } +/** + * This function fills in the parameter 'used' with a writemask that + * represent which components of each temporary register are used by the + * program. This is meant to be combined with rc_find_free_temporary_list as a + * more efficient version of rc_find_free_temporary. + * @param used The function does not initialize this parameter. + */ +void rc_get_used_temporaries( + struct radeon_compiler * c, + unsigned char * used, + unsigned int used_length) +{ + struct rc_instruction * inst; + struct get_used_temporaries_data d; + d.Used = used; + d.UsedLength = used_length; + + for(inst = c->Program.Instructions.Next; + inst != &c->Program.Instructions; inst = inst->Next) { + + rc_for_all_reads_mask(inst, get_used_temporaries_cb, &d); + rc_for_all_writes_mask(inst, get_used_temporaries_cb, &d); } +} - for (i = 0; i < RC_REGISTER_MAX_INDEX; i++) { - if (!used[i]) +/* Search a list of used temporaries for a free one + * \sa rc_get_used_temporaries + * @note If this functions finds a free temporary, it will mark it as used + * in the used temporary list (param 'used') + * @param used list of used temporaries + * @param used_length number of items in param 'used' + * @param mask which components must be free in the temporary index that is + * returned. + * @return -1 If there are no more free temporaries, otherwise the index of + * a temporary register where the components specified in param 'mask' are + * not being used. + */ +int rc_find_free_temporary_list( + struct radeon_compiler * c, + unsigned char * used, + unsigned int used_length, + unsigned int mask) +{ + int i; + for(i = 0; i < used_length; i++) { + if ((~used[i] & mask) == mask) { + used[i] |= mask; return i; + } } + return -1; +} - rc_error(c, "Ran out of temporary registers\n"); - return 0; +unsigned int rc_find_free_temporary(struct radeon_compiler * c) +{ + unsigned char used[RC_REGISTER_MAX_INDEX]; + int free; + + memset(used, 0, sizeof(used)); + + rc_get_used_temporaries(c, used, RC_REGISTER_MAX_INDEX); + + free = rc_find_free_temporary_list(c, used, RC_REGISTER_MAX_INDEX, + RC_MASK_XYZW); + if (free < 0) { + rc_error(c, "Ran out of temporary registers\n"); + return 0; + } + return free; } diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program.h b/src/mesa/drivers/dri/r300/compiler/radeon_program.h index a4d50d3663..be078b4f4f 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program.h @@ -236,6 +236,17 @@ void rc_local_transform( struct radeon_compiler *c, void *user); +void rc_get_used_temporaries( + struct radeon_compiler * c, + unsigned char * used, + unsigned int used_length); + +int rc_find_free_temporary_list( + struct radeon_compiler * c, + unsigned char * used, + unsigned int used_length, + unsigned int mask); + unsigned int rc_find_free_temporary(struct radeon_compiler * c); struct rc_instruction *rc_alloc_instruction(struct radeon_compiler * c); diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_rename_regs.c b/src/mesa/drivers/dri/r300/compiler/radeon_rename_regs.c index 87ec3dca06..88165f7895 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_rename_regs.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_rename_regs.c @@ -33,6 +33,7 @@ #include "radeon_compiler.h" #include "radeon_dataflow.h" +#include "radeon_program.h" /** * This function renames registers in an attempt to get the code close to @@ -44,10 +45,17 @@ */ void rc_rename_regs(struct radeon_compiler *c, void *user) { - unsigned int new_index, i; + unsigned int i, used_length; + int new_index; struct rc_instruction * inst; struct rc_reader_data reader_data; + unsigned char * used; + used_length = 2 * rc_recompute_ips(c); + used = memory_pool_malloc(&c->Pool, sizeof(unsigned char) * used_length); + memset(used, 0, sizeof(unsigned char) * used_length); + + rc_get_used_temporaries(c, used, used_length); for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) { @@ -60,7 +68,13 @@ void rc_rename_regs(struct radeon_compiler *c, void *user) if (reader_data.Abort || reader_data.ReaderCount == 0) continue; - new_index = rc_find_free_temporary(c); + new_index = rc_find_free_temporary_list(c, used, used_length, + RC_MASK_XYZW); + if (new_index < 0) { + rc_error(c, "Ran out of temporary registers\n"); + return; + } + reader_data.Writer->U.I.DstReg.Index = new_index; for(i = 0; i < reader_data.ReaderCount; i++) { reader_data.Readers[i].U.Src->Index = new_index; -- cgit v1.2.3