Mesa (master): r300/compiler: Track readers through branches in rc_get_readers()

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


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

Author: Tom Stellard <tstellar at gmail.com>
Date:   Sat Nov  6 11:30:27 2010 -0700

r300/compiler: Track readers through branches in rc_get_readers()

---

 .../drivers/dri/r300/compiler/r500_fragprog_emit.c |    5 +-
 src/mesa/drivers/dri/r300/compiler/radeon_code.h   |    2 +
 .../drivers/dri/r300/compiler/radeon_dataflow.c    |   92 +++++++++++++-------
 .../drivers/dri/r300/compiler/radeon_optimize.c    |    4 +-
 4 files changed, 65 insertions(+), 38 deletions(-)

diff --git a/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c b/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c
index 0311e7c..5da82d9 100644
--- a/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c
+++ b/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c
@@ -45,9 +45,6 @@
 
 #include "radeon_program_pair.h"
 
-#define MAX_BRANCH_DEPTH_FULL 32
-#define MAX_BRANCH_DEPTH_PARTIAL 4
-
 #define PROG_CODE \
 	struct r500_fragment_program_code *code = &c->code->code.r500
 
@@ -509,7 +506,7 @@ static void emit_flowcontrol(struct emit_state * s, struct rc_instruction * inst
 		break;
 	}
 	case RC_OPCODE_IF:
-		if ( s->CurrentBranchDepth >= MAX_BRANCH_DEPTH_FULL) {
+		if ( s->CurrentBranchDepth >= R500_PFS_MAX_BRANCH_DEPTH_FULL) {
 			rc_error(s->C, "Branch depth exceeds hardware limit");
 			return;
 		}
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_code.h b/src/mesa/drivers/dri/r300/compiler/radeon_code.h
index cfb6df2..b69e816 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_code.h
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_code.h
@@ -34,6 +34,8 @@
 #define R500_PFS_MAX_INST         512
 #define R500_PFS_NUM_TEMP_REGS    128
 #define R500_PFS_NUM_CONST_REGS   256
+#define R500_PFS_MAX_BRANCH_DEPTH_FULL 32
+#define R500_PFS_MAX_BRANCH_DEPTH_PARTIAL 4
 
 
 #define STATE_R300_WINDOW_DIMENSION (STATE_INTERNAL_DRIVER+0)
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c
index 2ce0c6e..600be8b 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c
@@ -461,6 +461,12 @@ static rc_opcode get_flow_control_inst(struct rc_instruction * inst)
 
 }
 
