diff options
-rw-r--r-- | src/mesa/drivers/dri/r300/compiler/radeon_program.c | 104 | ||||
-rw-r--r-- | src/mesa/drivers/dri/r300/compiler/radeon_program.h | 11 | ||||
-rw-r--r-- | src/mesa/drivers/dri/r300/compiler/radeon_rename_regs.c | 18 |
3 files changed, 110 insertions, 23 deletions
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 <stdio.h> #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; |