diff options
author | Eric Anholt <eric@anholt.net> | 2011-02-04 13:31:02 -0600 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2011-02-08 11:42:35 -0800 |
commit | 76857e8954484d5bf8758d7bfc87f264f95a0ebd (patch) | |
tree | 71c2a2ebfb980804487a93ee2c18e3178d184be5 | |
parent | 60aab5f335537e5b6788132e2563865243483750 (diff) |
mesa: Fix the Mesa IR copy propagation to not read past writes to the reg.
Fixes glsl-vs-post-increment-01.
Reviewed-by: José Fonseca <jfonseca@vmware.com>
-rw-r--r-- | src/mesa/program/ir_to_mesa.cpp | 47 |
1 files changed, 40 insertions, 7 deletions
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 3794c0de02..d0ec23fc85 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2742,13 +2742,46 @@ ir_to_mesa_visitor::copy_propagate(void) /* Continuing the block, clear any written channels from * the ACP. */ - if (inst->dst_reg.file == PROGRAM_TEMPORARY) { - if (inst->dst_reg.reladdr) { - memset(acp, 0, sizeof(*acp) * this->next_temp * 4); - } else { - for (int i = 0; i < 4; i++) { - if (inst->dst_reg.writemask & (1 << i)) { - acp[4 * inst->dst_reg.index + i] = NULL; + if (inst->dst_reg.file == PROGRAM_TEMPORARY && inst->dst_reg.reladdr) { + /* Any temporary might be written, so no copy propagation + * across this instruction. + */ + memset(acp, 0, sizeof(*acp) * this->next_temp * 4); + } else if (inst->dst_reg.file == PROGRAM_OUTPUT && + inst->dst_reg.reladdr) { + /* Any output might be written, so no copy propagation + * from outputs across this instruction. + */ + for (int r = 0; r < this->next_temp; r++) { + for (int c = 0; c < 4; c++) { + if (acp[4 * r + c]->src_reg[0].file == PROGRAM_OUTPUT) + acp[4 * r + c] = NULL; + } + } + } else if (inst->dst_reg.file == PROGRAM_TEMPORARY || + inst->dst_reg.file == PROGRAM_OUTPUT) { + /* Clear where it's used as dst. */ + if (inst->dst_reg.file == PROGRAM_TEMPORARY) { + for (int c = 0; c < 4; c++) { + if (inst->dst_reg.writemask & (1 << c)) { + acp[4 * inst->dst_reg.index + c] = NULL; + } + } + } + + /* Clear where it's used as src. */ + for (int r = 0; r < this->next_temp; r++) { + for (int c = 0; c < 4; c++) { + if (!acp[4 * r + c]) + continue; + + int src_chan = GET_SWZ(acp[4 * r + c]->src_reg[0].swizzle, c); + + if (acp[4 * r + c]->src_reg[0].file == inst->dst_reg.file && + acp[4 * r + c]->src_reg[0].index == inst->dst_reg.index && + inst->dst_reg.writemask & (1 << src_chan)) + { + acp[4 * r + c] = NULL; } } } |