diff options
author | Matt Turner <[email protected]> | 2015-02-03 17:38:49 -0800 |
---|---|---|
committer | Matt Turner <[email protected]> | 2015-02-04 12:14:34 -0800 |
commit | 7e6079439246e6a18d7f9d34b6c29a662dc619c7 (patch) | |
tree | 384b608d53e6d5f054eea6075794148a781240dc | |
parent | 661c8bb220faf6f7c2f065eec515cedfa8d5f8da (diff) |
i965/fs: Implement the WaCMPInstFlagDepClearedEarly work-around.
Prevents piglit regressions from the next patch.
Reviewed-by: Kenneth Graunke <[email protected]>
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs_generator.cpp | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp index 77d4908a457..8cd36f8ea3e 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp @@ -1734,7 +1734,42 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width) brw_F16TO32(p, dst, src[0]); break; case BRW_OPCODE_CMP: - brw_CMP(p, dst, inst->conditional_mod, src[0], src[1]); + /* The Ivybridge/BayTrail WaCMPInstFlagDepClearedEarly workaround says + * that when the destination is a GRF that the dependency-clear bit on + * the flag register is cleared early. + * + * Suggested workarounds are to disable coissuing CMP instructions + * or to split CMP(16) instructions into two CMP(8) instructions. + * + * We choose to split into CMP(8) instructions since disabling + * coissuing would affect CMP instructions not otherwise affected by + * the errata. + */ + if (dispatch_width == 16 && brw->gen == 7 && !brw->is_haswell) { + if (dst.file == BRW_GENERAL_REGISTER_FILE) { + brw_set_default_compression_control(p, BRW_COMPRESSION_NONE); + brw_CMP(p, firsthalf(dst), inst->conditional_mod, + firsthalf(src[0]), firsthalf(src[1])); + brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF); + brw_CMP(p, sechalf(dst), inst->conditional_mod, + sechalf(src[0]), sechalf(src[1])); + brw_set_default_compression_control(p, BRW_COMPRESSION_COMPRESSED); + + multiple_instructions_emitted = true; + } else if (dst.file == BRW_ARCHITECTURE_REGISTER_FILE) { + /* For unknown reasons, the aforementioned workaround is not + * sufficient. Overriding the type when the destination is the + * null register is necessary but not sufficient by itself. + */ + assert(dst.nr == BRW_ARF_NULL); + dst.type = BRW_REGISTER_TYPE_D; + brw_CMP(p, dst, inst->conditional_mod, src[0], src[1]); + } else { + unreachable("not reached"); + } + } else { + brw_CMP(p, dst, inst->conditional_mod, src[0], src[1]); + } break; case BRW_OPCODE_SEL: brw_SEL(p, dst, src[0], src[1]); |