Mesa (master): glsl: When doing algebraic simplification, make sure the type still matches.

Eric Anholt anholt at kemper.freedesktop.org
Tue Aug 17 20:56:28 UTC 2010


Module: Mesa
Branch: master
Commit: 0e6066df633f4594fd6fb8ceeb12b15561c57a48
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=0e6066df633f4594fd6fb8ceeb12b15561c57a48

Author: Eric Anholt <eric at anholt.net>
Date:   Tue Aug 17 13:24:50 2010 -0700

glsl: When doing algebraic simplification, make sure the type still matches.

When simplifying (vec4(1.0) / (float(x))) to rcp(float(x)), we forgot
to produce a vec4, angering ir_validate when starting alien-arena.

Fixes:
glsl-algebraic-add-zero-2
glsl-algebraic-div-one-2
glsl-algebraic-mul-one-2
glsl-algebraic-sub-zero-3
glsl-algebraic-rcp-sqrt-2

---

 src/glsl/ir_algebraic.cpp |   46 +++++++++++++++++++++++++++++++++-----------
 1 files changed, 34 insertions(+), 12 deletions(-)

diff --git a/src/glsl/ir_algebraic.cpp b/src/glsl/ir_algebraic.cpp
index 0092eea..b731ba0 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;




More information about the mesa-commit mailing list