summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/glsl/ir_algebraic.cpp46
1 files changed, 34 insertions, 12 deletions
diff --git a/src/glsl/ir_algebraic.cpp b/src/glsl/ir_algebraic.cpp
index 0092eea036b..b731ba05be9 100644
--- a/src/glsl/ir_algebraic.cpp
+++ b/src/glsl/ir_algebraic.cpp
@@ -60,8 +60,11 @@ public:
int op1,
ir_expression *ir2,
int op2);
+ ir_rvalue *swizzle_if_required(ir_expression *expr,
+ ir_rvalue *operand);
void *mem_ctx;
+
bool progress;
};
@@ -219,11 +222,27 @@ ir_algebraic_visitor::reassociate_constant(ir_expression *ir1, int const_index,
return false;
}
+/* When eliminating an expression and just returning one of its operands,
+ * we may need to swizzle that operand out to a vector if the expression was
+ * vector type.
+ */
+ir_rvalue *
+ir_algebraic_visitor::swizzle_if_required(ir_expression *expr,
+ ir_rvalue *operand)
+{
+ if (expr->type->is_vector() && operand->type->is_scalar()) {
+ return new(mem_ctx) ir_swizzle(operand, 0, 0, 0, 0,
+ expr->type->vector_elements);
+ } else
+ return operand;
+}
+
ir_rvalue *
ir_algebraic_visitor::handle_expression(ir_expression *ir)
{
ir_constant *op_const[2] = {NULL, NULL};
ir_expression *op_expr[2] = {NULL, NULL};
+ ir_expression *temp;
unsigned int i;
for (i = 0; i < ir->get_num_operands(); i++) {
@@ -272,11 +291,11 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
case ir_binop_add:
if (is_vec_zero(op_const[0])) {
this->progress = true;
- return ir->operands[1];
+ return swizzle_if_required(ir, ir->operands[1]);
}
if (is_vec_zero(op_const[1])) {
this->progress = true;
- return ir->operands[0];
+ return swizzle_if_required(ir, ir->operands[0]);
}
/* Reassociate addition of constants so that we can do constant
@@ -293,25 +312,26 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
case ir_binop_sub:
if (is_vec_zero(op_const[0])) {
this->progress = true;
- return new(mem_ctx) ir_expression(ir_unop_neg,
- ir->type,
+ temp = new(mem_ctx) ir_expression(ir_unop_neg,
+ ir->operands[1]->type,
ir->operands[1],
NULL);
+ return swizzle_if_required(ir, temp);
}
if (is_vec_zero(op_const[1])) {
this->progress = true;
- return ir->operands[0];
+ return swizzle_if_required(ir, ir->operands[0]);
}
break;
case ir_binop_mul:
if (is_vec_one(op_const[0])) {
this->progress = true;
- return ir->operands[1];
+ return swizzle_if_required(ir, ir->operands[1]);
}
if (is_vec_one(op_const[1])) {
this->progress = true;
- return ir->operands[0];
+ return swizzle_if_required(ir, ir->operands[0]);
}
if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) {
@@ -334,14 +354,15 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
case ir_binop_div:
if (is_vec_one(op_const[0]) && ir->type->base_type == GLSL_TYPE_FLOAT) {
this->progress = true;
- return new(mem_ctx) ir_expression(ir_unop_rcp,
- ir->type,
+ temp = new(mem_ctx) ir_expression(ir_unop_rcp,
+ ir->operands[1]->type,
ir->operands[1],
NULL);
+ return swizzle_if_required(ir, temp);
}
if (is_vec_one(op_const[1])) {
this->progress = true;
- return ir->operands[0];
+ return swizzle_if_required(ir, ir->operands[0]);
}
break;
@@ -359,10 +380,11 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
/* As far as we know, all backends are OK with rsq. */
if (op_expr[0] && op_expr[0]->operation == ir_unop_sqrt) {
this->progress = true;
- return new(mem_ctx) ir_expression(ir_unop_rsq,
- ir->type,
+ temp = new(mem_ctx) ir_expression(ir_unop_rsq,
+ op_expr[0]->operands[0]->type,
op_expr[0]->operands[0],
NULL);
+ return swizzle_if_required(ir, temp);
}
break;