summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Barbieri <luca@luca-barbieri.com>2010-09-08 01:31:39 +0200
committerIan Romanick <ian.d.romanick@intel.com>2010-09-13 17:53:04 -0700
commit4dfb89904c0a3d2166e9a3fc0253a254680e91bc (patch)
treecbdcd0ef976c8cb33d604a29caf10bec1571af3b
parent2cdbced10d98214616bcc5f960b21185c433d23b (diff)
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@intel.com>
-rw-r--r--src/glsl/ast_to_hir.cpp4
-rw-r--r--src/glsl/ir.cpp5
-rw-r--r--src/glsl/ir.h6
-rw-r--r--src/glsl/ir_algebraic.cpp2
-rw-r--r--src/glsl/ir_constant_expression.cpp38
-rw-r--r--src/glsl/ir_mat_op_to_vec.cpp8
-rw-r--r--src/glsl/ir_validate.cpp26
-rw-r--r--src/mesa/program/ir_to_mesa.cpp8
8 files changed, 74 insertions, 23 deletions
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 3de6caac70..31bb40dd13 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 b0945431ad..86dc490154 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 80a647e0dc..70c6faaf15 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 ff81563f19..2ed66db476 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 ca12392a74..ec0e26de18 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 da6de9492b..c32ca88b0f 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 445169f520..1c50957d13 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 6d67da495d..2edf01bb8f 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()) {