glsl/builtins: Use ivec for texel offsets in textureProjGradOffset.
[mesa.git] / src / glsl / opt_copy_propagation_elements.cpp
index a91e624cb720ae793a09ff2c0c185ab1f7a4ccc0..314db4e187ff7d74f8fed2d5b56fb3d6c2c4e071 100644 (file)
@@ -108,6 +108,7 @@ public:
    virtual ir_visitor_status visit_leave(class ir_assignment *);
    virtual ir_visitor_status visit_enter(class ir_call *);
    virtual ir_visitor_status visit_enter(class ir_if *);
+   virtual ir_visitor_status visit_leave(class ir_swizzle *);
 
    void handle_rvalue(ir_rvalue **rvalue);
 
@@ -179,6 +180,15 @@ ir_copy_propagation_elements_visitor::visit_leave(ir_assignment *ir)
    return visit_continue;
 }
 
+ir_visitor_status
+ir_copy_propagation_elements_visitor::visit_leave(ir_swizzle *ir)
+{
+   /* Don't visit the values of swizzles since they are handled while
+    * visiting the swizzle itself.
+    */
+   return visit_continue;
+}
+
 /**
  * Replaces dereferences of ACP RHS variables with ACP LHS variables.
  *
@@ -278,7 +288,7 @@ ir_visitor_status
 ir_copy_propagation_elements_visitor::visit_enter(ir_call *ir)
 {
    /* Do copy propagation on call parameters, but skip any out params */
-   exec_list_iterator sig_param_iter = ir->get_callee()->parameters.iterator();
+   exec_list_iterator sig_param_iter = ir->callee->parameters.iterator();
    foreach_iter(exec_list_iterator, iter, ir->actual_parameters) {
       ir_variable *sig_param = (ir_variable *)sig_param_iter.get();
       ir_instruction *ir = (ir_instruction *)iter.get();
@@ -451,7 +461,20 @@ ir_copy_propagation_elements_visitor::add_copy(ir_assignment *ir)
         swizzle[i] = orig_swizzle[j++];
    }
 
-   entry = new(this->mem_ctx) acp_entry(lhs->var, rhs->var, ir->write_mask,
+   int write_mask = ir->write_mask;
+   if (lhs->var == rhs->var) {
+      /* If this is a copy from the variable to itself, then we need
+       * to be sure not to include the updated channels from this
+       * instruction in the set of new source channels to be
+       * copy-propagated from.
+       */
+      for (int i = 0; i < 4; i++) {
+        if (ir->write_mask & (1 << orig_swizzle[i]))
+           write_mask &= ~(1 << i);
+      }
+   }
+
+   entry = new(this->mem_ctx) acp_entry(lhs->var, rhs->var, write_mask,
                                        swizzle);
    this->acp->push_tail(entry);
 }