nv50: use copies of tgsi src nv50_regs
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Wed, 2 Dec 2009 18:59:07 +0000 (19:59 +0100)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Sat, 12 Dec 2009 15:38:59 +0000 (16:38 +0100)
So we can use the 'mod' member without concern
if a source is used multiple times in 1 insn.

src/gallium/drivers/nv50/nv50_program.c

index f0fe7e616844bac6b3d03bfad6fd8f629007bb7f..61160568570707bbcf7dfd82214420a4988d7c46 100644 (file)
@@ -131,6 +131,9 @@ struct nv50_pc {
        struct nv50_reg *r_brdc;
        struct nv50_reg *r_dst[4];
 
+       struct nv50_reg reg_instances[16];
+       unsigned reg_instance_nr;
+
        unsigned interp_mode[32];
        /* perspective interpolation registers */
        struct nv50_reg *iv_p;
@@ -150,6 +153,19 @@ struct nv50_pc {
        boolean allow32;
 };
 
+static INLINE struct nv50_reg *
+reg_instance(struct nv50_pc *pc, struct nv50_reg *reg)
+{
+       struct nv50_reg *dup = NULL;
+       if (reg) {
+               assert(pc->reg_instance_nr < 16);
+               dup = &pc->reg_instances[pc->reg_instance_nr++];
+               *dup = *reg;
+               reg->mod = 0;
+       }
+       return dup;
+}
+
 static INLINE void
 ctor_reg(struct nv50_reg *reg, unsigned type, int index, int hw)
 {
@@ -898,7 +914,6 @@ static INLINE void
 emit_sub(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0,
         struct nv50_reg *src1)
 {
-       assert(src0 != src1);
        src1->mod ^= NV50_MOD_NEG;
        emit_add(pc, dst, src0, src1);
        src1->mod ^= NV50_MOD_NEG;
@@ -967,7 +982,6 @@ static INLINE void
 emit_msb(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0,
         struct nv50_reg *src1, struct nv50_reg *src2)
 {
-       assert(src2 != src0 && src2 != src1);
        src2->mod ^= NV50_MOD_NEG;
        emit_mad(pc, dst, src0, src1, src2);
        src2->mod ^= NV50_MOD_NEG;
@@ -1515,8 +1529,6 @@ convert_to_long(struct nv50_pc *pc, struct nv50_program_exec *e)
 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:
@@ -1526,29 +1538,14 @@ negate_supported(const struct tgsi_full_instruction *insn, int i)
        case TGSI_OPCODE_ADD:
        case TGSI_OPCODE_SUB:
        case TGSI_OPCODE_MAD:
-               break;
+               return TRUE;
        case TGSI_OPCODE_POW:
                if (i == 1)
-                       break;
+                       return TRUE;
                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->Src[s].Register.Index ==
-                    insn->Src[i].Register.Index) &&
-                   (insn->Src[s].Register.File ==
-                    insn->Src[i].Register.File))
-                       return FALSE;
-       }
-
-       return TRUE;
 }
 
 /* Return a read mask for source registers deduced from opcode & write mask. */
@@ -1882,7 +1879,8 @@ nv50_program_tx_insn(struct nv50_pc *pc,
 
                for (c = 0; c < 4; c++)
                        if (src_mask & (1 << c))
-                               src[i][c] = tgsi_src(pc, c, fs, neg_supp);
+                               src[i][c] = reg_instance(pc,
+                                       tgsi_src(pc, c, fs, neg_supp));
        }
 
        brdc = temp = pc->r_brdc;
@@ -2249,16 +2247,14 @@ nv50_program_tx_insn(struct nv50_pc *pc,
                for (c = 0; c < 4; c++) {
                        if (!src[i][c])
                                continue;
-                       src[i][c]->mod = 0;
-                       if (src[i][c]->index == -1 && src[i][c]->type == P_IMMD)
-                               FREE(src[i][c]);
-                       else
                        if (src[i][c]->acc < 0 && src[i][c]->type == P_CONST)
                                FREE(src[i][c]); /* indirect constant */
                }
        }
 
        kill_temp_temp(pc);
+       pc->reg_instance_nr = 0;
+
        return TRUE;
 }