diff options
author | Christoph Bumiller <[email protected]> | 2011-01-15 14:03:05 +0100 |
---|---|---|
committer | Christoph Bumiller <[email protected]> | 2011-01-15 14:14:50 +0100 |
commit | 52474d424622c13d7f37f5e954d92d88eefdeac9 (patch) | |
tree | 90c6af9a63aceea6d080abebc82695dc86c50f93 /src | |
parent | 1ae982adfd8144d11334895c39aca65dd30ad946 (diff) |
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/drivers/nvc0/nvc0_pc.c | 7 | ||||
-rw-r--r-- | src/gallium/drivers/nvc0/nvc0_pc.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/nvc0/nvc0_pc_optimize.c | 37 |
3 files changed, 45 insertions, 0 deletions
diff --git a/src/gallium/drivers/nvc0/nvc0_pc.c b/src/gallium/drivers/nvc0/nvc0_pc.c index 72483f120ed..304a1919768 100644 --- a/src/gallium/drivers/nvc0/nvc0_pc.c +++ b/src/gallium/drivers/nvc0/nvc0_pc.c @@ -515,6 +515,13 @@ nvc0_insn_insert_after(struct nv_instruction *at, struct nv_instruction *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) { struct nv_basic_block *b = nvi->bb; diff --git a/src/gallium/drivers/nvc0/nvc0_pc.h b/src/gallium/drivers/nvc0/nvc0_pc.h index 74867f02e72..969cc68c596 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 e4449c285b5..8dce32b40c3 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; } |