i965/fs: Optimize emit_bool_to_cond_code for logical exprs.
authorMatt Turner <mattst88@gmail.com>
Sat, 9 Aug 2014 04:04:26 +0000 (21:04 -0700)
committerMatt Turner <mattst88@gmail.com>
Tue, 19 Aug 2014 01:35:53 +0000 (18:35 -0700)
AND, OR, and XOR can generate the conditional code directly.

total instructions in shared programs: 4293335 -> 4292303 (-0.02%)
instructions in affected programs:     121408 -> 120376 (-0.85%)

Reviewed-by: Anuj Phogat <anuj.phogat@gmail.com>
src/mesa/drivers/dri/i965/brw_fs_visitor.cpp

index 1245c8a7667e4ebc52c8b855625280d34052e59d..fa2c2269356c9487910c2da3fb6ebe9a54c1bc0b 100644 (file)
@@ -2228,72 +2228,105 @@ fs_visitor::emit_bool_to_cond_code(ir_rvalue *ir)
 {
    ir_expression *expr = ir->as_expression();
 
-   if (expr &&
-       expr->operation != ir_binop_logic_and &&
-       expr->operation != ir_binop_logic_or &&
-       expr->operation != ir_binop_logic_xor) {
-      fs_reg op[2];
-      fs_inst *inst;
+   if (!expr) {
+      ir->accept(this);
 
-      assert(expr->get_num_operands() <= 2);
-      for (unsigned int i = 0; i < expr->get_num_operands(); i++) {
-        assert(expr->operands[i]->type->is_scalar());
+      fs_inst *inst = emit(AND(reg_null_d, this->result, fs_reg(1)));
+      inst->conditional_mod = BRW_CONDITIONAL_NZ;
+      return;
+   }
 
-        expr->operands[i]->accept(this);
-        op[i] = this->result;
+   fs_reg op[2];
+   fs_inst *inst;
 
-        resolve_ud_negate(&op[i]);
-      }
+   assert(expr->get_num_operands() <= 2);
+   for (unsigned int i = 0; i < expr->get_num_operands(); i++) {
+      assert(expr->operands[i]->type->is_scalar());
 
-      switch (expr->operation) {
-      case ir_unop_logic_not:
-        inst = emit(AND(reg_null_d, op[0], fs_reg(1)));
-        inst->conditional_mod = BRW_CONDITIONAL_Z;
-        break;
+      expr->operands[i]->accept(this);
+      op[i] = this->result;
 
-      case ir_unop_f2b:
-        if (brw->gen >= 6) {
-           emit(CMP(reg_null_d, op[0], fs_reg(0.0f), BRW_CONDITIONAL_NZ));
-        } else {
-           inst = emit(MOV(reg_null_f, op[0]));
-            inst->conditional_mod = BRW_CONDITIONAL_NZ;
-        }
-        break;
+      resolve_ud_negate(&op[i]);
+   }
 
-      case ir_unop_i2b:
-        if (brw->gen >= 6) {
-           emit(CMP(reg_null_d, op[0], fs_reg(0), BRW_CONDITIONAL_NZ));
-        } else {
-           inst = emit(MOV(reg_null_d, op[0]));
-            inst->conditional_mod = BRW_CONDITIONAL_NZ;
-        }
-        break;
+   switch (expr->operation) {
+   case ir_unop_logic_not:
+      inst = emit(AND(reg_null_d, op[0], fs_reg(1)));
+      inst->conditional_mod = BRW_CONDITIONAL_Z;
+      break;
 
-      case ir_binop_greater:
-      case ir_binop_gequal:
-      case ir_binop_less:
-      case ir_binop_lequal:
-      case ir_binop_equal:
-      case ir_binop_all_equal:
-      case ir_binop_nequal:
-      case ir_binop_any_nequal:
-        resolve_bool_comparison(expr->operands[0], &op[0]);
-        resolve_bool_comparison(expr->operands[1], &op[1]);
+   case ir_binop_logic_xor:
+      if (ctx->Const.UniformBooleanTrue == 1) {
+         fs_reg dst = fs_reg(this, glsl_type::uint_type);
+         emit(XOR(dst, op[0], op[1]));
+         inst = emit(AND(reg_null_d, dst, fs_reg(1)));
+         inst->conditional_mod = BRW_CONDITIONAL_NZ;
+      } else {
+         inst = emit(XOR(reg_null_d, op[0], op[1]));
+         inst->conditional_mod = BRW_CONDITIONAL_NZ;
+      }
+      break;
 
-        emit(CMP(reg_null_d, op[0], op[1],
-                  brw_conditional_for_comparison(expr->operation)));
-        break;
+   case ir_binop_logic_or:
+      if (ctx->Const.UniformBooleanTrue == 1) {
+         fs_reg dst = fs_reg(this, glsl_type::uint_type);
+         emit(OR(dst, op[0], op[1]));
+         inst = emit(AND(reg_null_d, dst, fs_reg(1)));
+         inst->conditional_mod = BRW_CONDITIONAL_NZ;
+      } else {
+         inst = emit(OR(reg_null_d, op[0], op[1]));
+         inst->conditional_mod = BRW_CONDITIONAL_NZ;
+      }
+      break;
 
-      default:
-        unreachable("not reached");
+   case ir_binop_logic_and:
+      if (ctx->Const.UniformBooleanTrue == 1) {
+         fs_reg dst = fs_reg(this, glsl_type::uint_type);
+         emit(AND(dst, op[0], op[1]));
+         inst = emit(AND(reg_null_d, dst, fs_reg(1)));
+         inst->conditional_mod = BRW_CONDITIONAL_NZ;
+      } else {
+         inst = emit(AND(reg_null_d, op[0], op[1]));
+         inst->conditional_mod = BRW_CONDITIONAL_NZ;
       }
-      return;
-   }
+      break;
 
-   ir->accept(this);
+   case ir_unop_f2b:
+      if (brw->gen >= 6) {
+         emit(CMP(reg_null_d, op[0], fs_reg(0.0f), BRW_CONDITIONAL_NZ));
+      } else {
+         inst = emit(MOV(reg_null_f, op[0]));
+         inst->conditional_mod = BRW_CONDITIONAL_NZ;
+      }
+      break;
 
-   fs_inst *inst = emit(AND(reg_null_d, this->result, fs_reg(1)));
-   inst->conditional_mod = BRW_CONDITIONAL_NZ;
+   case ir_unop_i2b:
+      if (brw->gen >= 6) {
+         emit(CMP(reg_null_d, op[0], fs_reg(0), BRW_CONDITIONAL_NZ));
+      } else {
+         inst = emit(MOV(reg_null_d, op[0]));
+         inst->conditional_mod = BRW_CONDITIONAL_NZ;
+      }
+      break;
+
+   case ir_binop_greater:
+   case ir_binop_gequal:
+   case ir_binop_less:
+   case ir_binop_lequal:
+   case ir_binop_equal:
+   case ir_binop_all_equal:
+   case ir_binop_nequal:
+   case ir_binop_any_nequal:
+      resolve_bool_comparison(expr->operands[0], &op[0]);
+      resolve_bool_comparison(expr->operands[1], &op[1]);
+
+      emit(CMP(reg_null_d, op[0], op[1],
+               brw_conditional_for_comparison(expr->operation)));
+      break;
+
+   default:
+      unreachable("not reached");
+   }
 }
 
 /**