Mesa (master): r300/compiler: implement elimination of unused constants

Marek Olšák mareko at kemper.freedesktop.org
Wed Aug 25 00:44:56 UTC 2010


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

Author: Marek Olšák <maraeo at gmail.com>
Date:   Mon Aug 23 05:48:39 2010 +0200

r300/compiler: implement elimination of unused constants

Wine likes to create a *lot* of constants, exceeding the size of the constant
file in hw.

---

 src/mesa/drivers/dri/r300/compiler/Makefile        |    1 +
 src/mesa/drivers/dri/r300/compiler/SConscript      |    1 +
 src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c |    8 ++
 src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c |    9 ++
 src/mesa/drivers/dri/r300/compiler/radeon_code.h   |    2 +
 .../drivers/dri/r300/compiler/radeon_compiler.h    |    5 +-
 .../dri/r300/compiler/radeon_remove_constants.c    |  128 ++++++++++++++++++++
 .../dri/r300/compiler/radeon_remove_constants.h    |   36 ++++++
 8 files changed, 189 insertions(+), 1 deletions(-)

diff --git a/src/mesa/drivers/dri/r300/compiler/Makefile b/src/mesa/drivers/dri/r300/compiler/Makefile
index 3167d49..d0eb170 100644
--- a/src/mesa/drivers/dri/r300/compiler/Makefile
+++ b/src/mesa/drivers/dri/r300/compiler/Makefile
@@ -23,6 +23,7 @@ C_SOURCES = \
 		radeon_dataflow_deadcode.c \
 		radeon_dataflow_swizzles.c \
 		radeon_optimize.c \
+		radeon_remove_constants.c \
 		radeon_rename_regs.c \
 		r3xx_fragprog.c \
 		r300_fragprog.c \
diff --git a/src/mesa/drivers/dri/r300/compiler/SConscript b/src/mesa/drivers/dri/r300/compiler/SConscript
index c6f47a6..9729441 100755
--- a/src/mesa/drivers/dri/r300/compiler/SConscript
+++ b/src/mesa/drivers/dri/r300/compiler/SConscript
@@ -22,6 +22,7 @@ r300compiler = env.ConvenienceLibrary(
         'radeon_pair_schedule.c',
         'radeon_pair_regalloc.c',
         'radeon_optimize.c',
+        'radeon_remove_constants.c'
         'radeon_rename_regs.c',
         'radeon_emulate_branches.c',
         'radeon_emulate_loops.c',
diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
index 59f4efc..8613ec5 100644
--- a/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
+++ b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
@@ -30,6 +30,7 @@
 #include "radeon_program_alu.h"
 #include "radeon_program_tex.h"
 #include "radeon_rename_regs.h"
+#include "radeon_remove_constants.h"
 #include "r300_fragprog.h"
 #include "r300_fragprog_swizzle.h"
 #include "r500_fragprog.h"
@@ -180,6 +181,13 @@ void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c)
 
 	debug_program_log(c, "after dataflow passes");
 
