summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/r300
diff options
context:
space:
mode:
authorTom Stellard <tstellar@gmail.com>2010-11-06 11:30:27 -0700
committerTom Stellard <tstellar@gmail.com>2010-11-21 18:48:31 -0800
commit681f56af807ed9e2a930a595ef509ee814d130dd (patch)
treeddc1fbe5739f9f4d15f96b9b6e9b8e58e73ef27f /src/mesa/drivers/dri/r300
parent255860113f12062c7341c012e6d9a3e6d834ab98 (diff)
r300/compiler: Track readers through branches in rc_get_readers()
Diffstat (limited to 'src/mesa/drivers/dri/r300')
-rw-r--r--src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c5
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_code.h2
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c92
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_optimize.c4
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 0311e7cf9a..5da82d90f6 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 cfb6df2cd7..b69e81698a 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 2ce0c6e2b6..600be8b886 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 0f707d8c52..2eb548474f 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;
}
}