ir_expression_flattening: Handle flattening values out of swizzles, too.
authorEric Anholt <eric@anholt.net>
Thu, 6 May 2010 21:48:20 +0000 (14:48 -0700)
committerEric Anholt <eric@anholt.net>
Tue, 1 Jun 2010 22:15:04 +0000 (15:15 -0700)
Fixes an uninlined normalize() in CorrectSwizzle2.vert.

ir_expression_flattening.cpp

index 9c410b1..394a0d0 100644 (file)
@@ -59,6 +59,7 @@ public:
    virtual ir_visitor_status visit_enter(ir_if *);
    virtual ir_visitor_status visit_enter(ir_loop *);
    virtual ir_visitor_status visit_leave(ir_expression *);
+   virtual ir_visitor_status visit_leave(ir_swizzle *);
 
    bool (*predicate)(ir_instruction *ir);
    ir_instruction *base_ir;
@@ -76,6 +77,24 @@ do_expression_flattening(exec_list *instructions,
    }
 }
 
+
+static ir_rvalue *
+operand_to_temp(ir_instruction *base_ir, ir_rvalue *ir)
+{
+   ir_variable *var;
+   ir_assignment *assign;
+
+   var = new ir_variable(ir->type, "flattening_tmp");
+   base_ir->insert_before(var);
+
+   assign = new ir_assignment(new ir_dereference_variable(var),
+                             ir,
+                             NULL);
+   base_ir->insert_before(assign);
+
+   return new ir_dereference_variable(var);
+}
+
 ir_visitor_status
 ir_expression_flattening_visitor::visit_enter(ir_function_signature *ir)
 {
@@ -113,24 +132,23 @@ ir_expression_flattening_visitor::visit_leave(ir_expression *ir)
        * value to a temporary and deref the temporary as the operand.
        */
       if (this->predicate(ir->operands[operand])) {
-        ir_variable *var;
-        ir_assignment *assign;
-
-        var = new ir_variable(ir->operands[operand]->type, "flattening_tmp");
-        this->base_ir->insert_before(var);
-
-        assign = new ir_assignment(new ir_dereference_variable(var),
-                                   ir->operands[operand],
-                                   NULL);
-        this->base_ir->insert_before(assign);
-
-        ir->operands[operand] = new ir_dereference_variable(var);
+        ir->operands[operand] = operand_to_temp(base_ir,
+                                                ir->operands[operand]);
       }
    }
 
    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);
+   }
+
+   return visit_continue;
+}
 
 ir_visitor_status
 ir_expression_flattening_visitor::visit_enter(ir_call *ir)