r300/compiler: Add a more efficient version of rc_find_free_temporary()
authorTom Stellard <tstellar@gmail.com>
Fri, 12 Nov 2010 08:59:13 +0000 (00:59 -0800)
committerTom Stellard <tstellar@gmail.com>
Mon, 22 Nov 2010 02:48:31 +0000 (18:48 -0800)
src/mesa/drivers/dri/r300/compiler/radeon_program.c
src/mesa/drivers/dri/r300/compiler/radeon_program.h
src/mesa/drivers/dri/r300/compiler/radeon_rename_regs.c

index 14dade9be7827bd4db3870e29640dd6f107a06b2..d7bedc57291938ce887ca56e0b98b70b7e1cb2bb 100644 (file)
@@ -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;
 }
 
 
index a4d50d3663883414c34ea85c7127c9b4d52faa22..be078b4f4fa596a8fac216d3939ab6b7fd6283f8 100644 (file)
@@ -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);
index 87ec3dca069e7160dd1b5cdc3cc8a6f4810cc0da..88165f78953e456c80ed2672cf289c0967a1391c 100644 (file)
@@ -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
  */
 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;