r300/compiler: Add remove dead sources pass
authorTom Stellard <tstellar@gmail.com>
Sat, 26 Mar 2011 00:05:53 +0000 (17:05 -0700)
committerTom Stellard <tstellar@gmail.com>
Sat, 30 Apr 2011 18:00:15 +0000 (11:00 -0700)
The instruction scheduler will sometimes leave orphaned sources when
converting instructions from RGB to Alpha.  If one of these orphaned
sources has an index greater than the maximum temporary register index,
then the compiler will incorrectly report "Too many hardware temporaries
used".  The dead sources pass cleans up these orphaned sources.

src/mesa/drivers/dri/r300/compiler/Makefile
src/mesa/drivers/dri/r300/compiler/SConscript
src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
src/mesa/drivers/dri/r300/compiler/radeon_pair_dead_sources.c [new file with mode: 0644]
src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h

index 51b896ae91f4c0ac1eda813e35731643fcce2246..90bd8e86768a655e82cd09dc22b2257f6b483490 100644 (file)
@@ -20,6 +20,7 @@ C_SOURCES = \
                radeon_pair_translate.c \
                radeon_pair_schedule.c \
                radeon_pair_regalloc.c \
+               radeon_pair_dead_sources.c \
                radeon_dataflow.c \
                radeon_dataflow_deadcode.c \
                radeon_dataflow_swizzles.c \
index 2b4bce1c08c86d63cffeae43ae977c629b767100..d44b745562c6a768d17af84bc26b914b9bb38025 100755 (executable)
@@ -22,6 +22,7 @@ r300compiler = env.ConvenienceLibrary(
         'radeon_pair_translate.c',
         'radeon_pair_schedule.c',
         'radeon_pair_regalloc.c',
+       'radeon_pair_dead_sources.c',
         'radeon_optimize.c',
         'radeon_remove_constants.c',
         'radeon_rename_regs.c',
index 9286733635fcc5c44ba13da355fc148e2502f7b4..cdfda0b3196b88b16e4c06733d4f15ec5c9c2044 100644 (file)
@@ -148,6 +148,7 @@ void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c)
                {"register rename",             1, !is_r500,    rc_rename_regs,                 NULL},
                {"pair translate",              1, 1,           rc_pair_translate,              NULL},
                {"pair scheduling",             1, 1,           rc_pair_schedule,               NULL},
+               {"dead sources",                1, 1,           rc_pair_remove_dead_sources, NULL},
                {"register allocation",         1, opt,         rc_pair_regalloc,               NULL},
                {"dumb register allocation",    1, !opt,        rc_pair_regalloc_inputs_only,   NULL},
                {"final code validation",       0, 1,           rc_validate_final_shader,       NULL},
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_pair_dead_sources.c b/src/mesa/drivers/dri/r300/compiler/radeon_pair_dead_sources.c
new file mode 100644 (file)
index 0000000..1e9a2c0
--- /dev/null
@@ -0,0 +1,62 @@
+
+#include "radeon_compiler.h"
+#include "radeon_compiler_util.h"
+#include "radeon_opcodes.h"
+#include "radeon_program_pair.h"
+
+static void mark_used_presub(struct rc_pair_sub_instruction * sub)
+{
+       if (sub->Src[RC_PAIR_PRESUB_SRC].Used) {
+               unsigned int presub_reg_count = rc_presubtract_src_reg_count(
+                                       sub->Src[RC_PAIR_PRESUB_SRC].Index);
+               unsigned int i;
+               for (i = 0; i < presub_reg_count; i++) {
+                       sub->Src[i].Used = 1;
+               }
+       }
+}
+
+static void mark_used(
+       struct rc_instruction * inst,
+       struct rc_pair_sub_instruction * sub)
+{
+       unsigned int i;
+       const struct rc_opcode_info * info = rc_get_opcode_info(sub->Opcode);
+       for (i = 0; i < info->NumSrcRegs; i++) {
+               unsigned int src_type = rc_source_type_swz(sub->Arg[i].Swizzle);
+               if (src_type & RC_SOURCE_RGB) {
+                       inst->U.P.RGB.Src[sub->Arg[i].Source].Used = 1;
+               }
+
+               if (src_type & RC_SOURCE_ALPHA) {
+                       inst->U.P.Alpha.Src[sub->Arg[i].Source].Used = 1;
+               }
+       }
+}
+
+/**
+ * This pass finds sources that are not used by their instruction and marks
+ * them as unused. 
+ */
+void rc_pair_remove_dead_sources(struct radeon_compiler * c, void *user)
+{
+       struct rc_instruction * inst;
+       for (inst = c->Program.Instructions.Next;
+                                       inst != &c->Program.Instructions;
+                                       inst = inst->Next) {
+               unsigned int i;
+               if (inst->Type == RC_INSTRUCTION_NORMAL)
+                       continue;
+
+               /* Mark all sources as unused */
+               for (i = 0; i < 4; i++) {
+                       inst->U.P.RGB.Src[i].Used = 0;
+                       inst->U.P.Alpha.Src[i].Used = 0;
+               }
+               mark_used(inst, &inst->U.P.RGB);
+               mark_used(inst, &inst->U.P.Alpha);
+
+               mark_used_presub(&inst->U.P.RGB);
+               mark_used_presub(&inst->U.P.Alpha);
+       }
+}
index d1a435fc5303b3ed36521c8117b562cd8824464a..82d7815aa78ff1fe6523eaf030467e13bec79f4a 100644 (file)
@@ -127,6 +127,7 @@ void rc_pair_translate(struct radeon_compiler *cc, void *user);
 void rc_pair_schedule(struct radeon_compiler *cc, void *user);
 void rc_pair_regalloc(struct radeon_compiler *cc, void *user);
 void rc_pair_regalloc_inputs_only(struct radeon_compiler *cc, void *user);
+void rc_pair_remove_dead_sources(struct radeon_compiler *c, void *user);
 /*@}*/
 
 #endif /* __RADEON_PROGRAM_PAIR_H_ */