Mesa (master): glsl: introduce ir_binop_all_equal and ir_binop_any_equal, allow vector cmps

Ian Romanick idr at kemper.freedesktop.org
Tue Sep 14 01:00:17 UTC 2010


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

Author: Luca Barbieri <luca at luca-barbieri.com>
Date:   Wed Sep  8 01:31:39 2010 +0200

glsl: introduce ir_binop_all_equal and ir_binop_any_equal, allow vector cmps

Currently GLSL IR forbids any vector comparisons, and defines "ir_binop_equal"
and "ir_binop_nequal" to compare all elements and give a single bool.

This is highly unintuitive and prevents generation of optimal Mesa IR.

Hence, first rename "ir_binop_equal" to "ir_binop_all_equal" and
"ir_binop_nequal" to "ir_binop_any_nequal".

Second, readd "ir_binop_equal" and "ir_binop_nequal" with the same semantics
as less, lequal, etc.

Third, allow all comparisons to acts on vectors.

Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>

---

 src/glsl/ast_to_hir.cpp             |    4 +-
 src/glsl/ir.cpp                     |    5 ++++
 src/glsl/ir.h                       |    6 +++-
 src/glsl/ir_algebraic.cpp           |    2 +
 src/glsl/ir_constant_expression.cpp |   38 +++++++++++++++++++++++++++++++---
 src/glsl/ir_mat_op_to_vec.cpp       |    8 +++---
 src/glsl/ir_validate.cpp            |   26 ++++++++++++++---------
 src/mesa/program/ir_to_mesa.cpp     |    8 ++++++-
 8 files changed, 74 insertions(+), 23 deletions(-)

diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 3de6caa..31bb40d 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -636,8 +636,8 @@ ast_expression::hir(exec_list *instructions,
       ir_binop_greater,
       ir_binop_lequal,
       ir_binop_gequal,
-      ir_binop_equal,
-      ir_binop_nequal,
+      ir_binop_all_equal,
+      ir_binop_any_nequal,
       ir_binop_bit_and,
       ir_binop_bit_xor,
       ir_binop_bit_or,
diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp
index b094543..86dc490 100644
--- a/src/glsl/ir.cpp
+++ b/src/glsl/ir.cpp
@@ -210,6 +210,8 @@ ir_expression::get_num_operands(ir_expression_operation op)
       2, /* ir_binop_gequal */
       2, /* ir_binop_equal */
       2, /* ir_binop_nequal */
+      2, /* ir_binop_all_equal */
+      2, /* ir_binop_any_nequal */
 
       2, /* ir_binop_lshift */
       2, /* ir_binop_rshift */
@@ -275,6 +277,8 @@ static const char *const operator_strs[] = {
    ">=",
    "==",
    "!=",
+   "all_equal",
+   "any_nequal",
    "<<",
    ">>",
    "&",
@@ -293,6 +297,7 @@ static const char *const operator_strs[] = {
 const char *ir_expression::operator_string(ir_expression_operation op)
 {
    assert((unsigned int) op < Elements(operator_strs));
+   assert(Elements(operator_strs) == (ir_binop_pow + 1));
    return operator_strs[op];
 }
 
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index 80a647e..70c6faa 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -675,16 +675,18 @@ enum ir_expression_operation {
    ir_binop_greater,
    ir_binop_lequal,
    ir_binop_gequal,
+   ir_binop_equal,
+   ir_binop_nequal,
    /**
     * Returns single boolean for whether all components of operands[0]
     * equal the components of operands[1].
     */
-   ir_binop_equal,
+   ir_binop_all_equal,
    /**
     * Returns single boolean for whether any component of operands[0]
     * is not equal to the corresponding component of operands[1].
     */
-   ir_binop_nequal,
+   ir_binop_any_nequal,
    /*@}*/
 
    /**
diff --git a/src/glsl/ir_algebraic.cpp b/src/glsl/ir_algebraic.cpp
index ff81563..2ed66db 100644
--- a/src/glsl/ir_algebraic.cpp
+++ b/src/glsl/ir_algebraic.cpp
@@ -270,6 +270,8 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
       case ir_binop_gequal:  new_op = ir_binop_less;    break;
       case ir_binop_equal:   new_op = ir_binop_nequal;  break;
       case ir_binop_nequal:  new_op = ir_binop_equal;   break;
+      case ir_binop_all_equal:   new_op = ir_binop_any_nequal;  break;
+      case ir_binop_any_nequal:  new_op = ir_binop_all_equal;   break;
 
       default:
 	 /* The default case handler is here to silence a warning from GCC.
diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp
index ca12392..ec0e26d 100644
--- a/src/glsl/ir_constant_expression.cpp
+++ b/src/glsl/ir_constant_expression.cpp
@@ -89,9 +89,9 @@ ir_expression::constant_expression_value()
    if (op[0]->type->is_array()) {
       assert(op[1] != NULL && op[1]->type->is_array());
       switch (this->operation) {
-      case ir_binop_equal:
+      case ir_binop_all_equal:
 	 return new(ctx) ir_constant(op[0]->has_value(op[1]));
-      case ir_binop_nequal:
+      case ir_binop_any_nequal:
 	 return new(ctx) ir_constant(!op[0]->has_value(op[1]));
       default:
 	 break;
@@ -622,11 +622,41 @@ ir_expression::constant_expression_value()
 	 assert(0);
       }
       break;
-
    case ir_binop_equal:
-      data.b[0] = op[0]->has_value(op[1]);
+      switch (op[0]->type->base_type) {
+      case GLSL_TYPE_UINT:
+         data.b[0] = op[0]->value.u[0] == op[1]->value.u[0];
+         break;
+      case GLSL_TYPE_INT:
+         data.b[0] = op[0]->value.i[0] == op[1]->value.i[0];
+         break;
+      case GLSL_TYPE_FLOAT:
+         data.b[0] = op[0]->value.f[0] == op[1]->value.f[0];
+         break;
+      default:
+         assert(0);
+      }
       break;
    case ir_binop_nequal:
+      switch (op[0]->type->base_type) {
+      case GLSL_TYPE_UINT:
+         data.b[0] = op[0]->value.u[0] != op[1]->value.u[0];
+         break;
+      case GLSL_TYPE_INT:
+         data.b[0] = op[0]->value.i[0] != op[1]->value.i[0];
+         break;
+      case GLSL_TYPE_FLOAT:
+         data.b[0] = op[0]->value.f[0] != op[1]->value.f[0];
+         break;
+      default:
+         assert(0);
+      }
+      break;
+
+   case ir_binop_all_equal:
+      data.b[0] = op[0]->has_value(op[1]);
+      break;
+   case ir_binop_any_nequal:
       data.b[0] = !op[0]->has_value(op[1]);
       break;
 
diff --git a/src/glsl/ir_mat_op_to_vec.cpp b/src/glsl/ir_mat_op_to_vec.cpp
index da6de94..c32ca88 100644
--- a/src/glsl/ir_mat_op_to_vec.cpp
+++ b/src/glsl/ir_mat_op_to_vec.cpp
@@ -307,7 +307,7 @@ ir_mat_op_to_vec_visitor::do_equal_mat_mat(ir_variable *result_var,
       ir_dereference *const op1 = get_column(b_var, i);
 
       ir_expression *const cmp =
-	 new(this->mem_ctx) ir_expression(ir_binop_nequal,
+	 new(this->mem_ctx) ir_expression(ir_binop_any_nequal,
 					  glsl_type::bool_type, op0, op1);
 
       ir_rvalue *const swiz =
@@ -473,10 +473,10 @@ ir_mat_op_to_vec_visitor::visit_leave(ir_assignment *orig_assign)
       }
       break;
 
-   case ir_binop_equal:
-   case ir_binop_nequal:
+   case ir_binop_all_equal:
+   case ir_binop_any_nequal:
       do_equal_mat_mat(result_var, op_var[1], op_var[0],
-		       (orig_expr->operation == ir_binop_equal));
+		       (orig_expr->operation == ir_binop_all_equal));
       break;
 
    default:
diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp
index 445169f..1c50957 100644
--- a/src/glsl/ir_validate.cpp
+++ b/src/glsl/ir_validate.cpp
@@ -293,24 +293,30 @@ ir_validate::visit_leave(ir_expression *ir)
 	 assert(ir->operands[0]->type == ir->type);
       }
       break;
+
    case ir_binop_less:
    case ir_binop_greater:
    case ir_binop_lequal:
    case ir_binop_gequal:
-      /* GLSL < > <= >= operators take scalar floats/ints, but in the
-       * IR we may want to do them for vectors instead to support the
-       * lessEqual() and friends builtins.
+   case ir_binop_equal:
+   case ir_binop_nequal:
+      /* The semantics of the IR operators differ from the GLSL <, >, <=, >=,
+       * ==, and != operators.  The IR operators perform a component-wise
+       * comparison on scalar or vector types and return a boolean scalar or
+       * vector type of the same size.
        */
-      assert(ir->type == glsl_type::bool_type);
+      assert(ir->type->base_type == GLSL_TYPE_BOOL);
       assert(ir->operands[0]->type == ir->operands[1]->type);
+      assert(ir->operands[0]->type->is_vector()
+	     || ir->operands[0]->type->is_scalar());
+      assert(ir->operands[0]->type->vector_elements
+	     == ir->type->vector_elements);
       break;
 
-   case ir_binop_equal:
-   case ir_binop_nequal:
-      /* GLSL == and != operate on vectors and return a bool, and the
-       * IR matches that.  We may want to switch up the IR to work on
-       * vectors and return a bvec and make the operators break down
-       * to ANDing/ORing the results of the vector comparison.
+   case ir_binop_all_equal:
+   case ir_binop_any_nequal:
+      /* GLSL == and != operate on scalars, vectors, matrices and arrays, and
+       * return a scalar boolean.  The IR matches that.
        */
       assert(ir->type == glsl_type::bool_type);
       assert(ir->operands[0]->type == ir->operands[1]->type);
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index 6d67da4..2edf01b 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -1193,6 +1193,12 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
       ir_to_mesa_emit_op2(ir, OPCODE_SGE, result_dst, op[0], op[1]);
       break;
    case ir_binop_equal:
+      ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst, op[0], op[1]);
+      break;
+   case ir_binop_nequal:
+      ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]);
+      break;
+   case ir_binop_all_equal:
       /* "==" operator producing a scalar boolean. */
       if (ir->operands[0]->type->is_vector() ||
 	  ir->operands[1]->type->is_vector()) {
@@ -1206,7 +1212,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
 	 ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst, op[0], op[1]);
       }
       break;
-   case ir_binop_nequal:
+   case ir_binop_any_nequal:
       /* "!=" operator producing a scalar boolean. */
       if (ir->operands[0]->type->is_vector() ||
 	  ir->operands[1]->type->is_vector()) {




More information about the mesa-commit mailing list