Mesa (master): r300/compiler: Introduce control flow instructions and refactor dataflow

Nicolai Hähnle nh at kemper.freedesktop.org
Wed Oct 7 18:48:18 UTC 2009


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

Author: Nicolai Hähnle <nhaehnle at gmail.com>
Date:   Sat Oct  3 21:28:59 2009 +0200

r300/compiler: Introduce control flow instructions and refactor dataflow

Note that control flow instruction support isn't actually fully functional yet.

Signed-off-by: Nicolai Hähnle <nhaehnle at gmail.com>

---

 src/gallium/drivers/r300/r300_tgsi_to_rc.c         |    6 +-
 src/mesa/drivers/dri/r300/compiler/Makefile        |    3 +-
 src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c |   15 +-
 src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c |   18 +-
 .../drivers/dri/r300/compiler/radeon_dataflow.c    |   74 ----
 .../drivers/dri/r300/compiler/radeon_dataflow.h    |   69 +----
 .../dri/r300/compiler/radeon_dataflow_annotate.c   |  365 --------------------
 .../dri/r300/compiler/radeon_dataflow_deadcode.c   |  253 ++++++++++++++
 .../dri/r300/compiler/radeon_dataflow_dealias.c    |  150 --------
 .../dri/r300/compiler/radeon_dataflow_swizzles.c   |   24 --
 .../drivers/dri/r300/compiler/radeon_opcodes.c     |   78 +++++
 .../drivers/dri/r300/compiler/radeon_opcodes.h     |   20 +
 .../drivers/dri/r300/compiler/radeon_program.c     |   19 +-
 .../drivers/dri/r300/compiler/radeon_program.h     |   71 ++--
 .../dri/r300/compiler/radeon_program_print.c       |   48 +---
 15 files changed, 434 insertions(+), 779 deletions(-)

diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.c b/src/gallium/drivers/r300/r300_tgsi_to_rc.c
index 7f12008..1246ffe 100644
--- a/src/gallium/drivers/r300/r300_tgsi_to_rc.c
+++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.c
@@ -106,11 +106,11 @@ static unsigned translate_opcode(unsigned opcode)
      /* case TGSI_OPCODE_DP2: return RC_OPCODE_DP2; */
         case TGSI_OPCODE_TXL: return RC_OPCODE_TXL;
      /* case TGSI_OPCODE_BRK: return RC_OPCODE_BRK; */
-     /* case TGSI_OPCODE_IF: return RC_OPCODE_IF; */
+        case TGSI_OPCODE_IF: return RC_OPCODE_IF;
      /* case TGSI_OPCODE_LOOP: return RC_OPCODE_LOOP; */
      /* case TGSI_OPCODE_REP: return RC_OPCODE_REP; */
-     /* case TGSI_OPCODE_ELSE: return RC_OPCODE_ELSE; */
-     /* case TGSI_OPCODE_ENDIF: return RC_OPCODE_ENDIF; */
+        case TGSI_OPCODE_ELSE: return RC_OPCODE_ELSE;
+        case TGSI_OPCODE_ENDIF: return RC_OPCODE_ENDIF;
      /* case TGSI_OPCODE_ENDLOOP: return RC_OPCODE_ENDLOOP; */
      /* case TGSI_OPCODE_ENDREP: return RC_OPCODE_ENDREP; */
      /* case TGSI_OPCODE_PUSHA: return RC_OPCODE_PUSHA; */
diff --git a/src/mesa/drivers/dri/r300/compiler/Makefile b/src/mesa/drivers/dri/r300/compiler/Makefile
index 53fb7ca..0d8dcb9 100644
--- a/src/mesa/drivers/dri/r300/compiler/Makefile
+++ b/src/mesa/drivers/dri/r300/compiler/Makefile
@@ -14,8 +14,7 @@ C_SOURCES = \
 		radeon_program_alu.c \
 		radeon_program_pair.c \
 		radeon_dataflow.c \
-		radeon_dataflow_annotate.c \
-		radeon_dataflow_dealias.c \
+		radeon_dataflow_deadcode.c \
 		radeon_dataflow_swizzles.c \
 		r3xx_fragprog.c \
 		r300_fragprog.c \
diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
index bf9bea6..590201a 100644
--- a/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
+++ b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
@@ -24,6 +24,7 @@
 
 #include <stdio.h>
 
+#include "radeon_dataflow.h"
 #include "radeon_program_alu.h"
 #include "r300_fragprog.h"
 #include "r300_fragprog_swizzle.h"
@@ -107,17 +108,23 @@ void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c)
 
 	if (c->Base.Debug) {
 		fprintf(stderr, "Fragment Program: After native rewrite:\n");
-		rc_print_program(&c->Base.Program, 0);
+		rc_print_program(&c->Base.Program);
+		fflush(stderr);
+	}
+
+	rc_dataflow_deadcode(&c->Base, &dataflow_outputs_mark_use, c);
+
+	if (c->Base.Debug) {
+		fprintf(stderr, "Fragment Program: After deadcode:\n");
+		rc_print_program(&c->Base.Program);
 		fflush(stderr);
 	}
 
-	rc_dataflow_annotate(&c->Base, &dataflow_outputs_mark_use, c);
-	rc_dataflow_dealias(&c->Base);
 	rc_dataflow_swizzles(&c->Base);
 
 	if (c->Base.Debug) {
 		fprintf(stderr, "Compiler: after dataflow passes:\n");
-		rc_print_program(&c->Base.Program, 0);
+		rc_print_program(&c->Base.Program);
 		fflush(stderr);
 	}
 
diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c
index ac72f8c..e1e7355 100644
--- a/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c
+++ b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c
@@ -588,7 +588,7 @@ void r3xx_compile_vertex_program(struct r300_vertex_program_compiler* compiler)
 
 	if (compiler->Base.Debug) {
 		fprintf(stderr, "Vertex program after native rewrite:\n");
-		rc_print_program(&compiler->Base.Program, 0);
+		rc_print_program(&compiler->Base.Program);
 		fflush(stderr);
 	}
 
@@ -605,21 +605,25 @@ void r3xx_compile_vertex_program(struct r300_vertex_program_compiler* compiler)
 
 	if (compiler->Base.Debug) {
 		fprintf(stderr, "Vertex program after source conflict resolve:\n");
-		rc_print_program(&compiler->Base.Program, 0);
+		rc_print_program(&compiler->Base.Program);
+		fflush(stderr);
+	}
+
+	rc_dataflow_deadcode(&compiler->Base, &dataflow_outputs_mark_used, compiler);
+
+	if (compiler->Base.Debug) {
+		fprintf(stderr, "Vertex program after deadcode:\n");
+		rc_print_program(&compiler->Base.Program);
 		fflush(stderr);
 	}
 
