summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2010-03-09 11:56:14 -0800
committerEric Anholt <eric@anholt.net>2010-03-16 12:15:12 -0700
commit42e0e8686688ff91e92fa4ac46c6dacb2d5f2140 (patch)
tree2d23c5ebc378850e1ad15ab504711213dcaf76f4 /src
parentd24f59d0081074ae9c4532949e75147447c8a82a (diff)
i965: Unalias all GLSL source regs from the destination regs used.
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)
Diffstat (limited to 'src')
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_glsl.c138
1 files changed, 25 insertions, 113 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_wm_glsl.c b/src/mesa/drivers/dri/i965/brw_wm_glsl.c
index a42e6bf7a58..e3e6f663390 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_glsl.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_glsl.c
@@ -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