+struct branch_write_mask {
+	unsigned int IfWriteMask:4;
+	unsigned int ElseWriteMask:4;
+	unsigned int HasElse:1;
+};
+
 union get_readers_read_cb {
 	rc_read_src_fn I;
 	rc_pair_read_arg_fn P;
@@ -476,6 +482,8 @@ struct get_readers_callback_data {
 	unsigned int DstIndex;
 	unsigned int DstMask;
 	unsigned int AliveWriteMask;
+	/*  For convenience, this is indexed starting at 1 */
+	struct branch_write_mask BranchMasks[R500_PFS_MAX_BRANCH_DEPTH_FULL + 1];
 };
 
 static void add_reader(
@@ -521,12 +529,12 @@ static unsigned int get_readers_read_callback(
 	/* If we make it this far, it means that this source reads from the
 	 * same register written to by d->ReaderData->Writer. */
 
-	if (cb_data->ReaderData->AbortOnRead) {
+	read_mask = rc_swizzle_to_writemask(swizzle);
+	if (cb_data->ReaderData->AbortOnRead & read_mask) {
 		cb_data->ReaderData->Abort = 1;
 		return shared_mask;
 	}
 
-	read_mask = rc_swizzle_to_writemask(swizzle);
 	/* XXX The behavior in this case should be configurable. */
 	if ((read_mask & cb_data->AliveWriteMask) != read_mask) {
 		cb_data->ReaderData->Abort = 1;
@@ -605,22 +613,8 @@ static void get_readers_write_callback(
 
 	if (index == d->DstIndex && file == d->DstFile) {
 		unsigned int shared_mask = mask & d->DstMask;
-		if (d->ReaderData->InElse) {
-			if (shared_mask & d->AliveWriteMask) {
-				/* We set AbortOnRead here because the
-				 * destination register of d->ReaderData->Writer
-				 * is written to in both the IF and the
-				 * ELSE block of this IF/ELSE statement.
-				 * This means that readers of this
-				 * destination register that follow this IF/ELSE
-				 * statement use the value of different
-				 * instructions depending on the control flow
-				 * decisions made by the program. */
-				d->ReaderData->AbortOnRead = 1;
-			}
-		} else {
-			d->AliveWriteMask &= ~shared_mask;
-		}
+		d->ReaderData->AbortOnRead &= ~shared_mask;
+		d->AliveWriteMask &= ~shared_mask;
 	}
 
 	if(d->WriteCB)
@@ -645,6 +639,7 @@ static void get_readers_for_single_write(
 	d->DstIndex = dst_index;
 	d->DstMask = dst_mask;
 	d->AliveWriteMask = dst_mask;
+	memset(d->BranchMasks, 0, sizeof(d->BranchMasks));
 
 	if (!dst_mask)
 		return;
@@ -670,21 +665,53 @@ static void get_readers_for_single_write(
 			d->ReaderData->Abort = 1;
 			return;
 		case RC_OPCODE_IF:
-			/* XXX We can do better here, but this will have to
-			 * do until this dataflow analysis is more mature. */
-			d->ReaderData->Abort = 1;
 			branch_depth++;
+			if (branch_depth > R500_PFS_MAX_BRANCH_DEPTH_FULL) {
+				d->ReaderData->Abort = 1;
+				return;
+			}
+			d->BranchMasks[branch_depth].IfWriteMask =
+							d->AliveWriteMask;
 			break;
 		case RC_OPCODE_ELSE:
-			if (branch_depth == 0)
+			if (branch_depth == 0) {
 				d->ReaderData->InElse = 1;
+			} else {
+				unsigned int temp_mask = d->AliveWriteMask;
+				d->AliveWriteMask =
+					d->BranchMasks[branch_depth].IfWriteMask;
+				d->BranchMasks[branch_depth].ElseWriteMask =
+								temp_mask;
+				d->BranchMasks[branch_depth].HasElse = 1;
+			}
 			break;
 		case RC_OPCODE_ENDIF:
 			if (branch_depth == 0) {
-				d->ReaderData->AbortOnRead = 1;
+				d->ReaderData->AbortOnRead = d->AliveWriteMask;
 				d->ReaderData->InElse = 0;
 			}
 			else {
+				struct branch_write_mask * masks =
+					&d->BranchMasks[branch_depth];
+
+				if (masks->HasElse) {
+					d->ReaderData->AbortOnRead |=
+						masks->IfWriteMask
+							& ~masks->ElseWriteMask;
+					d->AliveWriteMask = masks->IfWriteMask
+						^ ((masks->IfWriteMask ^
+							masks->ElseWriteMask)
+						& (masks->IfWriteMask
+							^ d->AliveWriteMask));
+				} else {
+					d->ReaderData->AbortOnRead |=
+						masks->IfWriteMask
+							& ~d->AliveWriteMask;
+					d->AliveWriteMask = masks->IfWriteMask;
+
+				}
+				memset(masks, 0,
+					sizeof(struct branch_write_mask));
 				branch_depth--;
 			}
 			break;
@@ -692,21 +719,22 @@ static void get_readers_for_single_write(
 			break;
 		}
 
-		if (!d->ReaderData->InElse) {
-			if (tmp->Type == RC_INSTRUCTION_NORMAL) {
-				rc_for_all_reads_src(tmp,
-					get_readers_normal_read_callback, d);
-			} else {
-				rc_pair_for_all_reads_arg(tmp,
-					get_readers_pair_read_callback, d);
-			}
+		if (d->ReaderData->InElse)
+			continue;
+
+		if (tmp->Type == RC_INSTRUCTION_NORMAL) {
+			rc_for_all_reads_src(tmp,
+				get_readers_normal_read_callback, d);
+		} else {
+			rc_pair_for_all_reads_arg(tmp,
+				get_readers_pair_read_callback, d);
 		}
 		rc_for_all_writes_mask(tmp, get_readers_write_callback, d);
 
 		if (d->ReaderData->Abort)
 			return;
 
-		if (!d->AliveWriteMask)
+		if (branch_depth == 0 && !d->AliveWriteMask)
 			return;
 	}
 }
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c b/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c
index 0f707d8..2eb5484 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c
@@ -112,11 +112,11 @@ static void src_clobbered_reads_cb(
 	    && src->Index == sc_data->Index
 	    && (rc_swizzle_to_writemask(src->Swizzle) & sc_data->Mask)) {
 
-		sc_data->ReaderData->AbortOnRead = 1;
+		sc_data->ReaderData->AbortOnRead = RC_MASK_XYZW;
 	}
 
 	if (src->RelAddr && sc_data->File == RC_FILE_ADDRESS) {
-		sc_data->ReaderData->AbortOnRead = 1;
+		sc_data->ReaderData->AbortOnRead = RC_MASK_XYZW;
 	}
 }
 




More information about the mesa-commit mailing list