[Mesa-dev] [PATCH 2/3] i965: Lower min/max after optimization on Gen4/5.

Matt Turner mattst88 at gmail.com
Fri Feb 12 00:41:49 UTC 2016


Gen4/5's SEL instruction cannot use conditional modifiers, so min/max
are implemented as CMP + SEL. Handling that after optimization lets us
CSE more.

On Ironlake:

   total instructions in shared programs: 6426035 -> 6422753 (-0.05%)
   instructions in affected programs: 326604 -> 323322 (-1.00%)
   helped: 1411

   total cycles in shared programs: 129184700 -> 129101586 (-0.06%)
   cycles in affected programs: 18950290 -> 18867176 (-0.44%)
   helped: 2419
   HURT: 328
---
 src/mesa/drivers/dri/i965/brw_fs.cpp           | 37 +++++++++++++++++++++++++
 src/mesa/drivers/dri/i965/brw_fs.h             |  1 +
 src/mesa/drivers/dri/i965/brw_fs_builder.h     | 10 ++-----
 src/mesa/drivers/dri/i965/brw_fs_nir.cpp       | 20 +++-----------
 src/mesa/drivers/dri/i965/brw_vec4.cpp         | 38 ++++++++++++++++++++++++++
 src/mesa/drivers/dri/i965/brw_vec4.h           |  2 ++
 src/mesa/drivers/dri/i965/brw_vec4_builder.h   | 10 ++-----
 src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp | 14 ++--------
 8 files changed, 88 insertions(+), 44 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index 0ce7ed1..e83f0ba 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -3475,6 +3475,36 @@ fs_visitor::lower_integer_multiplication()
    return progress;
 }
 
+bool
+fs_visitor::lower_minmax()
+{
+   assert(devinfo->gen < 6);
+
+   bool progress = false;
+
+   foreach_block_and_inst_safe(block, fs_inst, inst, cfg) {
+      const fs_builder ibld(this, block, inst);
+
+      if (inst->opcode == BRW_OPCODE_SEL &&
+          inst->predicate == BRW_PREDICATE_NONE) {
+         assert(inst->conditional_mod == BRW_CONDITIONAL_GE ||
+                inst->conditional_mod == BRW_CONDITIONAL_L);
+
+         ibld.CMP(ibld.null_reg_d(), inst->src[0], inst->src[1],
+                  inst->conditional_mod);
+         inst->predicate = BRW_PREDICATE_NORMAL;
+         inst->conditional_mod = BRW_CONDITIONAL_NONE;
+
+         progress = true;
+      }
+   }
+
+   if (progress)
+      invalidate_live_intervals();
+
+   return progress;
+}
+
 static void
 setup_color_payload(const fs_builder &bld, const brw_wm_prog_key *key,
                     fs_reg *dst, fs_reg color, unsigned components)
@@ -5132,6 +5162,13 @@ fs_visitor::optimize()
    OPT(opt_combine_constants);
    OPT(lower_integer_multiplication);
 
+   if (devinfo->gen <= 5 && OPT(lower_minmax)) {
+      OPT(opt_cmod_propagation);
+      OPT(opt_cse);
+      OPT(opt_copy_propagate);
+      OPT(dead_code_eliminate);
+   }
+
    lower_uniform_pull_constant_loads();
 
    validate();
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index 4a26ac1..16fccf6 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -175,6 +175,7 @@ public:
    bool lower_load_payload();
    bool lower_logical_sends();
    bool lower_integer_multiplication();
+   bool lower_minmax();
    bool lower_simd_width();
    bool opt_combine_constants();
 
