[Mesa-dev] [PATCH] i965/fs: Use the embedded compare in SEL on gen6+.

Eric Anholt eric at anholt.net
Fri May 27 19:52:13 PDT 2011


This avoids the extra CMP and the predication on SEL, so in addition
to one less instruction, it makes scheduling less constrained.

Improves glbenchmark Egypt performance 0.6% +/- 0.2% (n=3).  Reduces
FS instruction count across affected shaders in shader-db by 1.3%
without regressing any.
---
 src/mesa/drivers/dri/i965/brw_fs.cpp         |   12 ++++++---
 src/mesa/drivers/dri/i965/brw_fs_visitor.cpp |   34 ++++++++++++++++---------
 2 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index 36040c3..09033ae 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -1033,12 +1033,16 @@ fs_visitor::propagate_constants()
 		  scan_inst->src[i] = inst->src[0];
 		  progress = true;
 	       } else if (i == 0 && scan_inst->src[1].file != IMM) {
-		  /* Fit this constant in by swapping the operands and
-		   * flipping the predicate
-		   */
 		  scan_inst->src[0] = scan_inst->src[1];
 		  scan_inst->src[1] = inst->src[0];
-		  scan_inst->predicate_inverse = !scan_inst->predicate_inverse;
+
+		  /* If this was predicated, flipping operands means
+		   * we also need to flip the predicate.
+		   */
+		  if (scan_inst->conditional_mod == BRW_CONDITIONAL_NONE) {
+		     scan_inst->predicate_inverse =
+			!scan_inst->predicate_inverse;
+		  }
 		  progress = true;
 	       }
 	       break;
diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
index 6e81256..b485787 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
@@ -386,24 +386,34 @@ fs_visitor::visit(ir_expression *ir)
       break;
 
    case ir_binop_min:
-      /* Unalias the destination */
-      this->result = fs_reg(this, ir->type);
+      if (intel->gen >= 6) {
+	 inst = emit(BRW_OPCODE_SEL, this->result, op[0], op[1]);
+	 inst->conditional_mod = BRW_CONDITIONAL_L;
+      } else {
+	 /* Unalias the destination */
+	 this->result = fs_reg(this, ir->type);
 
-      inst = emit(BRW_OPCODE_CMP, this->result, op[0], op[1]);
-      inst->conditional_mod = BRW_CONDITIONAL_L;
+	 inst = emit(BRW_OPCODE_CMP, this->result, op[0], op[1]);
+	 inst->conditional_mod = BRW_CONDITIONAL_L;
 
-      inst = emit(BRW_OPCODE_SEL, this->result, op[0], op[1]);
-      inst->predicated = true;
+	 inst = emit(BRW_OPCODE_SEL, this->result, op[0], op[1]);
+	 inst->predicated = true;
+      }
       break;
    case ir_binop_max:
-      /* Unalias the destination */
-      this->result = fs_reg(this, ir->type);
+      if (intel->gen >= 6) {
+	 inst = emit(BRW_OPCODE_SEL, this->result, op[0], op[1]);
+	 inst->conditional_mod = BRW_CONDITIONAL_GE;
+      } else {
+	 /* Unalias the destination */
+	 this->result = fs_reg(this, ir->type);
 
-      inst = emit(BRW_OPCODE_CMP, this->result, op[0], op[1]);
-      inst->conditional_mod = BRW_CONDITIONAL_G;
+	 inst = emit(BRW_OPCODE_CMP, this->result, op[0], op[1]);
+	 inst->conditional_mod = BRW_CONDITIONAL_G;
 
-      inst = emit(BRW_OPCODE_SEL, this->result, op[0], op[1]);
-      inst->predicated = true;
+	 inst = emit(BRW_OPCODE_SEL, this->result, op[0], op[1]);
+	 inst->predicated = true;
+      }
       break;
 
    case ir_binop_pow:
-- 
1.7.5.1



More information about the mesa-dev mailing list