From 52474d424622c13d7f37f5e954d92d88eefdeac9 Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Sat, 15 Jan 2011 14:03:05 +0100 Subject: nvc0: make sure all sources of the BIND op are distinct They're supposed to be assigned consecutive registers so they can't contain the same SSA value more than once. --- src/gallium/drivers/nvc0/nvc0_pc.c | 7 ++++++ src/gallium/drivers/nvc0/nvc0_pc.h | 1 + src/gallium/drivers/nvc0/nvc0_pc_optimize.c | 37 +++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) (limited to 'src') diff --git a/src/gallium/drivers/nvc0/nvc0_pc.c b/src/gallium/drivers/nvc0/nvc0_pc.c index 72483f120e..304a191976 100644 --- a/src/gallium/drivers/nvc0/nvc0_pc.c +++ b/src/gallium/drivers/nvc0/nvc0_pc.c @@ -514,6 +514,13 @@ nvc0_insn_insert_after(struct nv_instruction *at, struct nv_instruction *ni) ni->prev->next = ni; } +void +nvc0_insn_insert_before(struct nv_instruction *at, struct nv_instruction *ni) +{ + nvc0_insn_insert_after(at, ni); + nvc0_insns_permute(at, ni); +} + void nvc0_insn_delete(struct nv_instruction *nvi) { diff --git a/src/gallium/drivers/nvc0/nvc0_pc.h b/src/gallium/drivers/nvc0/nvc0_pc.h index 74867f02e7..969cc68c59 100644 --- a/src/gallium/drivers/nvc0/nvc0_pc.h +++ b/src/gallium/drivers/nvc0/nvc0_pc.h @@ -473,6 +473,7 @@ struct nv_pc { }; void nvc0_insn_append(struct nv_basic_block *, struct nv_instruction *); +void nvc0_insn_insert_before(struct nv_instruction *, struct nv_instruction *); void nvc0_insn_insert_after(struct nv_instruction *, struct nv_instruction *); static INLINE struct nv_instruction * diff --git a/src/gallium/drivers/nvc0/nvc0_pc_optimize.c b/src/gallium/drivers/nvc0/nvc0_pc_optimize.c index e4449c285b..8dce32b40c 100644 --- a/src/gallium/drivers/nvc0/nvc0_pc_optimize.c +++ b/src/gallium/drivers/nvc0/nvc0_pc_optimize.c @@ -1101,6 +1101,40 @@ nv_pass_cse(struct nv_pass *ctx, struct nv_basic_block *b) return 0; } +/* Make sure all sources of an NV_OP_BIND are distinct, they need to occupy + * neighbouring registers. CSE might have messed this up. + */ +static int +nv_pass_fix_bind(struct nv_pass *ctx, struct nv_basic_block *b) +{ + struct nv_value *val; + struct nv_instruction *bnd, *nvi, *next; + int s, t; + + for (bnd = b->entry; bnd; bnd = next) { + next = bnd->next; + if (bnd->opcode != NV_OP_BIND) + continue; + for (s = 0; s < 4 && bnd->src[s]; ++s) { + val = bnd->src[s]->value; + for (t = s + 1; t < 4 && bnd->src[t]; ++t) { + if (bnd->src[t]->value != val) + continue; + nvi = nv_alloc_instruction(ctx->pc, NV_OP_MOV); + nvi->def[0] = new_value_like(ctx->pc, val); + nvi->def[0]->insn = nvi; + nv_reference(ctx->pc, nvi, 0, val); + nvc0_insn_insert_before(bnd, nvi); + + nv_reference(ctx->pc, bnd, t, nvi->def[0]); + } + } + } + DESCEND_ARBITRARY(t, nv_pass_fix_bind); + + return 0; +} + static int nv_pc_pass0(struct nv_pc *pc, struct nv_basic_block *root) { @@ -1177,6 +1211,9 @@ nv_pc_pass0(struct nv_pc *pc, struct nv_basic_block *root) if (ret) return ret; + pc->pass_seq++; + ret = nv_pass_fix_bind(&pass, root); + return ret; } -- cgit v1.2.3