diff options
Diffstat (limited to 'src/mesa/drivers/dri/r300/compiler/radeon_optimize.c')
-rw-r--r-- | src/mesa/drivers/dri/r300/compiler/radeon_optimize.c | 331 |
1 files changed, 136 insertions, 195 deletions
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c b/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c index 4d9120ffd0..27b10ffbd6 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c @@ -32,15 +32,14 @@ #include "radeon_compiler_util.h" #include "radeon_swizzle.h" -struct peephole_state { - struct rc_instruction * Inst; - /** Stores a bitmask of the components that are still "alive" (i.e. - * they have not been written to since Inst was executed.) - */ - unsigned int WriteMask; +struct src_clobbered_reads_cb_data { + rc_register_file File; + unsigned int Index; + unsigned int Mask; + struct rc_reader_data * ReaderData; }; -typedef void (*rc_presub_replace_fn)(struct peephole_state *, +typedef void (*rc_presub_replace_fn)(struct rc_instruction *, struct rc_instruction *, unsigned int); @@ -67,38 +66,18 @@ static struct rc_src_register chain_srcregs(struct rc_src_register outer, struct return combine; } -struct copy_propagate_state { - struct radeon_compiler * C; - struct rc_instruction * Mov; - unsigned int Conflict:1; - - /** Whether Mov's source has been clobbered */ - unsigned int SourceClobbered:1; - - /** Which components of Mov's destination register are still from that Mov? */ - unsigned int MovMask:4; - - /** Which components of Mov's destination register are clearly *not* from that Mov */ - unsigned int DefinedMask:4; - - /** Which components of Mov's source register are sourced */ - unsigned int SourcedMask:4; - - /** Branch depth beyond Mov; negative value indicates we left the Mov's block */ - int BranchDepth; -}; - static void copy_propagate_scan_read(void * data, struct rc_instruction * inst, struct rc_src_register * src) { rc_register_file file = src->File; struct rc_reader_data * reader_data = data; - const struct rc_opcode_info * info = rc_get_opcode_info(inst->U.I.Opcode); - /* It is possible to do copy propigation in this situation, - * just not right now, see peephole_add_presub_inv() */ - if (reader_data->Writer->U.I.PreSub.Opcode != RC_PRESUB_NONE && - (info->NumSrcRegs > 2 || info->HasTexture)) { + if(!rc_inst_can_use_presub(inst, + reader_data->Writer->U.I.PreSub.Opcode, + rc_swizzle_to_writemask(src->Swizzle), + *src, + reader_data->Writer->U.I.PreSub.SrcReg[0], + reader_data->Writer->U.I.PreSub.SrcReg[1])) { reader_data->Abort = 1; return; } @@ -123,23 +102,44 @@ static void copy_propagate_scan_read(void * data, struct rc_instruction * inst, } } -static void copy_propagate_scan_write(void * data, struct rc_instruction * inst, - rc_register_file file, unsigned int index, unsigned int mask) +static void src_clobbered_reads_cb( + void * data, + struct rc_instruction * inst, + struct rc_src_register * src) { - struct rc_reader_data * reader_data = data; - struct copy_propagate_state * s = reader_data->CbData; + struct src_clobbered_reads_cb_data * sc_data = data; + + if (src->File == sc_data->File + && src->Index == sc_data->Index + && (rc_swizzle_to_writemask(src->Swizzle) & sc_data->Mask)) { - if (file == reader_data->Writer->U.I.SrcReg[0].File && index == reader_data->Writer->U.I.SrcReg[0].Index) { - if (mask & s->SourcedMask) - reader_data->AbortOnRead = 1; - } else if (s->Mov->U.I.SrcReg[0].RelAddr && file == RC_FILE_ADDRESS) { - reader_data->AbortOnRead = 1; + sc_data->ReaderData->AbortOnRead = RC_MASK_XYZW; } + + if (src->RelAddr && sc_data->File == RC_FILE_ADDRESS) { + sc_data->ReaderData->AbortOnRead = RC_MASK_XYZW; + } +} + +static void is_src_clobbered_scan_write( + void * data, + struct rc_instruction * inst, + rc_register_file file, + unsigned int index, + unsigned int mask) +{ + struct src_clobbered_reads_cb_data sc_data; + struct rc_reader_data * reader_data = data; + sc_data.File = file; + sc_data.Index = index; + sc_data.Mask = mask; + sc_data.ReaderData = reader_data; + rc_for_all_reads_src(reader_data->Writer, + src_clobbered_reads_cb, &sc_data); } static void copy_propagate(struct radeon_compiler * c, struct rc_instruction * inst_mov) { - struct copy_propagate_state s; struct rc_reader_data reader_data; unsigned int i; @@ -149,22 +149,10 @@ static void copy_propagate(struct radeon_compiler * c, struct rc_instruction * i inst_mov->U.I.SaturateMode) return; - memset(&s, 0, sizeof(s)); - s.C = c; - s.Mov = inst_mov; - s.MovMask = inst_mov->U.I.DstReg.WriteMask; - s.DefinedMask = RC_MASK_XYZW & ~s.MovMask; - - reader_data.CbData = &s; - - for(unsigned int chan = 0; chan < 4; ++chan) { - unsigned int swz = GET_SWZ(inst_mov->U.I.SrcReg[0].Swizzle, chan); - s.SourcedMask |= (1 << swz) & RC_MASK_XYZW; - } - /* Get a list of all the readers of this MOV instruction. */ - rc_get_readers_normal(c, inst_mov, &reader_data, - copy_propagate_scan_read, copy_propagate_scan_write); + rc_get_readers(c, inst_mov, &reader_data, + copy_propagate_scan_read, NULL, + is_src_clobbered_scan_write); if (reader_data.Abort || reader_data.ReaderCount == 0) return; @@ -172,10 +160,10 @@ static void copy_propagate(struct radeon_compiler * c, struct rc_instruction * i /* Propagate the MOV instruction. */ for (i = 0; i < reader_data.ReaderCount; i++) { struct rc_instruction * inst = reader_data.Readers[i].Inst; - *reader_data.Readers[i].Src = chain_srcregs(*reader_data.Readers[i].Src, s.Mov->U.I.SrcReg[0]); + *reader_data.Readers[i].U.Src = chain_srcregs(*reader_data.Readers[i].U.Src, inst_mov->U.I.SrcReg[0]); - if (s.Mov->U.I.SrcReg[0].File == RC_FILE_PRESUB) - inst->U.I.PreSub = s.Mov->U.I.PreSub; + if (inst_mov->U.I.SrcReg[0].File == RC_FILE_PRESUB) + inst->U.I.PreSub = inst_mov->U.I.PreSub; } /* Finally, remove the original MOV instruction */ @@ -222,8 +210,8 @@ static int is_src_uniform_constant(struct rc_src_register src, static void constant_folding_mad(struct rc_instruction * inst) { - rc_swizzle swz; - unsigned int negate; + rc_swizzle swz = 0; + unsigned int negate= 0; if (is_src_uniform_constant(inst->U.I.SrcReg[2], &swz, &negate)) { if (swz == RC_SWIZZLE_ZERO) { @@ -263,8 +251,8 @@ static void constant_folding_mad(struct rc_instruction * inst) static void constant_folding_mul(struct rc_instruction * inst) { - rc_swizzle swz; - unsigned int negate; + rc_swizzle swz = 0; + unsigned int negate = 0; if (is_src_uniform_constant(inst->U.I.SrcReg[0], &swz, &negate)) { if (swz == RC_SWIZZLE_ONE) { @@ -296,8 +284,8 @@ static void constant_folding_mul(struct rc_instruction * inst) static void constant_folding_add(struct rc_instruction * inst) { - rc_swizzle swz; - unsigned int negate; + rc_swizzle swz = 0; + unsigned int negate = 0; if (is_src_uniform_constant(inst->U.I.SrcReg[0], &swz, &negate)) { if (swz == RC_SWIZZLE_ZERO) { @@ -431,132 +419,88 @@ static int src_has_const_swz(struct rc_src_register src) { return 0; } -static void peephole_scan_write(void * data, struct rc_instruction * inst, - rc_register_file file, unsigned int index, unsigned int mask) +static void presub_scan_read( + void * data, + struct rc_instruction * inst, + struct rc_src_register * src) { - struct peephole_state * s = data; - if(s->Inst->U.I.DstReg.File == file - && s->Inst->U.I.DstReg.Index == index) { - unsigned int common_mask = s->WriteMask & mask; - s->WriteMask &= ~common_mask; + struct rc_reader_data * reader_data = data; + rc_presubtract_op * presub_opcode = reader_data->CbData; + + if (!rc_inst_can_use_presub(inst, *presub_opcode, + reader_data->Writer->U.I.DstReg.WriteMask, + *src, + reader_data->Writer->U.I.SrcReg[0], + reader_data->Writer->U.I.SrcReg[1])) { + reader_data->Abort = 1; + return; } } static int presub_helper( struct radeon_compiler * c, - struct peephole_state * s, + struct rc_instruction * inst_add, rc_presubtract_op presub_opcode, rc_presub_replace_fn presub_replace) { - struct rc_instruction * inst; - unsigned int can_remove = 0; - unsigned int cant_sub = 0; - - for(inst = s->Inst->Next; inst != &c->Program.Instructions; - inst = inst->Next) { - unsigned int i; - unsigned char can_use_presub = 1; - const struct rc_opcode_info * info = - rc_get_opcode_info(inst->U.I.Opcode); - /* XXX: There are some situations where instructions - * with more than 2 src registers can use the - * presubtract select, but to keep things simple we - * will disable presubtract on these instructions for - * now. */ - if (info->NumSrcRegs > 2 || info->HasTexture) { - can_use_presub = 0; - } + struct rc_reader_data reader_data; + unsigned int i; + rc_presubtract_op cb_op = presub_opcode; - /* We can't use more than one presubtract value in an - * instruction, unless the two prsubtract operations - * are the same and read from the same registers. */ - if (inst->U.I.PreSub.Opcode != RC_PRESUB_NONE) { - if (inst->U.I.PreSub.Opcode != presub_opcode - || inst->U.I.PreSub.SrcReg[0].File != - s->Inst->U.I.SrcReg[1].File - || inst->U.I.PreSub.SrcReg[0].Index != - s->Inst->U.I.SrcReg[1].Index) { - can_use_presub = 0; - } - } + reader_data.CbData = &cb_op; + rc_get_readers(c, inst_add, &reader_data, presub_scan_read, NULL, + is_src_clobbered_scan_write); - /* Even if the instruction can't use a presubtract operation - * we still need to check if the instruction reads from - * s->Inst->U.I.DstReg, because if it does we must not - * remove s->Inst. */ - for(i = 0; i < info->NumSrcRegs; i++) { - unsigned int mask = src_reads_dst_mask( - inst->U.I.SrcReg[i], s->Inst->U.I.DstReg); - /* XXX We could be more aggressive here using - * presubtract. It is okay if SrcReg[i] only reads - * from some of the mask components. */ - if(s->Inst->U.I.DstReg.WriteMask != mask) { - if (s->Inst->U.I.DstReg.WriteMask & mask) { - can_remove = 0; - break; - } else { - continue; - } - } - if (cant_sub || !can_use_presub) { - can_remove = 0; - break; - } - presub_replace(s, inst, i); - can_remove = 1; - } - if(!can_remove) - break; - rc_for_all_writes_mask(inst, peephole_scan_write, s); - /* If all components of inst_add's destination register have - * been written to by subsequent instructions, the original - * value of the destination register is no longer valid and - * we can't keep doing substitutions. */ - if (!s->WriteMask){ - break; - } - /* Make this instruction doesn't write to the presubtract source. */ - if (inst->U.I.DstReg.WriteMask & - src_reads_dst_mask(s->Inst->U.I.SrcReg[1], - inst->U.I.DstReg) - || src_reads_dst_mask(s->Inst->U.I.SrcReg[0], - inst->U.I.DstReg) - || info->IsFlowControl) { - cant_sub = 1; + if (reader_data.Abort || reader_data.ReaderCount == 0) + return 0; + + for(i = 0; i < reader_data.ReaderCount; i++) { + unsigned int src_index; + struct rc_reader reader = reader_data.Readers[i]; + const struct rc_opcode_info * info = + rc_get_opcode_info(reader.Inst->U.I.Opcode); + + for (src_index = 0; src_index < info->NumSrcRegs; src_index++) { + if (&reader.Inst->U.I.SrcReg[src_index] == reader.U.Src) + presub_replace(inst_add, reader.Inst, src_index); } } - return can_remove; + return 1; } -/* This function assumes that s->Inst->U.I.SrcReg[0] and - * s->Inst->U.I.SrcReg[1] aren't both negative. */ -static void presub_replace_add(struct peephole_state *s, - struct rc_instruction * inst, - unsigned int src_index) +/* This function assumes that inst_add->U.I.SrcReg[0] and + * inst_add->U.I.SrcReg[1] aren't both negative. */ +static void presub_replace_add( + struct rc_instruction * inst_add, + struct rc_instruction * inst_reader, + unsigned int src_index) { rc_presubtract_op presub_opcode; - if (s->Inst->U.I.SrcReg[1].Negate || s->Inst->U.I.SrcReg[0].Negate) + if (inst_add->U.I.SrcReg[1].Negate || inst_add->U.I.SrcReg[0].Negate) presub_opcode = RC_PRESUB_SUB; else presub_opcode = RC_PRESUB_ADD; - if (s->Inst->U.I.SrcReg[1].Negate) { - inst->U.I.PreSub.SrcReg[0] = s->Inst->U.I.SrcReg[1]; - inst->U.I.PreSub.SrcReg[1] = s->Inst->U.I.SrcReg[0]; + if (inst_add->U.I.SrcReg[1].Negate) { + inst_reader->U.I.PreSub.SrcReg[0] = inst_add->U.I.SrcReg[1]; + inst_reader->U.I.PreSub.SrcReg[1] = inst_add->U.I.SrcReg[0]; } else { - inst->U.I.PreSub.SrcReg[0] = s->Inst->U.I.SrcReg[0]; - inst->U.I.PreSub.SrcReg[1] = s->Inst->U.I.SrcReg[1]; + inst_reader->U.I.PreSub.SrcReg[0] = inst_add->U.I.SrcReg[0]; + inst_reader->U.I.PreSub.SrcReg[1] = inst_add->U.I.SrcReg[1]; } - inst->U.I.PreSub.SrcReg[0].Negate = 0; - inst->U.I.PreSub.SrcReg[1].Negate = 0; - inst->U.I.PreSub.Opcode = presub_opcode; - inst->U.I.SrcReg[src_index] = chain_srcregs(inst->U.I.SrcReg[src_index], - inst->U.I.PreSub.SrcReg[0]); - inst->U.I.SrcReg[src_index].File = RC_FILE_PRESUB; - inst->U.I.SrcReg[src_index].Index = presub_opcode; + inst_reader->U.I.PreSub.SrcReg[0].Negate = 0; + inst_reader->U.I.PreSub.SrcReg[1].Negate = 0; + inst_reader->U.I.PreSub.Opcode = presub_opcode; + inst_reader->U.I.SrcReg[src_index] = + chain_srcregs(inst_reader->U.I.SrcReg[src_index], + inst_reader->U.I.PreSub.SrcReg[0]); + inst_reader->U.I.SrcReg[src_index].File = RC_FILE_PRESUB; + inst_reader->U.I.SrcReg[src_index].Index = presub_opcode; } -static int is_presub_candidate(struct rc_instruction * inst) +static int is_presub_candidate( + struct radeon_compiler * c, + struct rc_instruction * inst) { const struct rc_opcode_info * info = rc_get_opcode_info(inst->U.I.Opcode); unsigned int i; @@ -565,7 +509,12 @@ static int is_presub_candidate(struct rc_instruction * inst) return 0; for(i = 0; i < info->NumSrcRegs; i++) { - if (src_reads_dst_mask(inst->U.I.SrcReg[i], inst->U.I.DstReg)) + struct rc_src_register src = inst->U.I.SrcReg[i]; + if (src_reads_dst_mask(src, inst->U.I.DstReg)) + return 0; + + src.File = RC_FILE_PRESUB; + if (!c->SwizzleCaps->IsNative(inst->U.I.Opcode, src)) return 0; } return 1; @@ -578,9 +527,8 @@ static int peephole_add_presub_add( struct rc_src_register * src0 = NULL; struct rc_src_register * src1 = NULL; unsigned int i; - struct peephole_state s; - if (!is_presub_candidate(inst_add)) + if (!is_presub_candidate(c, inst_add)) return 0; if (inst_add->U.I.SrcReg[0].Swizzle != inst_add->U.I.SrcReg[1].Swizzle) @@ -604,30 +552,28 @@ static int peephole_add_presub_add( if (!src1) return 0; - s.Inst = inst_add; - s.WriteMask = inst_add->U.I.DstReg.WriteMask; - if (presub_helper(c, &s, RC_PRESUB_ADD, presub_replace_add)) { + if (presub_helper(c, inst_add, RC_PRESUB_ADD, presub_replace_add)) { rc_remove_instruction(inst_add); return 1; } return 0; } -static void presub_replace_inv(struct peephole_state * s, - struct rc_instruction * inst, - unsigned int src_index) +static void presub_replace_inv( + struct rc_instruction * inst_add, + struct rc_instruction * inst_reader, + unsigned int src_index) { - /* We must be careful not to modify s->Inst, since it - * is possible it will remain part of the program. - * XXX Maybe pass a struct instead of a pointer for s->Inst.*/ - inst->U.I.PreSub.SrcReg[0] = s->Inst->U.I.SrcReg[1]; - inst->U.I.PreSub.SrcReg[0].Negate = 0; - inst->U.I.PreSub.Opcode = RC_PRESUB_INV; - inst->U.I.SrcReg[src_index] = chain_srcregs(inst->U.I.SrcReg[src_index], - inst->U.I.PreSub.SrcReg[0]); - - inst->U.I.SrcReg[src_index].File = RC_FILE_PRESUB; - inst->U.I.SrcReg[src_index].Index = RC_PRESUB_INV; + /* We must be careful not to modify inst_add, since it + * is possible it will remain part of the program.*/ + inst_reader->U.I.PreSub.SrcReg[0] = inst_add->U.I.SrcReg[1]; + inst_reader->U.I.PreSub.SrcReg[0].Negate = 0; + inst_reader->U.I.PreSub.Opcode = RC_PRESUB_INV; + inst_reader->U.I.SrcReg[src_index] = chain_srcregs(inst_reader->U.I.SrcReg[src_index], + inst_reader->U.I.PreSub.SrcReg[0]); + + inst_reader->U.I.SrcReg[src_index].File = RC_FILE_PRESUB; + inst_reader->U.I.SrcReg[src_index].Index = RC_PRESUB_INV; } /** @@ -645,9 +591,8 @@ static int peephole_add_presub_inv( struct rc_instruction * inst_add) { unsigned int i, swz, mask; - struct peephole_state s; - if (!is_presub_candidate(inst_add)) + if (!is_presub_candidate(c, inst_add)) return 0; mask = inst_add->U.I.DstReg.WriteMask; @@ -674,11 +619,7 @@ static int peephole_add_presub_inv( return 0; } - /* Setup the peephole_state information. */ - s.Inst = inst_add; - s.WriteMask = inst_add->U.I.DstReg.WriteMask; - - if (presub_helper(c, &s, RC_PRESUB_INV, presub_replace_inv)) { + if (presub_helper(c, inst_add, RC_PRESUB_INV, presub_replace_inv)) { rc_remove_instruction(inst_add); return 1; } |