summaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers/dri/r300
diff options
context:
space:
mode:
authorTom Stellard <[email protected]>2011-04-16 12:39:09 -0700
committerTom Stellard <[email protected]>2011-04-16 13:55:54 -0700
commit0fa81d6d05b12db825be31533d9a485625ae35e2 (patch)
treec848a95b894d14a99228bdc377f64c13bf396763 /src/mesa/drivers/dri/r300
parentd5a5893adc395158e1dc77dacd417f4eb2696237 (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.c24
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))