nv50: quick fix for insn src negation
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Tue, 13 Oct 2009 13:09:13 +0000 (15:09 +0200)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Mon, 19 Oct 2009 16:25:09 +0000 (18:25 +0200)
We only have a per nv50_reg negation flag, if an
nv50_reg is used more than once in a TGSI op with
different sign modes, we'd generate wrong code.

We probably can't do much better without more
invasive changes.

src/gallium/drivers/nv50/nv50_program.c

index 89e0ac8db9fedfa1e651d9ca54ae22c15373b436..1bd6f717d103e622ec9c5e99dbf5a9c3dd5e1022 100644 (file)
@@ -1293,9 +1293,12 @@ convert_to_long(struct nv50_pc *pc, struct nv50_program_exec *e)
        e->inst[1] |= q;
 }
 
+/* Some operations support an optional negation flag. */
 static boolean
 negate_supported(const struct tgsi_full_instruction *insn, int i)
 {
+       int s;
+
        switch (insn->Instruction.Opcode) {
        case TGSI_OPCODE_DDY:
        case TGSI_OPCODE_DP3:
@@ -1305,12 +1308,29 @@ negate_supported(const struct tgsi_full_instruction *insn, int i)
        case TGSI_OPCODE_ADD:
        case TGSI_OPCODE_SUB:
        case TGSI_OPCODE_MAD:
-               return TRUE;
+               break;
        case TGSI_OPCODE_POW:
-               return (i == 1) ? TRUE : FALSE;
+               if (i == 1)
+                       break;
+               return FALSE;
        default:
                return FALSE;
        }
+
+       /* Watch out for possible multiple uses of an nv50_reg, we
+        * can't use nv50_reg::neg in these cases.
+        */
+       for (s = 0; s < insn->Instruction.NumSrcRegs; ++s) {
+               if (s == i)
+                       continue;
+               if ((insn->FullSrcRegisters[s].SrcRegister.Index ==
+                    insn->FullSrcRegisters[i].SrcRegister.Index) &&
+                   (insn->FullSrcRegisters[s].SrcRegister.File ==
+                    insn->FullSrcRegisters[i].SrcRegister.File))
+                       return FALSE;
+       }
+
+       return TRUE;
 }
 
 /* Return a read mask for source registers deduced from opcode & write mask. */
@@ -1956,6 +1976,7 @@ nv50_program_tx_insn(struct nv50_pc *pc,
                for (c = 0; c < 4; c++) {
                        if (!src[i][c])
                                continue;
+                       src[i][c]->neg = 0;
                        if (src[i][c]->index == -1 && src[i][c]->type == P_IMMD)
                                FREE(src[i][c]);
                }