[Mesa-dev] [PATCH 2/2] i965: Emit smarter code for b2i of a comparison

Ian Romanick idr at freedesktop.org
Tue Jun 10 19:13:08 PDT 2014


From: Ian Romanick <ian.d.romanick at intel.com>

Previously we would emit the comparison, emit an AND to mask off extra
bits from the comparison result, then convert the result to float.  Now,
do the comparison, then use a cleverly constructed SEL to pick either
0.0f or 1.0f.

No piglit regressions on Ivybridge.

NOTE: I have not yet tested actual application performance.  I'll do
that tomorrow.

total instructions in shared programs: 1642311 -> 1639449 (-0.17%)
instructions in affected programs:     136533 -> 133671 (-2.10%)
GAINED:                                0
LOST:                                  0

Programs that are affected appear to save between 1 and 5 instuctions
(just by skimming the output from shader-db report.py.

Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
---
 src/mesa/drivers/dri/i965/brw_vec4.h           |  1 +
 src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp | 47 ++++++++++++++++++++++++++
 2 files changed, 48 insertions(+)

diff --git a/src/mesa/drivers/dri/i965/brw_vec4.h b/src/mesa/drivers/dri/i965/brw_vec4.h
index c2bbd68..27e1e39 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4.h
+++ b/src/mesa/drivers/dri/i965/brw_vec4.h
@@ -587,6 +587,7 @@ public:
 
    bool try_emit_sat(ir_expression *ir);
    bool try_emit_mad(ir_expression *ir);
+   bool try_emit_b2f_of_compare(ir_expression *ir);
    void resolve_ud_negate(src_reg *reg);
 
    src_reg get_timestamp();
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
index 249072c..902f02d 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
@@ -1126,6 +1126,48 @@ vec4_visitor::try_emit_mad(ir_expression *ir)
    return true;
 }
 
+bool
+vec4_visitor::try_emit_b2f_of_compare(ir_expression *ir)
+{
+   ir_expression *const cmp = ir->operands[0]->as_expression();
+
+   if (cmp == NULL)
+      return false;
+
+   switch (cmp->operation) {
+   case ir_binop_less:
+   case ir_binop_greater:
+   case ir_binop_lequal:
+   case ir_binop_gequal:
+   case ir_binop_equal:
+   case ir_binop_nequal:
+      break;
+
+   default:
+      return false;
+   }
+
+   cmp->operands[0]->accept(this);
+   const src_reg cmp_src0 = this->result;
+
+   cmp->operands[1]->accept(this);
+   const src_reg cmp_src1 = this->result;
+
+   this->result = src_reg(this, ir->type);
+
+   emit(CMP(dst_reg(this->result), cmp_src0, cmp_src1,
+            brw_conditional_for_comparison(cmp->operation)));
+
+   /* If the comparison is false, this->result will just happen to be zero.
+    */
+   vec4_instruction *const inst = emit(BRW_OPCODE_SEL, dst_reg(this->result),
+                                       fix_3src_operand(src_reg(1.0f)),
+                                       this->result);
+   inst->predicate = BRW_PREDICATE_NORMAL;
+
+   return true;
+}
+
 void
 vec4_visitor::emit_bool_comparison(unsigned int op,
 				 dst_reg dst, src_reg src0, src_reg src1)
@@ -1202,6 +1244,11 @@ vec4_visitor::visit(ir_expression *ir)
 	 return;
    }
 
+   if (ir->operation == ir_unop_b2f) {
+      if (try_emit_b2f_of_compare(ir))
+	 return;
+   }
+
    for (operand = 0; operand < ir->get_num_operands(); operand++) {
       this->result.file = BAD_FILE;
       ir->operands[operand]->accept(this);
-- 
1.8.1.4



More information about the mesa-dev mailing list