glsl: introduce ir_binop_all_equal and ir_binop_any_equal, allow vector cmps
authorLuca Barbieri <luca@luca-barbieri.com>
Tue, 7 Sep 2010 23:31:39 +0000 (01:31 +0200)
committerIan Romanick <ian.d.romanick@intel.com>
Tue, 14 Sep 2010 00:53:04 +0000 (17:53 -0700)
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@intel.com>
src/glsl/ast_to_hir.cpp
src/glsl/ir.cpp
src/glsl/ir.h
src/glsl/ir_algebraic.cpp
src/glsl/ir_constant_expression.cpp
src/glsl/ir_mat_op_to_vec.cpp
src/glsl/ir_validate.cpp
src/mesa/program/ir_to_mesa.cpp

index 3de6caa..31bb40d 100644 (file)
@@ -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,
index b094543..86dc490 100644 (file)
@@ -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];
 }
 
index 80a647e..70c6faa 100644 (file)
@@ -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,
    /*@}*/
 
    /**
index ff81563..2ed66db 100644 (file)
@@ -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.
index ca12392..ec0e26d 100644 (file)
@@ -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;
 
index da6de94..c32ca88 100644 (file)
@@ -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:
index 445169f..1c50957 100644 (file)
@@ -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);
index 6d67da4..2edf01b 100644 (file)
@@ -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()) {