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

Tom Stellard tstellar at kemper.freedesktop.org
Mon Nov 22 05:41:38 UTC 2010


Module: Mesa
Branch: master
Commit: 1b6ed809729dd3adee4adfa87c227bbd98d9f23a
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=1b6ed809729dd3adee4adfa87c227bbd98d9f23a

Author: Tom Stellard <tstellar at gmail.com>
Date:   Fri Nov 12 00:59:13 2010 -0800

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

---

 .../drivers/dri/r300/compiler/radeon_program.c     |  104 ++++++++++++++++----
 .../drivers/dri/r300/compiler/radeon_program.h     |   11 ++
 .../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 14dade9..d7bedc5 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 a4d50d3..be078b4 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 87ec3dc..88165f7 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;




More information about the mesa-commit mailing list