Mesa (7.9): r300/compiler: Fix two mistakes in the presubtract optimization pass.
Tom Stellard
tstellar at kemper.freedesktop.org
Sat Sep 25 23:12:35 UTC 2010
Module: Mesa
Branch: 7.9
Commit: 5c78e931c230bee49f225cb00a66694529448acf
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=5c78e931c230bee49f225cb00a66694529448acf
Author: Tom Stellard <tstellar at gmail.com>
Date: Fri Sep 24 22:14:43 2010 -0700
r300/compiler: Fix two mistakes in the presubtract optimization pass.
1. We can't turn an instruction into a presubtract operation if it
writes to one of the registers it reads from.
2. If we turn an instruction into a presubtract operation, we can't
remove that intruction unless all readers can use the presubtract
operation.
This fixes fdo bug 30337.
This is a candidate for the 7.9 branch.
(cherry picked from commit 522e994a22e8b46c8a41f2920af88c5ebad43cd8)
---
.../drivers/dri/r300/compiler/radeon_optimize.c | 45 +++++++++++++------
1 files changed, 31 insertions(+), 14 deletions(-)
diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c b/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c
index c15a9b1..e288930 100644
--- a/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c
+++ b/src/mesa/drivers/dri/r300/compiler/radeon_optimize.c
@@ -475,8 +475,8 @@ static void constant_folding(struct radeon_compiler * c, struct rc_instruction *
}
/**
- * This function returns a writemask that indicates wich components are
- * read by src and also written by dst.
+ * If src and dst use the same register, this function returns a writemask that
+ * indicates wich components are read by src. Otherwise zero is returned.
*/
static unsigned int src_reads_dst_mask(struct rc_src_register src,
struct rc_dst_register dst)
@@ -563,10 +563,18 @@ static int presub_helper(
* s->Inst->U.I.DstReg, because if it does we must not
* remove s->Inst. */
for(i = 0; i < info->NumSrcRegs; i++) {
- if(s->Inst->U.I.DstReg.WriteMask !=
- src_reads_dst_mask(inst->U.I.SrcReg[i],
- s->Inst->U.I.DstReg)) {
- continue;
+ 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;
@@ -626,6 +634,21 @@ static void presub_replace_add(struct peephole_state *s,
inst->U.I.SrcReg[src_index].Index = presub_opcode;
}
+static int is_presub_candidate(struct rc_instruction * inst)
+{
+ const struct rc_opcode_info * info = rc_get_opcode_info(inst->U.I.Opcode);
+ unsigned int i;
+
+ if (inst->U.I.PreSub.Opcode != RC_PRESUB_NONE || inst->U.I.SaturateMode)
+ return 0;
+
+ for(i = 0; i < info->NumSrcRegs; i++) {
+ if (src_reads_dst_mask(inst->U.I.SrcReg[i], inst->U.I.DstReg))
+ return 0;
+ }
+ return 1;
+}
+
static int peephole_add_presub_add(
struct radeon_compiler * c,
struct rc_instruction * inst_add)
@@ -635,10 +658,7 @@ static int peephole_add_presub_add(
unsigned int i;
struct peephole_state s;
- if (inst_add->U.I.PreSub.Opcode != RC_PRESUB_NONE)
- return 0;
-
- if (inst_add->U.I.SaturateMode)
+ if (!is_presub_candidate(inst_add))
return 0;
if (inst_add->U.I.SrcReg[0].Swizzle != inst_add->U.I.SrcReg[1].Swizzle)
@@ -705,10 +725,7 @@ static int peephole_add_presub_inv(
unsigned int i, swz, mask;
struct peephole_state s;
- if (inst_add->U.I.PreSub.Opcode != RC_PRESUB_NONE)
- return 0;
-
- if (inst_add->U.I.SaturateMode)
+ if (!is_presub_candidate(inst_add))
return 0;
mask = inst_add->U.I.DstReg.WriteMask;
More information about the mesa-commit
mailing list