#include <stdio.h>
#include "radeon_compiler.h"
+#include "radeon_dataflow.h"
/**
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;
}
#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
*/
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) {
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;