diff options
author | Tom Stellard <[email protected]> | 2011-04-16 12:39:09 -0700 |
---|---|---|
committer | Tom Stellard <[email protected]> | 2011-04-16 13:55:54 -0700 |
commit | 0fa81d6d05b12db825be31533d9a485625ae35e2 (patch) | |
tree | c848a95b894d14a99228bdc377f64c13bf396763 /src/mesa/drivers/dri/r300 | |
parent | d5a5893adc395158e1dc77dacd417f4eb2696237 (diff) |
r300/compiler: Fix incorrect presubtract conversion
ADD instructions with constant swizzles can't be converted to
presubtract operations.
NOTE: This is a candidate for the 7.9 and 7.10 branches.
Diffstat (limited to 'src/mesa/drivers/dri/r300')
-rw-r--r-- | src/mesa/drivers/dri/r300/compiler/radeon_optimize.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c b/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c index c4e6a5e0a1f..79898e1047e 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c @@ -509,10 +509,34 @@ static int is_presub_candidate( { const struct rc_opcode_info * info = rc_get_opcode_info(inst->U.I.Opcode); unsigned int i; + unsigned int is_constant[2] = {0, 0}; + + assert(inst->U.I.Opcode == RC_OPCODE_ADD); if (inst->U.I.PreSub.Opcode != RC_PRESUB_NONE || inst->U.I.SaturateMode) return 0; + /* If both sources use a constant swizzle, then we can't convert it to + * a presubtract operation. In fact for the ADD and SUB presubtract + * operations neither source can contain a constant swizzle. This + * specific case is checked in peephole_add_presub_add() when + * we make sure the swizzles for both sources are equal, so we + * don't need to worry about it here. */ + for (i = 0; i < 2; i++) { + int chan; + for (chan = 0; chan < 4; chan++) { + rc_swizzle swz = + get_swz(inst->U.I.SrcReg[i].Swizzle, chan); + if (swz == RC_SWIZZLE_ONE + || swz == RC_SWIZZLE_ZERO + || swz == RC_SWIZZLE_HALF) { + is_constant[i] = 1; + } + } + } + if (is_constant[0] && is_constant[1]) + return 0; + for(i = 0; i < info->NumSrcRegs; i++) { struct rc_src_register src = inst->U.I.SrcReg[i]; if (src_reads_dst_mask(src, inst->U.I.DstReg)) |