r300/compiler: Add a more efficient version of rc_find_free_temporary()

This commit is contained in:
Tom Stellard
2010-11-12 00:59:13 -08:00
parent 8833f53e65
commit 1b6ed80972
3 changed files with 113 additions and 26 deletions
@@ -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;
}
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)
{
struct get_used_temporaries_data * d = userdata;
if (file != RC_FILE_TEMPORARY)
return;
if (index >= d->UsedLength)
return;
d->Used[index] |= mask;
}
/**
* 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);
}
}
/* 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;
}
unsigned int rc_find_free_temporary(struct radeon_compiler * c)
{
char used[RC_REGISTER_MAX_INDEX];
unsigned int i;
struct rc_instruction * rcinst;
unsigned char used[RC_REGISTER_MAX_INDEX];
int free;
memset(used, 0, sizeof(used));
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;
rc_get_used_temporaries(c, used, RC_REGISTER_MAX_INDEX);
for (k = 0; k < opcode->NumSrcRegs; k++) {
if (inst->SrcReg[k].File == RC_FILE_TEMPORARY)
used[inst->SrcReg[k].Index] = 1;
}
if (opcode->HasDstReg) {
if (inst->DstReg.File == RC_FILE_TEMPORARY)
used[inst->DstReg.Index] = 1;
}
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;
}
for (i = 0; i < RC_REGISTER_MAX_INDEX; i++) {
if (!used[i])
return i;
}
rc_error(c, "Ran out of temporary registers\n");
return 0;
return free;
}
@@ -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);
@@ -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;