summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Turner <mattst88@gmail.com>2015-02-03 17:38:49 -0800
committerMatt Turner <mattst88@gmail.com>2015-02-04 12:14:34 -0800
commit7e6079439246e6a18d7f9d34b6c29a662dc619c7 (patch)
tree384b608d53e6d5f054eea6075794148a781240dc
parent661c8bb220faf6f7c2f065eec515cedfa8d5f8da (diff)
i965/fs: Implement the WaCMPInstFlagDepClearedEarly work-around.
Prevents piglit regressions from the next patch. Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_generator.cpp37
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]);