summaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp
diff options
context:
space:
mode:
authorFrancisco Jerez <currojerez@riseup.net>2016-04-25 15:40:05 -0700
committerSamuel Iglesias Gonsálvez <siglesias@igalia.com>2016-05-16 09:55:32 +0200
commit70dc19f9d628f0459db93466fbf65af1bfe75af1 (patch)
tree66b507d8b727db068acd13bfcd980f607fce52a1 /src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp
parent17decd940c1e105506db74e8539a77db271adbc5 (diff)
downloadexternal_mesa3d-70dc19f9d628f0459db93466fbf65af1bfe75af1.zip
external_mesa3d-70dc19f9d628f0459db93466fbf65af1bfe75af1.tar.gz
external_mesa3d-70dc19f9d628f0459db93466fbf65af1bfe75af1.tar.bz2
i965/fs: Fix propagation of copies with strided source.
This has likely been broken since we started propagating copies not matching the offset of the instruction exactly (1728e74957a62b1b4b9fbb62a7de2c12b77c8a75). The copy source stride needs to be taken into account to find out the offset at the origin that corresponds to the offset at the destination of the copy which is being read by the instruction. This has led to program miscompilation on both my SIMD32 branch and Igalia's FP64 branch. Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Diffstat (limited to 'src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp')
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp30
1 files changed, 20 insertions, 10 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp b/src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp
index 3c702d8..83791bf 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp
@@ -460,16 +460,26 @@ fs_visitor::try_copy_propagate(fs_inst *inst, int arg, acp_entry *entry)
* parts of vgrfs so we have to do some reg_offset magic.
*/
- /* Compute the offset of inst->src[arg] relative to inst->dst */
- assert(entry->dst.subreg_offset == 0);
- int rel_offset = inst->src[arg].reg_offset - entry->dst.reg_offset;
- int rel_suboffset = inst->src[arg].subreg_offset;
-
- /* Compute the final register offset (in bytes) */
- int offset = entry->src.reg_offset * 32 + entry->src.subreg_offset;
- offset += rel_offset * 32 + rel_suboffset;
- inst->src[arg].reg_offset = offset / 32;
- inst->src[arg].subreg_offset = offset % 32;
+ /* Compute the offset of inst->src[arg] relative to entry->dst */
+ const unsigned rel_offset = (inst->src[arg].reg_offset
+ - entry->dst.reg_offset) * REG_SIZE +
+ inst->src[arg].subreg_offset;
+
+ /* Compute the first component of the copy that the instruction is
+ * reading, and the base byte offset within that component.
+ */
+ assert(entry->dst.subreg_offset == 0 && entry->dst.stride == 1);
+ const unsigned component = rel_offset / type_sz(entry->dst.type);
+ const unsigned suboffset = rel_offset % type_sz(entry->dst.type);
+
+ /* Calculate the byte offset at the origin of the copy of the given
+ * component and suboffset.
+ */
+ const unsigned offset = suboffset +
+ component * entry->src.stride * type_sz(entry->src.type) +
+ entry->src.reg_offset * REG_SIZE + entry->src.subreg_offset;
+ inst->src[arg].reg_offset = offset / REG_SIZE;
+ inst->src[arg].subreg_offset = offset % REG_SIZE;
}
break;