-	rc_dataflow_annotate(&compiler->Base, &dataflow_outputs_mark_used, compiler);
-	rc_dataflow_dealias(&compiler->Base);
 	rc_dataflow_swizzles(&compiler->Base);
 
-	/* This invalidates dataflow annotations and should be replaced
-	 * by a future generic register allocation pass. */
 	allocate_temporary_registers(compiler);
 
 	if (compiler->Base.Debug) {
 		fprintf(stderr, "Vertex program after dataflow:\n");
-		rc_print_program(&compiler->Base.Program, 0);
+		rc_print_program(&compiler->Base.Program);
 		fflush(stderr);
 	}
 
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c
index af6777a..a171d8a 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c
@@ -30,77 +30,3 @@
 #include "radeon_compiler.h"
 
 
-static void add_ref_to_vector(struct rc_dataflow_ref * ref, struct rc_dataflow_vector * vector)
-{
-	ref->Vector = vector;
-	ref->Prev = &vector->Refs;
-	ref->Next = vector->Refs.Next;
-	ref->Prev->Next = ref;
-	ref->Next->Prev = ref;
-}
-
-struct rc_dataflow_ref * rc_dataflow_create_ref(struct radeon_compiler * c,
-		struct rc_dataflow_vector * vector, struct rc_instruction * inst)
-{
-	struct rc_dataflow_ref * ref = memory_pool_malloc(&c->Pool, sizeof(struct rc_dataflow_ref));
-	ref->ReadInstruction = inst;
-	ref->UseMask = 0;
-
-	add_ref_to_vector(ref, vector);
-
-	return ref;
-}
-
-struct rc_dataflow_vector * rc_dataflow_create_vector(struct radeon_compiler * c,
-		rc_register_file file, unsigned int index, struct rc_instruction * inst)
-{
-	struct rc_dataflow_vector * vec = memory_pool_malloc(&c->Pool, sizeof(struct rc_dataflow_vector));
-
-	memset(vec, 0, sizeof(struct rc_dataflow_vector));
-	vec->File = file;
-	vec->Index = index;
-	vec->WriteInstruction = inst;
-
-	vec->Refs.Next = vec->Refs.Prev = &vec->Refs;
-
-	return vec;
-}
-
-void rc_dataflow_remove_ref(struct rc_dataflow_ref * ref)
-{
-	ref->Prev->Next = ref->Next;
-	ref->Next->Prev = ref->Prev;
-}
-
-void rc_dataflow_remove_instruction(struct rc_instruction * inst)
-{
-	for(unsigned int i = 0; i < 3; ++i) {
-		if (inst->Dataflow.SrcReg[i]) {
-			rc_dataflow_remove_ref(inst->Dataflow.SrcReg[i]);
-			inst->Dataflow.SrcReg[i] = 0;
-		}
-		if (inst->Dataflow.SrcRegAddress[i]) {
-			rc_dataflow_remove_ref(inst->Dataflow.SrcRegAddress[i]);
-			inst->Dataflow.SrcRegAddress[i] = 0;
-		}
-	}
-
-	if (inst->Dataflow.DstReg) {
-		while(inst->Dataflow.DstReg->Refs.Next != &inst->Dataflow.DstReg->Refs) {
-			struct rc_dataflow_ref * ref = inst->Dataflow.DstReg->Refs.Next;
-			rc_dataflow_remove_ref(ref);
-			if (inst->Dataflow.DstRegPrev)
-				add_ref_to_vector(ref, inst->Dataflow.DstRegPrev->Vector);
-		}
-
-		inst->Dataflow.DstReg->WriteInstruction = 0;
-		inst->Dataflow.DstReg = 0;
-	}
-
-	if (inst->Dataflow.DstRegPrev) {
-		rc_dataflow_remove_ref(inst->Dataflow.DstRegPrev);
-		inst->Dataflow.DstRegPrev = 0;
-	}
-
-	inst->Dataflow.DstRegAliased = 0;
-}
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.h b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.h
index c9856af..76c323d 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.h
@@ -34,79 +34,14 @@ struct radeon_compiler;
 struct rc_instruction;
 struct rc_swizzle_caps;
 
-struct rc_dataflow_vector;
-
-struct rc_dataflow_ref {
-	struct rc_dataflow_vector * Vector;
-
-	/**
-	 * Linked list of references to the above-mentioned vector.
-	 * The linked list is \em not sorted.
-	 */
-	/*@{*/
-	struct rc_dataflow_ref * Prev;
-	struct rc_dataflow_ref * Next;
-	/*@}*/
-
-	unsigned int UseMask:4;
-	struct rc_instruction * ReadInstruction;
-};
-
-struct rc_dataflow_vector {
-	rc_register_file File:3;
-	unsigned int Index:RC_REGISTER_INDEX_BITS;
-
-	/** For private use in compiler passes. MUST BE RESET TO 0 by the end of each pass.
-	 * The annotate pass uses this bit to track whether a vector is in the
-	 * update stack.
-	 */
-	unsigned int PassBit:1;
-	/** Which of the components have been written with useful values */
-	unsigned int ValidMask:4;
-	/** Which of the components are used downstream */
-	unsigned int UseMask:4;
-	/** The instruction that produced this vector */
-	struct rc_instruction * WriteInstruction;
-
-	/** Linked list of references to this vector */
-	struct rc_dataflow_ref Refs;
-};
-
-struct rc_instruction_dataflow {
-	struct rc_dataflow_ref * SrcReg[3];
-	struct rc_dataflow_ref * SrcRegAddress[3];
-
-	/** Reference the components of the destination register
-	 * that are carried over without being overwritten */
-	struct rc_dataflow_ref * DstRegPrev;
-	/** Indicates whether the destination register was in use
-	 * before this instruction */
-	unsigned int DstRegAliased:1;
-	struct rc_dataflow_vector * DstReg;
-};
-
-/**
- * General functions for manipulating the dataflow structures.
- */
-/*@{*/
-struct rc_dataflow_ref * rc_dataflow_create_ref(struct radeon_compiler * c,
-		struct rc_dataflow_vector * vector, struct rc_instruction * inst);
-struct rc_dataflow_vector * rc_dataflow_create_vector(struct radeon_compiler * c,
-		rc_register_file file, unsigned int index, struct rc_instruction * inst);
-void rc_dataflow_remove_ref(struct rc_dataflow_ref * ref);
-
-void rc_dataflow_remove_instruction(struct rc_instruction * inst);
-/*@}*/
-
 
 /**
- * Compiler passes based on dataflow structures.
+ * Compiler passes based on dataflow analysis.
  */
 /*@{*/
 typedef void (*rc_dataflow_mark_outputs_fn)(void * userdata, void * data,
 			void (*mark_fn)(void * data, unsigned int index, unsigned int mask));
