diff options
author | Jason Ekstrand <[email protected]> | 2017-10-17 14:45:43 -0700 |
---|---|---|
committer | Jason Ekstrand <[email protected]> | 2017-11-07 10:37:52 -0800 |
commit | fd1bcccc2de9ba6a1ad6171342a155091963c3b9 (patch) | |
tree | 0d9489c5f90cc6aaee101c7321220d19316cfeb3 /src | |
parent | 6041a31e77680597614776e59edb12709ec2e019 (diff) |
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 <[email protected]>
Cc: [email protected]
Diffstat (limited to 'src')
-rw-r--r-- | src/intel/compiler/brw_fs_generator.cpp | 75 |
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 09bd6dbeb40..46be1c7a497 100644 --- a/src/intel/compiler/brw_fs_generator.cpp +++ b/src/intel/compiler/brw_fs_generator.cpp @@ -496,45 +496,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); + } } } } |