summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Ekstrand <jason.ekstrand@intel.com>2017-10-17 14:45:43 -0700
committerAndres Gomez <agomez@igalia.com>2017-11-21 18:16:44 +0200
commiteb14fb271974aafb0b50cd5291aa6cfdf43ef978 (patch)
tree55a4930d7cc9773452b89c64e858963fc1a7bd25
parent73342c304d608e1a0180d19c5de50b177e27bdf7 (diff)
downloadmesa-eb14fb271974aafb0b50cd5291aa6cfdf43ef978.tar.gz
intel/fs: Fix MOV_INDIRECT for 64-bit values on little-core
The same workaround we need for 64-bit values on little core also takes care of the Ivy Bridge problem and does so a bit more efficiently so we can drop that code while we're here. Reviewed-by: Iago Toral Quiroga <itoral@igalia.com> Cc: mesa-stable@lists.freedesktop.org (cherry picked from commit fd1bcccc2de9ba6a1ad6171342a155091963c3b9)
-rw-r--r--src/intel/compiler/brw_fs_generator.cpp75
1 files changed, 39 insertions, 36 deletions
diff --git a/src/intel/compiler/brw_fs_generator.cpp b/src/intel/compiler/brw_fs_generator.cpp
index 0c14c03a21b..71332564143 100644
--- a/src/intel/compiler/brw_fs_generator.cpp
+++ b/src/intel/compiler/brw_fs_generator.cpp
@@ -479,45 +479,48 @@ fs_generator::generate_mov_indirect(fs_inst *inst,
* code, using it saves us 0 instructions and would require quite a bit
* of case-by-case work. It's just not worth it.
*/
- if (devinfo->gen >= 8 || devinfo->is_haswell || type_sz(reg.type) < 8) {
- brw_ADD(p, addr, indirect_byte_offset, brw_imm_uw(imm_byte_offset));
- } else {
- /* IVB reads two address register components per channel for
- * indirectly addressed 64-bit sources, so we need to initialize
- * adjacent address components to consecutive dwords of the source
- * region by emitting two separate ADD instructions. Found
- * empirically.
+ brw_ADD(p, addr, indirect_byte_offset, brw_imm_uw(imm_byte_offset));
+
+ if (type_sz(reg.type) > 4 &&
+ ((devinfo->gen == 7 && !devinfo->is_haswell) ||
+ devinfo->is_cherryview || gen_device_info_is_9lp(devinfo))) {
+ /* IVB has an issue (which we found empirically) where it reads two
+ * address register components per channel for indirectly addressed
+ * 64-bit sources.
+ *
+ * From the Cherryview PRM Vol 7. "Register Region Restrictions":
+ *
+ * "When source or destination datatype is 64b or operation is
+ * integer DWord multiply, indirect addressing must not be used."
+ *
+ * To work around both of these, we do two integer MOVs insead of one
+ * 64-bit MOV. Because no double value should ever cross a register
+ * boundary, it's safe to use the immediate offset in the indirect
+ * here to handle adding 4 bytes to the offset and avoid the extra
+ * ADD to the register file.
*/
- assert(inst->exec_size <= 4);
- brw_push_insn_state(p);
- brw_set_default_exec_size(p, cvt(inst->exec_size) - 1);
-
- brw_ADD(p, spread(addr, 2), indirect_byte_offset,
- brw_imm_uw(imm_byte_offset));
- brw_inst_set_no_dd_clear(devinfo, brw_last_inst, true);
-
- brw_ADD(p, spread(suboffset(addr, 1), 2), indirect_byte_offset,
- brw_imm_uw(imm_byte_offset + 4));
- brw_inst_set_no_dd_check(devinfo, brw_last_inst, true);
-
- brw_pop_insn_state(p);
- }
-
- struct brw_reg ind_src = brw_VxH_indirect(0, 0);
+ brw_MOV(p, subscript(dst, BRW_REGISTER_TYPE_D, 0),
+ retype(brw_VxH_indirect(0, 0), BRW_REGISTER_TYPE_D));
+ brw_MOV(p, subscript(dst, BRW_REGISTER_TYPE_D, 1),
+ retype(brw_VxH_indirect(0, 4), BRW_REGISTER_TYPE_D));
+ } else {
+ struct brw_reg ind_src = brw_VxH_indirect(0, 0);
- brw_inst *mov = brw_MOV(p, dst, retype(ind_src, reg.type));
+ brw_inst *mov = brw_MOV(p, dst, retype(ind_src, reg.type));
- if (devinfo->gen == 6 && dst.file == BRW_MESSAGE_REGISTER_FILE &&
- !inst->get_next()->is_tail_sentinel() &&
- ((fs_inst *)inst->get_next())->mlen > 0) {
- /* From the Sandybridge PRM:
- *
- * "[Errata: DevSNB(SNB)] If MRF register is updated by any
- * instruction that “indexed/indirect” source AND is followed by a
- * send, the instruction requires a “Switch”. This is to avoid
- * race condition where send may dispatch before MRF is updated."
- */
- brw_inst_set_thread_control(devinfo, mov, BRW_THREAD_SWITCH);
+ if (devinfo->gen == 6 && dst.file == BRW_MESSAGE_REGISTER_FILE &&
+ !inst->get_next()->is_tail_sentinel() &&
+ ((fs_inst *)inst->get_next())->mlen > 0) {
+ /* From the Sandybridge PRM:
+ *
+ * "[Errata: DevSNB(SNB)] If MRF register is updated by any
+ * instruction that “indexed/indirect” source AND is followed
+ * by a send, the instruction requires a “Switch”. This is to
+ * avoid race condition where send may dispatch before MRF is
+ * updated."
+ */
+ brw_inst_set_thread_control(devinfo, mov, BRW_THREAD_SWITCH);
+ }
}
}
}