-void rc_dataflow_annotate(struct radeon_compiler * c, rc_dataflow_mark_outputs_fn dce, void * userdata);
-void rc_dataflow_dealias(struct radeon_compiler * c);
+void rc_dataflow_deadcode(struct radeon_compiler * c, rc_dataflow_mark_outputs_fn dce, void * userdata);
 void rc_dataflow_swizzles(struct radeon_compiler * c);
 /*@}*/
 
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_annotate.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_annotate.c
deleted file mode 100644
index 41d175a..0000000
--- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_annotate.c
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Copyright (C) 2009 Nicolai Haehnle.
- *
- * 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_dataflow.h"
-
-#include "radeon_compiler.h"
-
-
-struct dataflow_state {
-	struct radeon_compiler * C;
-	unsigned int DCE:1;
-	unsigned int UpdateRunning:1;
-
-	struct rc_dataflow_vector * Input[RC_REGISTER_MAX_INDEX];
-	struct rc_dataflow_vector * Output[RC_REGISTER_MAX_INDEX];
-	struct rc_dataflow_vector * Temporary[RC_REGISTER_MAX_INDEX];
-	struct rc_dataflow_vector * Address;
-
-	struct rc_dataflow_vector ** UpdateStack;
-	unsigned int UpdateStackSize;
-	unsigned int UpdateStackReserved;
-};
-
-static void mark_vector_use(struct dataflow_state * s, struct rc_dataflow_vector * vector, unsigned int mask);
-
-static struct rc_dataflow_vector * get_register_contents(struct dataflow_state * s,
-		rc_register_file file, unsigned int index)
-{
-	if (file == RC_FILE_INPUT || file == RC_FILE_OUTPUT || file == RC_FILE_TEMPORARY) {
-		if (index >= RC_REGISTER_MAX_INDEX)
-			return 0; /* cannot happen, but be defensive */
-
-		if (file == RC_FILE_TEMPORARY)
-			return s->Temporary[index];
-		if (file == RC_FILE_INPUT)
-			return s->Input[index];
-		if (file == RC_FILE_OUTPUT)
-			return s->Output[index];
-	}
-
-	if (file == RC_FILE_ADDRESS)
-		return s->Address;
-
-	return 0; /* can happen, constant register file */
-}
-
-static void mark_ref_use(struct dataflow_state * s, struct rc_dataflow_ref * ref, unsigned int mask)
-{
-	if (!(mask & ~ref->UseMask))
-		return;
-
-	ref->UseMask |= mask;
-	mark_vector_use(s, ref->Vector, ref->UseMask);
-}
-
-static void mark_source_use(struct dataflow_state * s, struct rc_instruction * inst,
-		unsigned int src, unsigned int srcmask)
-{
-	unsigned int refmask = 0;
-
-	for(unsigned int i = 0; i < 4; ++i) {
-		if (GET_BIT(srcmask, i))
-			refmask |= 1 << GET_SWZ(inst->I.SrcReg[src].Swizzle, i);
-	}
-
-	/* get rid of spurious bits from ZERO, ONE, etc. swizzles */
-	refmask &= RC_MASK_XYZW;
-
-	if (!refmask)
-		return; /* can happen if the swizzle contains constant components */
-
-	if (inst->Dataflow.SrcReg[src])
-		mark_ref_use(s, inst->Dataflow.SrcReg[src], refmask);
-
-	if (inst->Dataflow.SrcRegAddress[src])
-		mark_ref_use(s, inst->Dataflow.SrcRegAddress[src], RC_MASK_X);
-}
-
-static void compute_sources_for_writemask(
-		struct rc_instruction * inst,
-		unsigned int writemask,
-		unsigned int *srcmasks)
-{
-	const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->I.Opcode);
-
-	srcmasks[0] = 0;
-	srcmasks[1] = 0;
-	srcmasks[2] = 0;
-
-	if (inst->I.Opcode == RC_OPCODE_KIL)
-		srcmasks[0] |= RC_MASK_XYZW;
-
-	if (!writemask)
-		return;
-
-	if (opcode->IsComponentwise) {
-		for(unsigned int src = 0; src < opcode->NumSrcRegs; ++src)
-			srcmasks[src] |= writemask;
-	} else if (opcode->IsStandardScalar) {
-		for(unsigned int src = 0; src < opcode->NumSrcRegs; ++src)
-			srcmasks[src] |= RC_MASK_X;
-	} else {
-		switch(inst->I.Opcode) {
-		case RC_OPCODE_ARL:
-			srcmasks[0] |= RC_MASK_X;
-			break;
-		case RC_OPCODE_DP3:
-			srcmasks[0] |= RC_MASK_XYZ;
-			srcmasks[1] |= RC_MASK_XYZ;
-			break;
-		case RC_OPCODE_DP4:
-			srcmasks[0] |= RC_MASK_XYZW;
-			srcmasks[1] |= RC_MASK_XYZW;
-			break;
-		case RC_OPCODE_TEX:
-		case RC_OPCODE_TXB:
-		case RC_OPCODE_TXP:
-			srcmasks[0] |= RC_MASK_XYZW;
-			break;
-		case RC_OPCODE_DST:
-			srcmasks[0] |= 0x6;
-			srcmasks[1] |= 0xa;
-			break;
-		case RC_OPCODE_EXP:
-		case RC_OPCODE_LOG:
-			srcmasks[0] |= RC_MASK_XY;
-			break;
-		case RC_OPCODE_LIT:
-			srcmasks[0] |= 0xb;
-			break;
-		default:
-			break;
-		}
-	}
-}
-
-static void mark_instruction_source_use(struct dataflow_state * s,
-		struct rc_instruction * inst, unsigned int writemask)
-{
-	unsigned int srcmasks[3];
-
-	compute_sources_for_writemask(inst, writemask, srcmasks);
-
-	for(unsigned int src = 0; src < 3; ++src)
-		mark_source_use(s, inst, src, srcmasks[src]);
-}
-
-static void run_update(struct dataflow_state * s)
-{
-	s->UpdateRunning = 1;
-
-	while(s->UpdateStackSize) {
-		struct rc_dataflow_vector * vector = s->UpdateStack[--s->UpdateStackSize];
-		vector->PassBit = 0;
-
-		if (vector->WriteInstruction) {
-			struct rc_instruction * inst = vector->WriteInstruction;
-
-			if (inst->Dataflow.DstRegPrev) {
-				unsigned int carryover = vector->UseMask & ~inst->I.DstReg.WriteMask;
-
-				if (carryover)
-					mark_ref_use(s, inst->Dataflow.DstRegPrev, carryover);
-			}
-
-			mark_instruction_source_use(
-					s, vector->WriteInstruction,
-					vector->UseMask & inst->I.DstReg.WriteMask);
-		}
-	}
-
-	s->UpdateRunning = 0;
-}
-
-static void mark_vector_use(struct dataflow_state * s, struct rc_dataflow_vector * vector, unsigned int mask)
-{
-	if (!(mask & ~vector->UseMask))
-		return; /* no new used bits */
-
-	vector->UseMask |= mask;
-	if (vector->PassBit)
-		return;
-
-	if (s->UpdateStackSize >= s->UpdateStackReserved) {
-		unsigned int new_reserve = 2 * s->UpdateStackReserved;
-		struct rc_dataflow_vector ** new_stack;
-
-		if (!new_reserve)
-			new_reserve = 16;
-
-		new_stack = memory_pool_malloc(&s->C->Pool, new_reserve * sizeof(struct rc_dataflow_vector *));
-		memcpy(new_stack, s->UpdateStack, s->UpdateStackSize * sizeof(struct rc_dataflow_vector *));
-
-		s->UpdateStack = new_stack;
-		s->UpdateStackReserved = new_reserve;
-	}
-
-	s->UpdateStack[s->UpdateStackSize++] = vector;
-	vector->PassBit = 1;
-
-	if (!s->UpdateRunning)
-		run_update(s);
-}
-
-static void annotate_instruction(struct dataflow_state * s, struct rc_instruction * inst)
-{
-	const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->I.Opcode);
-	unsigned int src;
-
-	for(src = 0; src < opcode->NumSrcRegs; ++src) {
-		struct rc_dataflow_vector * vector = get_register_contents(s, inst->I.SrcReg[src].File, inst->I.SrcReg[src].Index);
-		if (vector) {
-			inst->Dataflow.SrcReg[src] = rc_dataflow_create_ref(s->C, vector, inst);
-		}
-		if (inst->I.SrcReg[src].RelAddr) {
-			struct rc_dataflow_vector * addr = get_register_contents(s, RC_FILE_ADDRESS, 0);
-			if (addr)
-				inst->Dataflow.SrcRegAddress[src] = rc_dataflow_create_ref(s->C, addr, inst);
-		}
-	}
-
-	mark_instruction_source_use(s, inst, 0); /* for KIL */
-
-	if (opcode->HasDstReg) {
-		struct rc_dataflow_vector * oldvec = get_register_contents(s, inst->I.DstReg.File, inst->I.DstReg.Index);
-		struct rc_dataflow_vector * newvec = rc_dataflow_create_vector(s->C, inst->I.DstReg.File, inst->I.DstReg.Index, inst);
-
-		newvec->ValidMask = inst->I.DstReg.WriteMask;
-
-		if (oldvec) {
-			unsigned int carryover = oldvec->ValidMask & ~inst->I.DstReg.WriteMask;
-
-			if (oldvec->ValidMask)
-				inst->Dataflow.DstRegAliased = 1;
-
-			if (carryover) {
-				inst->Dataflow.DstRegPrev = rc_dataflow_create_ref(s->C, oldvec, inst);
-				newvec->ValidMask |= carryover;
-
-				if (!s->DCE)
-					mark_ref_use(s, inst->Dataflow.DstRegPrev, carryover);
-			}
-		}
-
-		inst->Dataflow.DstReg = newvec;
-
-		if (newvec->File == RC_FILE_TEMPORARY)
-			s->Temporary[newvec->Index] = newvec;
-		else if (newvec->File == RC_FILE_OUTPUT)
-			s->Output[newvec->Index] = newvec;
-		else
-			s->Address = newvec;
-
-		if (!s->DCE)
-			mark_vector_use(s, newvec, inst->I.DstReg.WriteMask);
-	}
-}
-
-static void init_inputs(struct dataflow_state * s)
-{
-	unsigned int index;
-
-	for(index = 0; index < 32; ++index) {
-		if (s->C->Program.InputsRead & (1 << index)) {
-			s->Input[index] = rc_dataflow_create_vector(s->C, RC_FILE_INPUT, index, 0);
-			s->Input[index]->ValidMask = RC_MASK_XYZW;
-		}
-	}
-}
-
-static void mark_output_use(void * data, unsigned int index, unsigned int mask)
-{
-	struct dataflow_state * s = data;
-	struct rc_dataflow_vector * vec = s->Output[index];
-
-	if (vec)
-		mark_vector_use(s, vec, mask);
-}
-
-void rc_dataflow_annotate(struct radeon_compiler * c, rc_dataflow_mark_outputs_fn dce, void * userdata)
-{
-	struct dataflow_state s;
-	struct rc_instruction * inst;
-
-	memset(&s, 0, sizeof(s));
-	s.C = c;
-	s.DCE = dce ? 1 : 0;
-
-	init_inputs(&s);
-
-	for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) {
-		annotate_instruction(&s, inst);
-	}
-
-	if (s.DCE) {
-		dce(userdata, &s, &mark_output_use);
-
-		for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) {
-			const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->I.Opcode);
-
-			if (opcode->HasDstReg) {
-				unsigned int redundant_writes = inst->I.DstReg.WriteMask & ~inst->Dataflow.DstReg->UseMask;
-
-				inst->I.DstReg.WriteMask &= ~redundant_writes;
-
-				if (!inst->I.DstReg.WriteMask) {
-					struct rc_instruction * todelete = inst;
-					inst = inst->Prev;
-					rc_remove_instruction(todelete);
-					continue;
-				}
-			}
-
-			unsigned int srcmasks[3];
-			compute_sources_for_writemask(inst, inst->I.DstReg.WriteMask, srcmasks);
-
-			for(unsigned int src = 0; src < 3; ++src) {
-				for(unsigned int chan = 0; chan < 4; ++chan) {
-					if (!GET_BIT(srcmasks[src], chan))
-						SET_SWZ(inst->I.SrcReg[src].Swizzle, chan, RC_SWIZZLE_UNUSED);
-				}
-
-				if (inst->Dataflow.SrcReg[src]) {
-					if (!inst->Dataflow.SrcReg[src]->UseMask) {
-						rc_dataflow_remove_ref(inst->Dataflow.SrcReg[src]);
-						inst->Dataflow.SrcReg[src] = 0;
-					}
-				}
-
-				if (inst->Dataflow.SrcRegAddress[src]) {
-					if (!inst->Dataflow.SrcRegAddress[src]->UseMask) {
-						rc_dataflow_remove_ref(inst->Dataflow.SrcRegAddress[src]);
-						inst->Dataflow.SrcRegAddress[src] = 0;
-					}
-				}
-			}
-		}
-
-		rc_calculate_inputs_outputs(c);
-	}
-}
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c
new file mode 100644
index 0000000..95af6fd
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2009 Nicolai Haehnle.
+ *
+ * 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_dataflow.h"
+
+#include "radeon_compiler.h"
+
+
+struct updatemask_state {
+	unsigned char Output[RC_REGISTER_MAX_INDEX];
+	unsigned char Temporary[RC_REGISTER_MAX_INDEX];
+	unsigned char Address;
+};
+
+struct instruction_state {
+	unsigned char WriteMask;
+	unsigned char SrcReg[3];
+};
+
+struct branchinfo {
+	unsigned int HaveElse:1;
+
+	struct updatemask_state StoreEndif;
+	struct updatemask_state StoreElse;
+};
+
+struct deadcode_state {
+	struct radeon_compiler * C;
+	struct instruction_state * Instructions;
+
+	struct updatemask_state R;
+
+	struct branchinfo * BranchStack;
+	unsigned int BranchStackSize;
+	unsigned int BranchStackReserved;
+};
+
+
+static void or_updatemasks(
+	struct updatemask_state * dst,
+	struct updatemask_state * a,
+	struct updatemask_state * b)
+{
+	for(unsigned int i = 0; i < RC_REGISTER_MAX_INDEX; ++i) {
+		dst->Output[i] = a->Output[i] | b->Output[i];
+		dst->Temporary[i] = a->Temporary[i] | b->Temporary[i];
+	}
+
+	dst->Address = a->Address | b->Address;
+}
+
+static void push_branch(struct deadcode_state * s)
+{
+	if (s->BranchStackSize >= s->BranchStackReserved) {
+		unsigned int new_reserve = 2 * s->BranchStackReserved;
+		struct branchinfo * new_stack;
+
+		if (!new_reserve)
+			new_reserve = 4;
+
+		new_stack = memory_pool_malloc(&s->C->Pool, new_reserve * sizeof(struct branchinfo));
+		memcpy(new_stack, s->BranchStack, s->BranchStackSize * sizeof(struct branchinfo));
+
+		s->BranchStack = new_stack;
+		s->BranchStackReserved = new_reserve;
+	}
+
+	struct branchinfo * branch = &s->BranchStack[s->BranchStackSize++];
+	branch->HaveElse = 0;
+	memcpy(&branch->StoreEndif, &s->R, sizeof(s->R));
+}
+
+static unsigned char * get_used_ptr(struct deadcode_state *s, rc_register_file file, unsigned int index)
+{
+	if (file == RC_FILE_OUTPUT || file == RC_FILE_TEMPORARY) {
+		if (index >= RC_REGISTER_MAX_INDEX) {
+			rc_error(s->C, "%s: index %i is out of bounds for file %i\n", __FUNCTION__, index, file);
+			return 0;
+		}
+
+		if (file == RC_FILE_OUTPUT)
+			return &s->R.Output[index];
+		else
+			return &s->R.Temporary[index];
+	} else if (file == RC_FILE_ADDRESS) {
+		return &s->R.Address;
+	}
+
+	return 0;
+}
+
+static void mark_used(struct deadcode_state * s, rc_register_file file, unsigned int index, unsigned int mask)
+{
+	unsigned char * pused = get_used_ptr(s, file, index);
+	if (pused)
+		*pused |= mask;
+}
+
+static void update_instruction(struct deadcode_state * s, struct rc_instruction * inst)
+{
+	const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->I.Opcode);
+	struct instruction_state * insts = &s->Instructions[inst->IP];
+	unsigned int usedmask = 0;
+
+	if (opcode->HasDstReg) {
+		unsigned char * pused = get_used_ptr(s, inst->I.DstReg.File, inst->I.DstReg.Index);
+		if (pused) {
+			usedmask = *pused & inst->I.DstReg.WriteMask;
+			*pused &= ~usedmask;
+		}
+	}
+
+	insts->WriteMask |= usedmask;
+
+	unsigned int srcmasks[3];
+	rc_compute_sources_for_writemask(opcode, usedmask, srcmasks);
+
+	for(unsigned int src = 0; src < opcode->NumSrcRegs; ++src) {
+		unsigned int refmask = 0;
+		unsigned int newsrcmask = srcmasks[src] & ~insts->SrcReg[src];
+		insts->SrcReg[src] |= newsrcmask;
+
+		for(unsigned int chan = 0; chan < 4; ++chan) {
+			if (GET_BIT(newsrcmask, chan))
+				refmask |= 1 << GET_SWZ(inst->I.SrcReg[src].Swizzle, chan);
+		}
+
+		/* get rid of spurious bits from ZERO, ONE, etc. swizzles */
+		refmask &= RC_MASK_XYZW;
+
+		if (!refmask)
+			continue;
+
+		mark_used(s, inst->I.SrcReg[src].File, inst->I.SrcReg[src].Index, refmask);
+
+		if (inst->I.SrcReg[src].RelAddr)
+			mark_used(s, RC_FILE_ADDRESS, 0, RC_MASK_X);
+	}
+}
+
+static void mark_output_use(void * data, unsigned int index, unsigned int mask)
+{
+	struct deadcode_state * s = data;
+
+	mark_used(s, RC_FILE_OUTPUT, index, mask);
+}
+
+void rc_dataflow_deadcode(struct radeon_compiler * c, rc_dataflow_mark_outputs_fn dce, void * userdata)
+{
+	struct deadcode_state s;
+	unsigned int nr_instructions;
+
+	memset(&s, 0, sizeof(s));
+	s.C = c;
+
+	nr_instructions = rc_recompute_ips(c);
+	s.Instructions = memory_pool_malloc(&c->Pool, sizeof(struct instruction_state)*nr_instructions);
+	memset(s.Instructions, 0, sizeof(struct instruction_state)*nr_instructions);
+
+	dce(userdata, &s, &mark_output_use);
+
+	for(struct rc_instruction * inst = c->Program.Instructions.Prev;
+	    inst != &c->Program.Instructions;
+	    inst = inst->Prev) {
+		const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->I.Opcode);
+
+		if (opcode->IsControlFlow) {
+			if (opcode->Opcode == RC_OPCODE_ENDIF) {
+				push_branch(&s);
+			} else {
+				if (s.BranchStackSize) {
+					struct branchinfo * branch = &s.BranchStack[s.BranchStackSize-1];
+
+					if (opcode->Opcode == RC_OPCODE_IF) {
+						or_updatemasks(&s.R,
+								&s.R,
+								branch->HaveElse ? &branch->StoreElse : &branch->StoreEndif);
+
+						s.BranchStackSize--;
+					} else if (opcode->Opcode == RC_OPCODE_ELSE) {
+						if (branch->HaveElse) {
+							rc_error(c, "%s: Multiple ELSE for one IF/ENDIF\n", __FUNCTION__);
+						} else {
+							memcpy(&branch->StoreElse, &s.R, sizeof(s.R));
+							memcpy(&s.R, &branch->StoreEndif, sizeof(s.R));
+							branch->HaveElse = 1;
+						}
+					} else {
+						rc_error(c, "%s: Unhandled control flow instruction %s\n", __FUNCTION__, opcode->Name);
+					}
+				} else {
+					rc_error(c, "%s: Unexpected control flow instruction\n", __FUNCTION__);
+				}
+			}
+		}
+
+		update_instruction(&s, inst);
+	}
+
+	unsigned int ip = 0;
+	for(struct rc_instruction * inst = c->Program.Instructions.Next;
+	    inst != &c->Program.Instructions;
+	    inst = inst->Next, ++ip) {
+		const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->I.Opcode);
+
+		if (opcode->HasDstReg) {
+			if (s.Instructions[ip].WriteMask) {
+				inst->I.DstReg.WriteMask = s.Instructions[ip].WriteMask;
+			} else {
+				struct rc_instruction * todelete = inst;
+				inst = inst->Prev;
+				rc_remove_instruction(todelete);
+				continue;
+			}
+		}
+
+		unsigned int srcmasks[3];
+		rc_compute_sources_for_writemask(opcode, s.Instructions[ip].WriteMask, srcmasks);
+
+		for(unsigned int src = 0; src < 3; ++src) {
+			for(unsigned int chan = 0; chan < 4; ++chan) {
+				if (!GET_BIT(srcmasks[src], chan))
+					SET_SWZ(inst->I.SrcReg[src].Swizzle, chan, RC_SWIZZLE_UNUSED);
+			}
+		}
+	}
+
+	rc_calculate_inputs_outputs(c);
+}
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_dealias.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_dealias.c
deleted file mode 100644
index 4596636..0000000
--- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_dealias.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2009 Nicolai Haehnle.
- *
- * 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_dataflow.h"
-
-#include "radeon_compiler.h"
-
-
-#define DEALIAS_LIST_SIZE 128
-
-struct dealias_state {
-	struct radeon_compiler * C;
-
-	unsigned int OldIndex:RC_REGISTER_INDEX_BITS;
-	unsigned int NewIndex:RC_REGISTER_INDEX_BITS;
-	unsigned int DealiasFail:1;
-
-	struct rc_dataflow_vector * List[DEALIAS_LIST_SIZE];
-	unsigned int Length;
-};
-
-static void push_dealias_vector(struct dealias_state * s, struct rc_dataflow_vector * vec)
-{
-	if (s->Length >= DEALIAS_LIST_SIZE) {
-		rc_debug(s->C, "%s: list size exceeded\n", __FUNCTION__);
-		s->DealiasFail = 1;
-		return;
-	}
-
-	if (rc_assert(s->C, vec->File == RC_FILE_TEMPORARY && vec->Index == s->OldIndex))
-		return;
-
-	s->List[s->Length++] = vec;
-}
-
-static void run_dealias(struct dealias_state * s)
-{
-	unsigned int i;
-
-	for(i = 0; i < s->Length && !s->DealiasFail; ++i) {
-		struct rc_dataflow_vector * vec = s->List[i];
-		struct rc_dataflow_ref * ref;
-
-		for(ref = vec->Refs.Next; ref != &vec->Refs; ref = ref->Next) {
-			if (ref->ReadInstruction->Dataflow.DstRegPrev == ref)
-				push_dealias_vector(s, ref->ReadInstruction->Dataflow.DstReg);
-		}
-	}
-
-	if (s->DealiasFail)
-		return;
-
-	for(i = 0; i < s->Length; ++i) {
-		struct rc_dataflow_vector * vec = s->List[i];
-		struct rc_dataflow_ref * ref;
-
-		vec->Index = s->NewIndex;
-		vec->WriteInstruction->I.DstReg.Index = s->NewIndex;
-
-		for(ref = vec->Refs.Next; ref != &vec->Refs; ref = ref->Next) {
-			struct rc_instruction * inst = ref->ReadInstruction;
-			unsigned int i;
-
-			for(i = 0; i < 3; ++i) {
-				if (inst->Dataflow.SrcReg[i] == ref) {
-					if (rc_assert(s->C, inst->I.SrcReg[i].File == RC_FILE_TEMPORARY &&
-					                    inst->I.SrcReg[i].Index == s->OldIndex))
-						return;
-
-					inst->I.SrcReg[i].Index = s->NewIndex;
-				}
-			}
-		}
-	}
-}
-
-/**
- * Breaks register aliasing to reduce multiple assignments to a single register.
- *
- * This affects sequences like:
- *  MUL r0, ...;
- *  MAD r0, r1, r2, r0;
- * In this example, a new register will be used for the destination of the
- * second MAD.
- *
- * The purpose of this dealiasing is to make the resulting code more SSA-like
- * and therefore make it easier to move instructions around.
- * This is of crucial importance for R300 fragment programs, where de-aliasing
- * can help to reduce texture indirections, but other targets can benefit from
- * it as well.
- *
- * \note When compiling GLSL, there may be some benefit gained from breaking
- * up vectors whose components are unrelated. This is not done yet and should
- * be investigated at some point (of course, a matching pass to re-merge
- * components would be required).
- */
-void rc_dataflow_dealias(struct radeon_compiler * c)
-{
-	struct dealias_state s;
-
-	memset(&s, 0, sizeof(s));
-	s.C = c;
-
-	struct rc_instruction * inst;
-	for(inst = c->Program.Instructions.Prev; inst != &c->Program.Instructions; inst = inst->Prev) {
-		if (!inst->Dataflow.DstRegAliased || inst->Dataflow.DstReg->File != RC_FILE_TEMPORARY)
-			continue;
-
-		if (inst->Dataflow.DstReg->UseMask & ~inst->I.DstReg.WriteMask)
-			continue;
-
-		s.OldIndex = inst->I.DstReg.Index;
-		s.NewIndex = rc_find_free_temporary(c);
-		s.DealiasFail = 0;
-		s.Length = 0;
-
-		inst->Dataflow.DstRegAliased = 0;
-		if (inst->Dataflow.DstRegPrev) {
-			rc_dataflow_remove_ref(inst->Dataflow.DstRegPrev);
-			inst->Dataflow.DstRegPrev = 0;
-		}
-
-		push_dealias_vector(&s, inst->Dataflow.DstReg);
-		run_dealias(&s);
-	}
-}
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_swizzles.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_swizzles.c
index 1aa91ef..fcef218 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_swizzles.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_swizzles.c
@@ -37,8 +37,6 @@ static void rewrite_source(struct radeon_compiler * c,
 	struct rc_swizzle_split split;
 	unsigned int tempreg = rc_find_free_temporary(c);
 	unsigned int usemask;
-	struct rc_dataflow_ref * oldref = inst->Dataflow.SrcReg[src];
-	struct rc_dataflow_vector * vector = 0;
 
 	usemask = 0;
 	for(unsigned int chan = 0; chan < 4; ++chan) {
@@ -75,30 +73,8 @@ static void rewrite_source(struct radeon_compiler * c,
 		else if (masked_negate == split.Phase[phase])
 			mov->I.SrcReg[0].Negate = RC_MASK_XYZW;
 
-		if (oldref) {
-			mov->Dataflow.SrcReg[0] = rc_dataflow_create_ref(c, oldref->Vector, mov);
-			mov->Dataflow.SrcReg[0]->UseMask = phase_refmask;
-		}
-
-		mov->Dataflow.DstReg = rc_dataflow_create_vector(c, RC_FILE_TEMPORARY, tempreg, mov);
-		mov->Dataflow.DstReg->ValidMask = split.Phase[phase];
-
-		if (vector) {
-			mov->Dataflow.DstRegPrev = rc_dataflow_create_ref(c, vector, mov);
-			mov->Dataflow.DstRegPrev->UseMask = vector->ValidMask;
-			mov->Dataflow.DstReg->ValidMask |= vector->ValidMask;
-			mov->Dataflow.DstRegAliased = 1;
-		}
-
-		mov->Dataflow.DstReg->UseMask = mov->Dataflow.DstReg->ValidMask;
-		vector = mov->Dataflow.DstReg;
 	}
 
-	if (oldref)
-		rc_dataflow_remove_ref(oldref);
-	inst->Dataflow.SrcReg[src] = rc_dataflow_create_ref(c, vector, inst);
-	inst->Dataflow.SrcReg[src]->UseMask = usemask;
-
 	inst->I.SrcReg[src].File = RC_FILE_TEMPORARY;
 	inst->I.SrcReg[src].Index = tempreg;
 	inst->I.SrcReg[src].Swizzle = 0;
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.c b/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.c
index b720099..e097a62 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.c
@@ -27,6 +27,8 @@
 
 #include "radeon_opcodes.h"
 
+#include "radeon_program_constants.h"
+
 struct rc_opcode_info rc_opcodes[MAX_RC_OPCODE] = {
 	{
 		.Opcode = RC_OPCODE_NOP,
@@ -340,8 +342,84 @@ struct rc_opcode_info rc_opcodes[MAX_RC_OPCODE] = {
 		.HasDstReg = 1
 	},
 	{
+		.Opcode = RC_OPCODE_IF,
+		.Name = "IF",
+		.IsControlFlow = 1,
+		.NumSrcRegs = 1
+	},
+	{
+		.Opcode = RC_OPCODE_ELSE,
+		.Name = "ELSE",
+		.IsControlFlow = 1,
+		.NumSrcRegs = 0
+	},
+	{
+		.Opcode = RC_OPCODE_ENDIF,
+		.Name = "ENDIF",
+		.IsControlFlow = 1,
+		.NumSrcRegs = 0
+	},
+	{
 		.Opcode = RC_OPCODE_REPL_ALPHA,
 		.Name = "REPL_ALPHA",
 		.HasDstReg = 1
 	}
 };
+
+void rc_compute_sources_for_writemask(
+		const struct rc_opcode_info * opcode,
+		unsigned int writemask,
+		unsigned int *srcmasks)
+{
+	srcmasks[0] = 0;
+	srcmasks[1] = 0;
+	srcmasks[2] = 0;
+
+	if (opcode->Opcode == RC_OPCODE_KIL)
+		srcmasks[0] |= RC_MASK_XYZW;
+	else if (opcode->Opcode == RC_OPCODE_IF)
+		srcmasks[0] |= RC_MASK_X;
+
+	if (!writemask)
+		return;
+
+	if (opcode->IsComponentwise) {
+		for(unsigned int src = 0; src < opcode->NumSrcRegs; ++src)
+			srcmasks[src] |= writemask;
+	} else if (opcode->IsStandardScalar) {
+		for(unsigned int src = 0; src < opcode->NumSrcRegs; ++src)
+			srcmasks[src] |= RC_MASK_X;
+	} else {
+		switch(opcode->Opcode) {
+		case RC_OPCODE_ARL:
+			srcmasks[0] |= RC_MASK_X;
+			break;
+		case RC_OPCODE_DP3:
+			srcmasks[0] |= RC_MASK_XYZ;
+			srcmasks[1] |= RC_MASK_XYZ;
+			break;
+		case RC_OPCODE_DP4:
+			srcmasks[0] |= RC_MASK_XYZW;
+			srcmasks[1] |= RC_MASK_XYZW;
+			break;
+		case RC_OPCODE_TEX:
+		case RC_OPCODE_TXB:
+		case RC_OPCODE_TXP:
+			srcmasks[0] |= RC_MASK_XYZW;
+			break;
+		case RC_OPCODE_DST:
+			srcmasks[0] |= 0x6;
+			srcmasks[1] |= 0xa;
+			break;
+		case RC_OPCODE_EXP:
+		case RC_OPCODE_LOG:
+			srcmasks[0] |= RC_MASK_XY;
+			break;
+		case RC_OPCODE_LIT:
+			srcmasks[0] |= 0xb;
+			break;
+		default:
+			break;
+		}
+	}
+}
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.h b/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.h
index 8e30bef..f8ba525 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.h
@@ -166,6 +166,18 @@ typedef enum {
 	RC_OPCODE_TXL,
 	RC_OPCODE_TXP,
 
+	/** branch instruction:
+	 * If src0.x != 0.0, continue with the next instruction;
+	 * otherwise, jump to matching RC_OPCODE_ELSE or RC_OPCODE_ENDIF.
+	 */
+	RC_OPCODE_IF,
+
+	/** branch instruction: jump to matching RC_OPCODE_ENDIF */
+	RC_OPCODE_ELSE,
+
+	/** branch instruction: has no effect */
+	RC_OPCODE_ENDIF,
+
 	/** special instruction, used in R300-R500 fragment program pair instructions
 	 * indicates that the result of the alpha operation shall be replicated
 	 * across all other channels */
@@ -188,6 +200,9 @@ struct rc_opcode_info {
 	unsigned int NumSrcRegs:2;
 	unsigned int HasDstReg:1;
 
+	/** true if this instruction affects control flow */
+	unsigned int IsControlFlow:1;
+
 	/** true if this is a vector instruction that operates on components in parallel
 	 * without any cross-component interaction */
 	unsigned int IsComponentwise:1;
@@ -207,4 +222,9 @@ static inline const struct rc_opcode_info * rc_get_opcode_info(rc_opcode opcode)
 	return &rc_opcodes[opcode];
 }
 
+void rc_compute_sources_for_writemask(
+		const struct rc_opcode_info * opcode,
+		unsigned int writemask,
+		unsigned int *srcmasks);
+
 #endif /* RADEON_OPCODES_H */
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program.c b/src/mesa/drivers/dri/r300/compiler/radeon_program.c
index b97c480..a1ee7c0 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_program.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program.c
@@ -154,7 +154,24 @@ struct rc_instruction *rc_insert_new_instruction(struct radeon_compiler * c, str
 
 void rc_remove_instruction(struct rc_instruction * inst)
 {
-	rc_dataflow_remove_instruction(inst);
 	inst->Prev->Next = inst->Next;
 	inst->Next->Prev = inst->Prev;
 }
+
+/**
+ * Return the number of instructions in the program.
+ */
+unsigned int rc_recompute_ips(struct radeon_compiler * c)
+{
+	unsigned int ip = 0;
+
+	for(struct rc_instruction * inst = c->Program.Instructions.Next;
+	    inst != &c->Program.Instructions;
+	    inst = inst->Next) {
+		inst->IP = ip++;
+	}
+
+	c->Program.Instructions.IP = 0xcafedead;
+
+	return ip;
+}
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program.h b/src/mesa/drivers/dri/r300/compiler/radeon_program.h
index d38c9a4..efa2b0d 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_program.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program.h
@@ -34,7 +34,6 @@
 #include "radeon_opcodes.h"
 #include "radeon_code.h"
 #include "radeon_program_constants.h"
-#include "radeon_dataflow.h"
 
 struct radeon_compiler;
 
@@ -73,33 +72,33 @@ struct rc_dst_register {
  * instruction types may be valid.
  */
 struct rc_sub_instruction {
-		struct rc_src_register SrcReg[3];
-		struct rc_dst_register DstReg;
-
-		/**
-		 * Opcode of this instruction, according to \ref rc_opcode enums.
-		 */
-		rc_opcode Opcode:8;
-
-		/**
-		 * Saturate each value of the result to the range [0,1] or [-1,1],
-		 * according to \ref rc_saturate_mode enums.
-		 */
-		rc_saturate_mode SaturateMode:2;
-
-		/**
-		 * \name Extra fields for TEX, TXB, TXD, TXL, TXP instructions.
-		 */
-		/*@{*/
-		/** Source texture unit. */
-		unsigned int TexSrcUnit:5;
-
-		/** Source texture target, one of the \ref rc_texture_target enums */
-		rc_texture_target TexSrcTarget:3;
-
-		/** True if tex instruction should do shadow comparison */
-		unsigned int TexShadow:1;
-		/*@}*/
+	struct rc_src_register SrcReg[3];
+	struct rc_dst_register DstReg;
+
+	/**
+	 * Opcode of this instruction, according to \ref rc_opcode enums.
+	 */
+	rc_opcode Opcode:8;
+
+	/**
+	 * Saturate each value of the result to the range [0,1] or [-1,1],
+	 * according to \ref rc_saturate_mode enums.
+	 */
+	rc_saturate_mode SaturateMode:2;
+
+	/**
+	 * \name Extra fields for TEX, TXB, TXD, TXL, TXP instructions.
+	 */
+	/*@{*/
+	/** Source texture unit. */
+	unsigned int TexSrcUnit:5;
+
+	/** Source texture target, one of the \ref rc_texture_target enums */
+	rc_texture_target TexSrcTarget:3;
+
+	/** True if tex instruction should do shadow comparison */
+	unsigned int TexShadow:1;
+	/*@}*/
 };
 
 struct rc_instruction {
@@ -109,13 +108,11 @@ struct rc_instruction {
 	struct rc_sub_instruction I;
 
 	/**
-	 * Dataflow annotations.
-	 *
-	 * These are not supplied by the caller of the compiler,
-	 * but filled in during compilation stages that make use of
-	 * dataflow analysis.
+	 * Warning: IPs are not stable. If you want to use them,
+	 * you need to recompute them at the beginning of each pass
+	 * using \ref rc_recompute_ips
 	 */
-	struct rc_instruction_dataflow Dataflow;
+	unsigned int IP;
 };
 
 struct rc_program {
@@ -210,10 +207,8 @@ struct rc_instruction *rc_alloc_instruction(struct radeon_compiler * c);
 struct rc_instruction *rc_insert_new_instruction(struct radeon_compiler * c, struct rc_instruction * after);
 void rc_remove_instruction(struct rc_instruction * inst);
 
-enum {
-	RC_PRINT_DATAFLOW = 0x1
-};
+unsigned int rc_recompute_ips(struct radeon_compiler * c);
 
-void rc_print_program(const struct rc_program *prog, unsigned int flags);
+void rc_print_program(const struct rc_program *prog);
 
 #endif
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c
index 38060ea..0485286 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c
@@ -24,11 +24,6 @@
 
 #include <stdio.h>
 
-static void print_comment(FILE * f)
-{
-	fprintf(f, "               # ");
-}
-
 static const char * textarget_to_string(rc_texture_target target)
 {
 	switch(target) {
@@ -121,19 +116,7 @@ static void rc_print_src_register(FILE * f, struct rc_src_register src)
 		fprintf(f, "|");
 }
 
-static void rc_print_ref(FILE * f, struct rc_dataflow_ref * ref)
-{
-	fprintf(f, "ref(%p", ref->Vector);
-
-	if (ref->UseMask != RC_MASK_XYZW) {
-		fprintf(f, ".");
-		rc_print_mask(f, ref->UseMask);
-	}
-
-	fprintf(f, ")");
-}
-
-static void rc_print_instruction(FILE * f, unsigned int flags, struct rc_instruction * inst)
+static void rc_print_instruction(FILE * f, struct rc_instruction * inst)
 {
 	const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->I.Opcode);
 	unsigned int reg;
@@ -169,45 +152,22 @@ static void rc_print_instruction(FILE * f, unsigned int flags, struct rc_instruc
 	}
 
 	fprintf(f, ";\n");
-
-	if (flags & RC_PRINT_DATAFLOW) {
-		print_comment(f);
-
-		fprintf(f, "Dst = %p", inst->Dataflow.DstReg);
-		if (inst->Dataflow.DstRegAliased)
-			fprintf(f, " aliased");
-		if (inst->Dataflow.DstRegPrev) {
-			fprintf(f, " from ");
-			rc_print_ref(f, inst->Dataflow.DstRegPrev);
-		}
-
-		for(reg = 0; reg < opcode->NumSrcRegs; ++reg) {
-			fprintf(f, ", ");
-			if (inst->Dataflow.SrcReg[reg])
-				rc_print_ref(f, inst->Dataflow.SrcReg[reg]);
-			else
-				fprintf(f, "<no ref>");
-		}
-
-		fprintf(f, "\n");
-	}
 }
 
 /**
  * Print program to stderr, default options.
  */
-void rc_print_program(const struct rc_program *prog, unsigned int flags)
+void rc_print_program(const struct rc_program *prog)
 {
 	unsigned int linenum = 0;
 	struct rc_instruction *inst;
 
-	fprintf(stderr, "# Radeon Compiler Program%s\n",
-			flags & RC_PRINT_DATAFLOW ? " (with dataflow annotations)" : "");
+	fprintf(stderr, "# Radeon Compiler Program\n");
 
 	for(inst = prog->Instructions.Next; inst != &prog->Instructions; inst = inst->Next) {
 		fprintf(stderr, "%3d: ", linenum);
 
-		rc_print_instruction(stderr, flags, inst);
+		rc_print_instruction(stderr, inst);
 
 		linenum++;
 	}




More information about the mesa-commit mailing list