r300/compiler: Add a more efficient version of rc_find_free_temporary()
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user