Mesa (master): i965: Add peepholing of conditional mod generation from expressions.

Eric Anholt anholt at kemper.freedesktop.org
Thu Oct 14 19:03:53 UTC 2010


Module: Mesa
Branch: master
Commit: 5dd07b442e02696bf0ec5d4e3b4be1674519664a
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=5dd07b442e02696bf0ec5d4e3b4be1674519664a

Author: Eric Anholt <eric at anholt.net>
Date:   Thu Oct 14 11:27:17 2010 -0700

i965: Add peepholing of conditional mod generation from expressions.

This cuts usually 2 out of 3 instructions for flag reg generation (if
statements, conditional assignment) by producing the conditional mod
in the expression representing the boolean value.

Fixes glsl-fs-vec4-indexing-temp-dst-in-nested-loop-combined (register
allocation no longer fails for the conditional generation
proliferation)

---

 src/mesa/drivers/dri/i965/brw_fs.cpp |   88 ++++++++++++++++++++++++++++++++++
 1 files changed, 88 insertions(+), 0 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index c92bb54..d5ebccb 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -717,6 +717,9 @@ fs_visitor::visit(ir_expression *ir)
 
    switch (ir->operation) {
    case ir_unop_logic_not:
+      /* Note that BRW_OPCODE_NOT is not appropriate here, since it is
+       * ones complement of the whole register, not just bit 0.
+       */
       emit(fs_inst(BRW_OPCODE_ADD, this->result, op[0], fs_reg(-1)));
       break;
    case ir_unop_neg:
@@ -1342,6 +1345,91 @@ fs_visitor::visit(ir_constant *ir)
 void
 fs_visitor::emit_bool_to_cond_code(ir_rvalue *ir)
 {
+   ir_expression *expr = ir->as_expression();
+
+   if (expr) {
+      fs_reg op[2];
+      fs_inst *inst;
+
+      for (unsigned int i = 0; i < expr->get_num_operands(); i++) {
+	 assert(expr->operands[i]->type->is_scalar());
+
+	 expr->operands[i]->accept(this);
+	 op[i] = this->result;
+      }
+
+      switch (expr->operation) {
+      case ir_unop_logic_not:
+	 inst = emit(fs_inst(BRW_OPCODE_ADD, reg_null, op[0], fs_reg(-1)));
+	 inst->conditional_mod = BRW_CONDITIONAL_NZ;
+	 break;
+
+      case ir_binop_logic_xor:
+	 inst = emit(fs_inst(BRW_OPCODE_XOR, reg_null, op[0], op[1]));
+	 inst->conditional_mod = BRW_CONDITIONAL_NZ;
+	 break;
+
+      case ir_binop_logic_or:
+	 inst = emit(fs_inst(BRW_OPCODE_OR, reg_null, op[0], op[1]));
+	 inst->conditional_mod = BRW_CONDITIONAL_NZ;
+	 break;
+
+      case ir_binop_logic_and:
+	 inst = emit(fs_inst(BRW_OPCODE_AND, reg_null, op[0], op[1]));
+	 inst->conditional_mod = BRW_CONDITIONAL_NZ;
+	 break;
+
+      case ir_unop_f2b:
+	 if (intel->gen >= 6) {
+	    inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null, op[0], fs_reg(0.0f)));
+	 } else {
+	    inst = emit(fs_inst(BRW_OPCODE_MOV, reg_null, op[0]));
+	 }
+	 inst->conditional_mod = BRW_CONDITIONAL_NZ;
+	 break;
+
+      case ir_unop_i2b:
+	 if (intel->gen >= 6) {
+	    inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null, op[0], fs_reg(0)));
+	 } else {
+	    inst = emit(fs_inst(BRW_OPCODE_MOV, reg_null, op[0]));
+	 }
+	 inst->conditional_mod = BRW_CONDITIONAL_NZ;
+	 break;
+
+      case ir_binop_greater:
+	 inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null, op[0], op[1]));
+	 inst->conditional_mod = BRW_CONDITIONAL_G;
+	 break;
+      case ir_binop_gequal:
+	 inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null, op[0], op[1]));
+	 inst->conditional_mod = BRW_CONDITIONAL_GE;
+	 break;
+      case ir_binop_less:
+	 inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null, op[0], op[1]));
+	 inst->conditional_mod = BRW_CONDITIONAL_L;
+	 break;
+      case ir_binop_lequal:
+	 inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null, op[0], op[1]));
+	 inst->conditional_mod = BRW_CONDITIONAL_LE;
+	 break;
+      case ir_binop_equal:
+      case ir_binop_all_equal:
+	 inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null, op[0], op[1]));
+	 inst->conditional_mod = BRW_CONDITIONAL_Z;
+	 break;
+      case ir_binop_nequal:
+      case ir_binop_any_nequal:
+	 inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null, op[0], op[1]));
+	 inst->conditional_mod = BRW_CONDITIONAL_NZ;
+	 break;
+      default:
+	 assert(!"not reached");
+	 this->fail = true;
+	 break;
+      }
+      return;
+   }
 
    ir->accept(this);
 




More information about the mesa-commit mailing list