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>
This commit is contained in:
Luca Barbieri
2010-09-08 01:31:39 +02:00
committed by Ian Romanick
parent 2cdbced10d
commit 4dfb89904c
8 changed files with 76 additions and 25 deletions

View 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,

View 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];
}

View 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,
/*@}*/
/**

View 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.

View 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;

View 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:

View 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.
*/
assert(ir->type == glsl_type::bool_type);
assert(ir->operands[0]->type == ir->operands[1]->type);
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.
/* 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->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_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);

View 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()) {