From 681f56af807ed9e2a930a595ef509ee814d130dd Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Sat, 6 Nov 2010 11:30:27 -0700 Subject: 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(-) (limited to 'src/mesa/drivers/dri') 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; } } -- cgit v1.2.3