i965: Unalias all GLSL source regs from the destination regs used.
authorEric Anholt <eric@anholt.net>
Tue, 9 Mar 2010 19:56:14 +0000 (11:56 -0800)
committerEric Anholt <eric@anholt.net>
Tue, 16 Mar 2010 19:15:12 +0000 (12:15 -0700)
We were doing it ad-hoc before, as instructions with potential
aliasing problems were identified.  But thanks to swizzling basically
anything can have aliasing, so just do it generally at source reg
setup time.  This is somewhat inefficient, because sometimes an
operation doesn't need unaliasing protection if the swizzling is safe,
but the unaliasing before didn't cover those cases either.

Fixes piglit glsl-fs-loop.
(cherry picked from commit 6b194dab6b4d9f12cdd54c699b23c0d3420a49c2)

src/mesa/drivers/dri/i965/brw_wm_glsl.c

index a42e6bf7a58788532472949ccb79eb6c3ca1358e..e3e6f6633903be3b4ded92220c6ffbab3a194a80 100644 (file)
@@ -614,112 +614,6 @@ static void invoke_subroutine( struct brw_wm_compile *c,
     }
 }
 
-/* Workaround for using brw_wm_emit.c's emit functions, which expect
- * destination regs to be uniquely written.  Moves arguments out to
- * temporaries as necessary for instructions which use their destination as
- * a temporary.
- */
-static void
-unalias3(struct brw_wm_compile *c,
-        void (*func)(struct brw_compile *c,
-                     const struct brw_reg *dst,
-                     GLuint mask,
-                     const struct brw_reg *arg0,
-                     const struct brw_reg *arg1,
-                     const struct brw_reg *arg2),
-        const struct brw_reg *dst,
-        GLuint mask,
-        const struct brw_reg *arg0,
-        const struct brw_reg *arg1,
-        const struct brw_reg *arg2)
-{
-    struct brw_compile *p = &c->func;
-    struct brw_reg tmp_arg0[4], tmp_arg1[4], tmp_arg2[4];
-    int i, j;
-    int mark = mark_tmps(c);
-
-    for (j = 0; j < 4; j++) {
-       tmp_arg0[j] = arg0[j];
-       tmp_arg1[j] = arg1[j];
-       tmp_arg2[j] = arg2[j];
-    }
-
-    for (i = 0; i < 4; i++) {
-       if (mask & (1<<i)) {
-           for (j = 0; j < 4; j++) {
-               if (arg0[j].file == dst[i].file &&
-                   dst[i].nr == arg0[j].nr) {
-                   tmp_arg0[j] = alloc_tmp(c);
-                   brw_MOV(p, tmp_arg0[j], arg0[j]);
-               }
-               if (arg1[j].file == dst[i].file &&
-                   dst[i].nr == arg1[j].nr) {
-                   tmp_arg1[j] = alloc_tmp(c);
-                   brw_MOV(p, tmp_arg1[j], arg1[j]);
-               }
-               if (arg2[j].file == dst[i].file &&
-                   dst[i].nr == arg2[j].nr) {
-                   tmp_arg2[j] = alloc_tmp(c);
-                   brw_MOV(p, tmp_arg2[j], arg2[j]);
-               }
-           }
-       }
-    }
-
-    func(p, dst, mask, tmp_arg0, tmp_arg1, tmp_arg2);
-
-    release_tmps(c, mark);
-}
-
-/* Workaround for using brw_wm_emit.c's emit functions, which expect
- * destination regs to be uniquely written.  Moves arguments out to
- * temporaries as necessary for instructions which use their destination as
- * a temporary.
- */
-static void
-unalias2(struct brw_wm_compile *c,
-        void (*func)(struct brw_compile *c,
-                     const struct brw_reg *dst,
-                     GLuint mask,
-                     const struct brw_reg *arg0,
-                     const struct brw_reg *arg1),
-        const struct brw_reg *dst,
-        GLuint mask,
-        const struct brw_reg *arg0,
-        const struct brw_reg *arg1)
-{
-    struct brw_compile *p = &c->func;
-    struct brw_reg tmp_arg0[4], tmp_arg1[4];
-    int i, j;
-    int mark = mark_tmps(c);
-
-    for (j = 0; j < 4; j++) {
-       tmp_arg0[j] = arg0[j];
-       tmp_arg1[j] = arg1[j];
-    }
-
-    for (i = 0; i < 4; i++) {
-       if (mask & (1<<i)) {
-           for (j = 0; j < 4; j++) {
-               if (arg0[j].file == dst[i].file &&
-                   dst[i].nr == arg0[j].nr) {
-                   tmp_arg0[j] = alloc_tmp(c);
-                   brw_MOV(p, tmp_arg0[j], arg0[j]);
-               }
-               if (arg1[j].file == dst[i].file &&
-                   dst[i].nr == arg1[j].nr) {
-                   tmp_arg1[j] = alloc_tmp(c);
-                   brw_MOV(p, tmp_arg1[j], arg1[j]);
-               }
-           }
-       }
-    }
-
-    func(p, dst, mask, tmp_arg0, tmp_arg1);
-
-    release_tmps(c, mark);
-}
-
 static void emit_arl(struct brw_wm_compile *c,
                      const struct prog_instruction *inst)
 {
@@ -1813,14 +1707,29 @@ static void
 get_argument_regs(struct brw_wm_compile *c,
                  const struct prog_instruction *inst,
                  int index,
+                 struct brw_reg *dst,
                  struct brw_reg *regs,
                  int mask)
 {
-    int i;
+    struct brw_compile *p = &c->func;
+    int i, j;
 
     for (i = 0; i < 4; i++) {
-       if (mask & (1 << i))
+       if (mask & (1 << i)) {
            regs[i] = get_src_reg(c, inst, index, i);
+
+           /* Unalias destination registers from our sources. */
+           if (regs[i].file == BRW_GENERAL_REGISTER_FILE) {
+              for (j = 0; j < 4; j++) {
+                  if (memcmp(&regs[i], &dst[j], sizeof(regs[0])) == 0) {
+                      struct brw_reg tmp = alloc_tmp(c);
+                      brw_MOV(p, tmp, regs[i]);
+                      regs[i] = tmp;
+                      break;
+                  }
+              }
+           }
+       }
     }
 }
 
@@ -1845,6 +1754,7 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
        int dst_flags;
        struct brw_reg args[3][4], dst[4];
        int j;
+       int mark = mark_tmps( c );
 
         c->cur_inst = i;
 
@@ -1866,7 +1776,7 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
           }
        }
        for (j = 0; j < brw_wm_nr_args(inst->Opcode); j++)
