glsl2: Flatten out expressions that are the child of an assignment rhs.
authorEric Anholt <eric@anholt.net>
Mon, 12 Jul 2010 17:48:22 +0000 (10:48 -0700)
committerEric Anholt <eric@anholt.net>
Mon, 12 Jul 2010 19:02:32 +0000 (12:02 -0700)
This feels a little odd, but it will be useful for ir_mat_to_vec,
where I want to see a plain assignment of the expression to a
variable, not to a writemasked array dereference with a call as the
array index.

src/glsl/ir_expression_flattening.cpp

index 5ba24e390b4554db698370e3d0e096bc375e5149..0f10b671936312970f83b70df2912e8c522bf809 100644 (file)
@@ -57,9 +57,11 @@ public:
    virtual ir_visitor_status visit_enter(ir_function_signature *);
    virtual ir_visitor_status visit_enter(ir_if *);
    virtual ir_visitor_status visit_enter(ir_loop *);
+   virtual ir_visitor_status visit_leave(ir_assignment *);
    virtual ir_visitor_status visit_leave(ir_expression *);
    virtual ir_visitor_status visit_leave(ir_swizzle *);
 
+   ir_rvalue *operand_to_temp(ir_rvalue *val);
    bool (*predicate)(ir_instruction *ir);
    ir_instruction *base_ir;
 };
@@ -77,13 +79,16 @@ do_expression_flattening(exec_list *instructions,
 }
 
 
-static ir_rvalue *
-operand_to_temp(ir_instruction *base_ir, ir_rvalue *ir)
+ir_rvalue *
+ir_expression_flattening_visitor::operand_to_temp(ir_rvalue *ir)
 {
    void *ctx = talloc_parent(base_ir);
    ir_variable *var;
    ir_assignment *assign;
 
+   if (!this->predicate(ir))
+      return ir;
+
    var = new(ctx) ir_variable(ir->type, "flattening_tmp");
    base_ir->insert_before(var);
 
@@ -131,20 +136,27 @@ ir_expression_flattening_visitor::visit_leave(ir_expression *ir)
       /* If the operand matches the predicate, then we'll assign its
        * value to a temporary and deref the temporary as the operand.
        */
-      if (this->predicate(ir->operands[operand])) {
-        ir->operands[operand] = operand_to_temp(base_ir,
-                                                ir->operands[operand]);
-      }
+      ir->operands[operand] = operand_to_temp(ir->operands[operand]);
    }
 
    return visit_continue;
 }
 
+ir_visitor_status
+ir_expression_flattening_visitor::visit_leave(ir_assignment *ir)
+{
+   ir->rhs = operand_to_temp(ir->rhs);
+   if (ir->condition)
+      ir->condition = operand_to_temp(ir->condition);
+
+   return visit_continue;
+}
+
 ir_visitor_status
 ir_expression_flattening_visitor::visit_leave(ir_swizzle *ir)
 {
    if (this->predicate(ir->val)) {
-      ir->val = operand_to_temp(this->base_ir, ir->val);
+      ir->val = operand_to_temp(ir->val);
    }
 
    return visit_continue;