diff --git a/src/mesa/drivers/dri/i965/brw_fs_builder.h b/src/mesa/drivers/dri/i965/brw_fs_builder.h
index dd3c383..bb94c3d 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_builder.h
+++ b/src/mesa/drivers/dri/i965/brw_fs_builder.h
@@ -375,14 +375,8 @@ namespace brw {
       {
          assert(mod == BRW_CONDITIONAL_GE || mod == BRW_CONDITIONAL_L);
 
-         if (shader->devinfo->gen >= 6) {
-            set_condmod(mod, SEL(dst, fix_unsigned_negate(src0),
-                                 fix_unsigned_negate(src1)));
-         } else {
-            CMP(null_reg_d(), src0, src1, mod);
-            set_predicate(BRW_PREDICATE_NORMAL,
-                          SEL(dst, src0, src1));
-         }
+         set_condmod(mod, SEL(dst, fix_unsigned_negate(src0),
+                              fix_unsigned_negate(src1)));
       }
 
       /**
diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
index 1fc21e4..3014dbb 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
@@ -950,28 +950,16 @@ fs_visitor::nir_emit_alu(const fs_builder &bld, nir_alu_instr *instr)
    case nir_op_fmin:
    case nir_op_imin:
    case nir_op_umin:
-      if (devinfo->gen >= 6) {
-         inst = bld.emit(BRW_OPCODE_SEL, result, op[0], op[1]);
-         inst->conditional_mod = BRW_CONDITIONAL_L;
-      } else {
-         bld.CMP(bld.null_reg_d(), op[0], op[1], BRW_CONDITIONAL_L);
-         inst = bld.SEL(result, op[0], op[1]);
-         inst->predicate = BRW_PREDICATE_NORMAL;
-      }
+      inst = bld.emit(BRW_OPCODE_SEL, result, op[0], op[1]);
+      inst->conditional_mod = BRW_CONDITIONAL_L;
       inst->saturate = instr->dest.saturate;
       break;
 
    case nir_op_fmax:
    case nir_op_imax:
    case nir_op_umax:
-      if (devinfo->gen >= 6) {
-         inst = bld.emit(BRW_OPCODE_SEL, result, op[0], op[1]);
-         inst->conditional_mod = BRW_CONDITIONAL_GE;
-      } else {
-         bld.CMP(bld.null_reg_d(), op[0], op[1], BRW_CONDITIONAL_GE);
-         inst = bld.SEL(result, op[0], op[1]);
-         inst->predicate = BRW_PREDICATE_NORMAL;
-      }
+      inst = bld.emit(BRW_OPCODE_SEL, result, op[0], op[1]);
+      inst->conditional_mod = BRW_CONDITIONAL_GE;
       inst->saturate = instr->dest.saturate;
       break;
 
diff --git a/src/mesa/drivers/dri/i965/brw_vec4.cpp b/src/mesa/drivers/dri/i965/brw_vec4.cpp
index 0d8c104..d4acd7c 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4.cpp
@@ -26,6 +26,7 @@
 #include "brw_cfg.h"
 #include "brw_vs.h"
 #include "brw_nir.h"
+#include "brw_vec4_builder.h"
 #include "brw_vec4_live_variables.h"
 #include "brw_dead_control_flow.h"
 #include "program/prog_parameter.h"
@@ -1632,6 +1633,36 @@ vec4_vs_visitor::setup_payload(void)
    this->first_non_payload_grf = reg;
 }
 
+bool
+vec4_visitor::lower_minmax()
+{
+   assert(devinfo->gen < 6);
+
+   bool progress = false;
+
+   foreach_block_and_inst_safe(block, vec4_instruction, inst, cfg) {
+      const vec4_builder ibld(this, block, inst);
+
+      if (inst->opcode == BRW_OPCODE_SEL &&
+          inst->predicate == BRW_PREDICATE_NONE) {
+         assert(inst->conditional_mod == BRW_CONDITIONAL_GE ||
+                inst->conditional_mod == BRW_CONDITIONAL_L);
+
+         ibld.CMP(ibld.null_reg_d(), inst->src[0], inst->src[1],
+                  inst->conditional_mod);
+         inst->predicate = BRW_PREDICATE_NORMAL;
+         inst->conditional_mod = BRW_CONDITIONAL_NONE;
+
+         progress = true;
+      }
+   }
+
+   if (progress)
+      invalidate_live_intervals();
+
+   return progress;
+}
+
 src_reg
 vec4_visitor::get_timestamp()
 {
@@ -1904,6 +1935,13 @@ vec4_visitor::run()
       OPT(dead_code_eliminate);
    }
 
+   if (devinfo->gen <= 5 && OPT(lower_minmax)) {
+      OPT(opt_cmod_propagation);
+      OPT(opt_cse);
+      OPT(opt_copy_propagation);
+      OPT(dead_code_eliminate);
+   }
+
    if (failed)
       return false;
 
diff --git a/src/mesa/drivers/dri/i965/brw_vec4.h b/src/mesa/drivers/dri/i965/brw_vec4.h
index 14a5f0e..633f13c 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4.h
+++ b/src/mesa/drivers/dri/i965/brw_vec4.h
@@ -307,6 +307,8 @@ public:
 
    void resolve_ud_negate(src_reg *reg);
 
+   bool lower_minmax();
+
    src_reg get_timestamp();
 
    void dump_instruction(backend_instruction *inst);
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_builder.h b/src/mesa/drivers/dri/i965/brw_vec4_builder.h
index 5d4b452..a0b390b 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_builder.h
+++ b/src/mesa/drivers/dri/i965/brw_vec4_builder.h
@@ -303,14 +303,8 @@ namespace brw {
       emit_minmax(const dst_reg &dst, const src_reg &src0,
                   const src_reg &src1, brw_conditional_mod mod) const
       {
-         if (shader->devinfo->gen >= 6) {
-            set_condmod(mod, SEL(dst, fix_unsigned_negate(src0),
-                                 fix_unsigned_negate(src1)));
-         } else {
-            CMP(null_reg_d(), src0, src1, mod);
-            set_predicate(BRW_PREDICATE_NORMAL,
-                          SEL(dst, src0, src1));
-         }
+         set_condmod(mod, SEL(dst, fix_unsigned_negate(src0),
+                              fix_unsigned_negate(src1)));
       }
 
       /**
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
index 96dbc37..9f62f61 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
@@ -678,18 +678,8 @@ vec4_instruction *
 vec4_visitor::emit_minmax(enum brw_conditional_mod conditionalmod, dst_reg dst,
                           src_reg src0, src_reg src1)
 {
-   vec4_instruction *inst;
-
-   if (devinfo->gen >= 6) {
-      inst = emit(BRW_OPCODE_SEL, dst, src0, src1);
-      inst->conditional_mod = conditionalmod;
-   } else {
-      emit(CMP(dst, src0, src1, conditionalmod));
-
-      inst = emit(BRW_OPCODE_SEL, dst, src0, src1);
-      inst->predicate = BRW_PREDICATE_NORMAL;
-   }
-
+   vec4_instruction *inst = emit(BRW_OPCODE_SEL, dst, src0, src1);
+   inst->conditional_mod = conditionalmod;
    return inst;
 }
 
-- 
2.4.10



More information about the mesa-dev mailing list