-           get_argument_regs(c, inst, j, args[j], WRITEMASK_XYZW);
+           get_argument_regs(c, inst, j, dst, args[j], WRITEMASK_XYZW);
 
        dst_flags = inst->DstReg.WriteMask;
        if (inst->SaturateMode == SATURATE_ZERO_ONE)
@@ -1920,8 +1830,7 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
                emit_alu1(p, brw_RNDD, dst, dst_flags, args[0]);
                break;
            case OPCODE_LRP:
-               unalias3(c, emit_lrp,
-                        dst, dst_flags, args[0], args[1], args[2]);
+               emit_lrp(p, dst, dst_flags, args[0], args[1], args[2]);
                break;
            case OPCODE_TRUNC:
                emit_alu1(p, brw_RNDZ, dst, dst_flags, args[0]);
@@ -1964,10 +1873,10 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
                emit_cmp(p, dst, dst_flags, args[0], args[1], args[2]);
                break;
            case OPCODE_MIN:    
-               unalias2(c, emit_min, dst, dst_flags, args[0], args[1]);
+               emit_min(p, dst, dst_flags, args[0], args[1]);
                break;
            case OPCODE_MAX:    
-               unalias2(c, emit_max, dst, dst_flags, args[0], args[1]);
+               emit_max(p, dst, dst_flags, args[0], args[1]);
                break;
            case OPCODE_DDX:
            case OPCODE_DDY:
@@ -2122,6 +2031,9 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
                        inst->Opcode);
        }
 
+       /* Release temporaries containing any unaliased source regs. */
+       release_tmps( c, mark );
+
        if (inst->CondUpdate)
            brw_set_predicate_control(p, BRW_PREDICATE_NORMAL);
        else