[Mesa-dev] [PATCH 1/2] i965: Refactor SIMD16-to-2xSIMD8 checks.

Kenneth Graunke kenneth at whitecape.org
Wed Mar 4 12:53:44 PST 2015


Gathering all the checks into a single place makes it easier to add new
workarounds.

Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
Cc: Neil Roberts <neil at linux.intel.com>
Cc: Matt Turner <mattst88 at gmail.com>
---
 src/mesa/drivers/dri/i965/brw_fs_generator.cpp | 28 +++++----------
 src/mesa/drivers/dri/i965/brw_shader.cpp       | 48 ++++++++++++++++++++++++++
 src/mesa/drivers/dri/i965/brw_shader.h         |  1 +
 3 files changed, 58 insertions(+), 19 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp
index cbe6191..8a5ad9b 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp
@@ -1613,6 +1613,9 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
          unreachable(!"Invalid instruction width");
       }
 
+      bool must_break_down_simd16_to_simd8 = dispatch_width == 16 &&
+         !brw_instruction_supports_simd16(brw, inst->opcode);
+
       switch (inst->opcode) {
       case BRW_OPCODE_MOV:
 	 brw_MOV(p, dst, src[0]);
@@ -1637,7 +1640,7 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
       case BRW_OPCODE_MAD:
          assert(brw->gen >= 6);
 	 brw_set_default_access_mode(p, BRW_ALIGN_16);
-         if (dispatch_width == 16 && brw->gen < 8 && !brw->is_haswell) {
+         if (must_break_down_simd16_to_simd8) {
 	    brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
             brw_inst *f = brw_MAD(p, firsthalf(dst), firsthalf(src[0]), firsthalf(src[1]), firsthalf(src[2]));
 	    brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF);
@@ -1658,7 +1661,7 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
       case BRW_OPCODE_LRP:
          assert(brw->gen >= 6);
 	 brw_set_default_access_mode(p, BRW_ALIGN_16);
-         if (dispatch_width == 16 && brw->gen < 8 && !brw->is_haswell) {
+         if (must_break_down_simd16_to_simd8) {
 	    brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
             brw_inst *f = brw_LRP(p, firsthalf(dst), firsthalf(src[0]), firsthalf(src[1]), firsthalf(src[2]));
 	    brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF);
@@ -1730,7 +1733,7 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
           * coissuing would affect CMP instructions not otherwise affected by
           * the errata.
           */
-         if (dispatch_width == 16 && brw->gen == 7 && !brw->is_haswell) {
+         if (must_break_down_simd16_to_simd8) {
             if (dst.file == BRW_GENERAL_REGISTER_FILE) {
                brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
                brw_CMP(p, firsthalf(dst), inst->conditional_mod,
@@ -1795,7 +1798,7 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
       case BRW_OPCODE_BFE:
          assert(brw->gen >= 7);
          brw_set_default_access_mode(p, BRW_ALIGN_16);
-         if (dispatch_width == 16 && brw->gen < 8 && !brw->is_haswell) {
+         if (must_break_down_simd16_to_simd8) {
             brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
             brw_BFE(p, firsthalf(dst), firsthalf(src[0]), firsthalf(src[1]), firsthalf(src[2]));
             brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF);
@@ -1809,12 +1812,7 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
 
       case BRW_OPCODE_BFI1:
          assert(brw->gen >= 7);
-         /* The Haswell WaForceSIMD8ForBFIInstruction workaround says that we
-          * should
-          *
-          *    "Force BFI instructions to be executed always in SIMD8."
-          */
-         if (dispatch_width == 16 && brw->is_haswell) {
+         if (must_break_down_simd16_to_simd8) {
             brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
             brw_BFI1(p, firsthalf(dst), firsthalf(src[0]), firsthalf(src[1]));
             brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF);
@@ -1827,15 +1825,7 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
       case BRW_OPCODE_BFI2:
          assert(brw->gen >= 7);
          brw_set_default_access_mode(p, BRW_ALIGN_16);
-         /* The Haswell WaForceSIMD8ForBFIInstruction workaround says that we
-          * should
-          *
-          *    "Force BFI instructions to be executed always in SIMD8."
-          *
-          * Otherwise we would be able to emit compressed instructions like we
-          * do for the other three-source instructions.
-          */
-         if (dispatch_width == 16 && brw->gen < 8) {
+         if (must_break_down_simd16_to_simd8) {
             brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
             brw_BFI2(p, firsthalf(dst), firsthalf(src[0]), firsthalf(src[1]), firsthalf(src[2]));
             brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF);
diff --git a/src/mesa/drivers/dri/i965/brw_shader.cpp b/src/mesa/drivers/dri/i965/brw_shader.cpp
index ec3cfcb..fed4ba3 100644
--- a/src/mesa/drivers/dri/i965/brw_shader.cpp
+++ b/src/mesa/drivers/dri/i965/brw_shader.cpp
@@ -392,6 +392,54 @@ brw_texture_offset(struct gl_context *ctx, int *offsets,
    return offset_bits;
 }
 
+/**
+ * Some instructions aren't always natively supported in SIMD16 mode
+ * and need to be broken down into a pair of SIMD8 instructions.
+ */
+bool
+brw_instruction_supports_simd16(const struct brw_context *brw, enum opcode op)
+{
+   bool supports_3src = brw->is_haswell || brw->gen >= 8;
+
+   switch (op) {
+   case BRW_OPCODE_MAD:
+   case BRW_OPCODE_LRP:
+      return supports_3src;
+   case BRW_OPCODE_BFI2:
+      /* The Haswell WaForceSIMD8ForBFIInstruction workaround says that we
+       * should
+       *
+       *    "Force BFI instructions to be executed always in SIMD8."
+       *
+       * Otherwise we would be able to emit compressed instructions like we
+       * do for the other three-source instructions.
+       */
+      return supports_3src && !brw->is_haswell;
+   case BRW_OPCODE_BFI1:
+      /* The Haswell WaForceSIMD8ForBFIInstruction workarounds says that we
+       * should
+       *
+       *    "Force BFI instructions to be executed always in SIMD8."
+       */
+      return !brw->is_haswell;
+   case BRW_OPCODE_CMP:
+      /* 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.
+       */
+      return brw->gen != 7 || brw->is_haswell;
+   default:
+      return true;
+   }
+}
+
 const char *
 brw_instruction_name(enum opcode op)
 {
diff --git a/src/mesa/drivers/dri/i965/brw_shader.h b/src/mesa/drivers/dri/i965/brw_shader.h
index 5c95355..a9c9565 100644
--- a/src/mesa/drivers/dri/i965/brw_shader.h
+++ b/src/mesa/drivers/dri/i965/brw_shader.h
@@ -212,6 +212,7 @@ uint32_t brw_texture_offset(struct gl_context *ctx, int *offsets,
 enum brw_reg_type brw_type_for_base_type(const struct glsl_type *type);
 enum brw_conditional_mod brw_conditional_for_comparison(unsigned int op);
 uint32_t brw_math_function(enum opcode op);
+bool brw_instruction_supports_simd16(const struct brw_context *brw, enum opcode);
 const char *brw_instruction_name(enum opcode op);
 bool brw_saturate_immediate(enum brw_reg_type type, struct brw_reg *reg);
 bool brw_negate_immediate(enum brw_reg_type type, struct brw_reg *reg);
-- 
2.2.2



More information about the mesa-dev mailing list