diff options
author | Christoph Bumiller <e0425955@student.tuwien.ac.at> | 2011-01-15 14:03:05 +0100 |
---|---|---|
committer | Christoph Bumiller <e0425955@student.tuwien.ac.at> | 2011-01-15 14:14:50 +0100 |
commit | 52474d424622c13d7f37f5e954d92d88eefdeac9 (patch) | |
tree | 90c6af9a63aceea6d080abebc82695dc86c50f93 /src/gallium/drivers/nvc0/nvc0_pc_optimize.c | |
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/gallium/drivers/nvc0/nvc0_pc_optimize.c')
-rw-r--r-- | src/gallium/drivers/nvc0/nvc0_pc_optimize.c | 37 |
1 files changed, 37 insertions, 0 deletions
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; } |