+	if (c->Base.remove_unused_constants) {
+		rc_remove_unused_constants(&c->Base,
+					   &c->code->constants_remap_table);
+
+		debug_program_log(c, "after constants cleanup");
+	}
+
 	if(!c->Base.is_r500) {
 		/* This pass makes it easier for the scheduler to group TEX
 		 * instructions and reduces the chances of creating too
diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c
index 5009ab9..997c091 100644
--- a/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c
+++ b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c
@@ -31,6 +31,7 @@
 #include "radeon_swizzle.h"
 #include "radeon_emulate_branches.h"
 #include "radeon_emulate_loops.h"
+#include "radeon_remove_constants.h"
 
 struct loop {
 	int BgnLoop;
@@ -993,6 +994,14 @@ void r3xx_compile_vertex_program(struct r300_vertex_program_compiler *c)
 
 	debug_program_log(c, "after register allocation");
 
+	if (c->Base.remove_unused_constants) {
+		rc_remove_unused_constants(&c->Base,
+					   &c->code->constants_remap_table);
+		if (c->Base.Error)
+			return;
+
+		debug_program_log(c, "after constants cleanup");
+	}
 
 	translate_vertex_program(c);
 	if (c->Base.Error)
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_code.h b/src/mesa/drivers/dri/r300/compiler/radeon_code.h
index 896246d..f76676f 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_code.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_code.h
@@ -235,6 +235,7 @@ struct rX00_fragment_program_code {
 	unsigned writes_depth:1;
 
 	struct rc_constant_list constants;
+	unsigned *constants_remap_table;
 };
 
 
@@ -266,6 +267,7 @@ struct r300_vertex_program_code {
 	int outputs[VSF_MAX_OUTPUTS];
 
 	struct rc_constant_list constants;
+	unsigned *constants_remap_table;
 
 	uint32_t InputsRead;
 	uint32_t OutputsWritten;
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h
index 7c42eb3..5155b91 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_compiler.h
@@ -39,9 +39,12 @@ struct radeon_compiler {
 	char * ErrorMsg;
 
 	/* Hardware specification. */
-	unsigned is_r500;
+	unsigned is_r500:1;
 	unsigned max_temp_regs;
 
+	/* Whether to remove unused constants and empty holes in constant space. */
+	unsigned remove_unused_constants:1;
+
 	/**
 	 * Variables used internally, not be touched by callers
 	 * of the compiler
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.c b/src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.c
new file mode 100644
index 0000000..be89e9f
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2010 Marek Olšák <maraeo at gmail.com>
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "radeon_remove_constants.h"
+
+void rc_remove_unused_constants(struct radeon_compiler *c,
+                                unsigned **out_remap_table)
+{
+        unsigned char *const_used;
+        unsigned *remap_table;
+        unsigned *inv_remap_table;
+        unsigned has_rel_addr = 0;
+        unsigned is_identity = 1;
+	unsigned are_externals_remapped = 0;
+        struct rc_constant *constants = c->Program.Constants.Constants;
+
+        if (!c->Program.Constants.Count) {
+                *out_remap_table = NULL;
+                return;
+        }
+
+        const_used = malloc(c->Program.Constants.Count);
+        memset(const_used, 0, c->Program.Constants.Count);
+
+	/* Pass 1: Mark used constants. */
+        for (struct rc_instruction *inst = c->Program.Instructions.Next;
+             inst != &c->Program.Instructions; inst = inst->Next) {
+                const struct rc_opcode_info *opcode = rc_get_opcode_info(inst->U.I.Opcode);
+
+                for (unsigned i = 0; i < opcode->NumSrcRegs; i++) {
+                        if (inst->U.I.SrcReg[i].File == RC_FILE_CONSTANT) {
+                                if (inst->U.I.SrcReg[i].RelAddr) {
+                                        has_rel_addr = 1;
+                                } else {
+                                        const_used[inst->U.I.SrcReg[i].Index] = 1;
+                                }
+                        }
+                }
+        }
+
+        /* Pass 2: If there is relative addressing, mark all externals as used. */
+        if (has_rel_addr) {
+                for (unsigned i = 0; i < c->Program.Constants.Count; i++)
+                        if (constants[i].Type == RC_CONSTANT_EXTERNAL)
+                                const_used[i] = 1;
+        }
+
+        /* Pass 3: Make the remapping table and remap constants.
+	 * This pass removes unused constants simply by overwriting them by other constants. */
+        remap_table = malloc(c->Program.Constants.Count * sizeof(unsigned));
+        inv_remap_table = malloc(c->Program.Constants.Count * sizeof(unsigned));
+        unsigned new_count = 0;
+
+        for (unsigned i = 0; i < c->Program.Constants.Count; i++) {
+                if (const_used[i]) {
+                        remap_table[new_count] = i;
+                        inv_remap_table[i] = new_count;
+
+                        if (i != new_count) {
+				if (constants[i].Type == RC_CONSTANT_EXTERNAL)
+					are_externals_remapped = 1;
+
+				constants[new_count] = constants[i];
+                                is_identity = 0;
+                        }
+                        new_count++;
+                }
+        }
+
+	/*  is_identity ==> new_count == old_count
+	 * !is_identity ==> new_count <  old_count */
+	assert( is_identity || new_count <  c->Program.Constants.Count);
+	assert(!(has_rel_addr && are_externals_remapped));
+
+        /* Pass 4: Redirect reads of all constants to their new locations. */
+        if (!is_identity) {
+                for (struct rc_instruction *inst = c->Program.Instructions.Next;
+                     inst != &c->Program.Instructions; inst = inst->Next) {
+                        const struct rc_opcode_info *opcode = rc_get_opcode_info(inst->U.I.Opcode);
+
+                        for (unsigned i = 0; i < opcode->NumSrcRegs; i++) {
+                                if (inst->U.I.SrcReg[i].File == RC_FILE_CONSTANT) {
+                                        inst->U.I.SrcReg[i].Index = inv_remap_table[inst->U.I.SrcReg[i].Index];
+                                }
+                        }
+                }
+
+	}
+
+	/* Set the new constant count. Note that new_count may be less than
+	 * Count even though the remapping function is identity. In that case,
+	 * the constants have been removed at the end of the array. */
+	c->Program.Constants.Count = new_count;
+
+	if (are_externals_remapped) {
+                *out_remap_table = remap_table;
+        } else {
+                *out_remap_table = NULL;
+                free(remap_table);
+        }
+
+        free(const_used);
+        free(inv_remap_table);
+}
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.h b/src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.h
new file mode 100644
index 0000000..0d3a26c
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_remove_constants.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2010 Marek Olšák <maraeo at gmail.com>
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef RADEON_REMOVE_CONSTANTS_H
+#define RADEON_REMOVE_CONSTANTS_H
+
+#include "radeon_compiler.h"
+
+void rc_remove_unused_constants(struct radeon_compiler *c,
+                                unsigned **out_remap_table);
+
+#endif




More information about the mesa-commit mailing list