#include "ir_optimization.h"
#include "ir_builder.h"
#include "compiler/glsl_types.h"
+#include "main/mtypes.h"
using namespace ir_builder;
static inline bool
is_less_than_one(ir_constant *ir)
{
- assert(ir->type->base_type == GLSL_TYPE_FLOAT);
+ assert(ir->type->is_float());
if (!is_valid_vec_const(ir))
return false;
static inline bool
is_greater_than_zero(ir_constant *ir)
{
- assert(ir->type->base_type == GLSL_TYPE_FLOAT);
+ assert(ir->type->is_float());
if (!is_valid_vec_const(ir))
return false;
/**
* Reassociates a constant down a tree of adds or multiplies.
*
- * Consider (2 * (a * (b * 0.5))). We want to send up with a * b.
+ * Consider (2 * (a * (b * 0.5))). We want to end up with a * b.
*/
bool
ir_algebraic_visitor::reassociate_constant(ir_expression *ir1, int const_index,
ir2->operands[1]->type->is_matrix())
return false;
+ void *mem_ctx = ralloc_parent(ir2);
+
ir_constant *ir2_const[2];
- ir2_const[0] = ir2->operands[0]->constant_expression_value();
- ir2_const[1] = ir2->operands[1]->constant_expression_value();
+ ir2_const[0] = ir2->operands[0]->constant_expression_value(mem_ctx);
+ ir2_const[1] = ir2->operands[1]->constant_expression_value(mem_ctx);
if (ir2_const[0] && ir2_const[1])
return false;
{
ir_constant *op_const[4] = {NULL, NULL, NULL, NULL};
ir_expression *op_expr[4] = {NULL, NULL, NULL, NULL};
- unsigned int i;
if (ir->operation == ir_binop_mul &&
ir->operands[0]->type->is_matrix() &&
}
}
- assert(ir->get_num_operands() <= 4);
- for (i = 0; i < ir->get_num_operands(); i++) {
+ assert(ir->num_operands <= 4);
+ for (unsigned i = 0; i < ir->num_operands; i++) {
if (ir->operands[i]->type->is_matrix())
return ir;
- op_const[i] = ir->operands[i]->constant_expression_value();
+ op_const[i] =
+ ir->operands[i]->constant_expression_value(ralloc_parent(ir));
op_expr[i] = ir->operands[i]->as_expression();
}
switch (op_expr[0]->operation) {
case ir_binop_less: new_op = ir_binop_gequal; break;
- case ir_binop_greater: new_op = ir_binop_lequal; break;
- case ir_binop_lequal: new_op = ir_binop_greater; break;
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;
}
break;
+ /* This macro CANNOT use the do { } while(true) mechanism because
+ * then the breaks apply to the loop instead of the switch!
+ */
+#define HANDLE_PACK_UNPACK_INVERSE(inverse_operation) \
+ { \
+ ir_expression *const op = ir->operands[0]->as_expression(); \
+ if (op == NULL) \
+ break; \
+ if (op->operation == (inverse_operation)) \
+ return op->operands[0]; \
+ break; \
+ }
+
+ case ir_unop_unpack_uint_2x32:
+ HANDLE_PACK_UNPACK_INVERSE(ir_unop_pack_uint_2x32);
+ case ir_unop_pack_uint_2x32:
+ HANDLE_PACK_UNPACK_INVERSE(ir_unop_unpack_uint_2x32);
+ case ir_unop_unpack_int_2x32:
+ HANDLE_PACK_UNPACK_INVERSE(ir_unop_pack_int_2x32);
+ case ir_unop_pack_int_2x32:
+ HANDLE_PACK_UNPACK_INVERSE(ir_unop_unpack_int_2x32);
+ case ir_unop_unpack_double_2x32:
+ HANDLE_PACK_UNPACK_INVERSE(ir_unop_pack_double_2x32);
+ case ir_unop_pack_double_2x32:
+ HANDLE_PACK_UNPACK_INVERSE(ir_unop_unpack_double_2x32);
+
+#undef HANDLE_PACK_UNPACK_INVERSE
+
case ir_binop_add:
if (is_vec_zero(op_const[0]))
return ir->operands[1];
if (is_vec_zero(op_const[1]))
return ir->operands[0];
+ /* Replace (x + (-x)) with constant 0 */
+ for (int i = 0; i < 2; i++) {
+ if (op_expr[i]) {
+ if (op_expr[i]->operation == ir_unop_neg) {
+ ir_rvalue *other = ir->operands[(i + 1) % 2];
+ if (other && op_expr[i]->operands[0]->equals(other)) {
+ return ir_constant::zero(ir, ir->type);
+ }
+ }
+ }
+ }
+
/* Reassociate addition of constants so that we can do constant
* folding.
*/
ir_rvalue *y_operand = inner_add->operands[1 - neg_pos];
ir_rvalue *a_operand = mul->operands[1 - inner_add_pos];
- if (x_operand->type != y_operand->type ||
+ if (!x_operand->type->is_float_16_32_64() ||
+ x_operand->type != y_operand->type ||
x_operand->type != a_operand->type)
continue;
case ir_binop_div:
if (is_vec_one(op_const[0]) && (
- ir->type->base_type == GLSL_TYPE_FLOAT ||
- ir->type->base_type == GLSL_TYPE_DOUBLE)) {
+ ir->type->is_float() || ir->type->is_double())) {
return new(mem_ctx) ir_expression(ir_unop_rcp,
ir->operands[1]->type,
ir->operands[1],
break;
case ir_binop_less:
- case ir_binop_lequal:
- case ir_binop_greater:
case ir_binop_gequal:
case ir_binop_equal:
case ir_binop_nequal:
if (!is_vec_zero(zero))
continue;
+ /* We are allowed to add scalars with a vector or matrix. In that
+ * case lets just exit early.
+ */
+ if (add->operands[0]->type != add->operands[1]->type)
+ continue;
+
/* Depending of the zero position we want to optimize
* (0 cmp x+y) into (-x cmp y) or (x+y cmp 0) into (x cmp -y)
*/
case ir_binop_min:
case ir_binop_max:
- if (ir->type->base_type != GLSL_TYPE_FLOAT || options->EmitNoSat)
+ if (!ir->type->is_float() || options->EmitNoSat)
break;
/* Replace min(max) operations and its commutative combinations with
ir_constant *one;
switch (ir->type->base_type) {
+ case GLSL_TYPE_FLOAT16:
+ one = new(mem_ctx) ir_constant(float16_t::one(), op2_components);
+ break;
case GLSL_TYPE_FLOAT:
one = new(mem_ctx) ir_constant(1.0f, op2_components);
break;
return ir->operands[2];
break;
+ /* Remove interpolateAt* instructions for demoted inputs. They are
+ * assigned a constant expression to facilitate this.
+ */
+ case ir_unop_interpolate_at_centroid:
+ case ir_binop_interpolate_at_offset:
+ case ir_binop_interpolate_at_sample:
+ if (op_const[0])
+ return ir->operands[0];
+ break;
+
default:
break;
}