X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fglsl%2Fopt_copy_propagation_elements.cpp;h=6a19da40df5bd7e9639b5fcc7902b32e5dcdcb81;hb=9add4e803877f97ad7f6d479d81d537426f09b6f;hp=8541d9a8ee1ca80904b1e261047242211a844f84;hpb=b922a0ce12916a91cfc3e56714913fcf63279ff2;p=mesa.git diff --git a/src/glsl/opt_copy_propagation_elements.cpp b/src/glsl/opt_copy_propagation_elements.cpp index 8541d9a8ee1..6a19da40df5 100644 --- a/src/glsl/opt_copy_propagation_elements.cpp +++ b/src/glsl/opt_copy_propagation_elements.cpp @@ -49,6 +49,8 @@ static bool debug = false; +namespace { + class acp_entry : public exec_node { public: @@ -93,6 +95,7 @@ public: ir_copy_propagation_elements_visitor() { this->progress = false; + this->killed_all = false; this->mem_ctx = ralloc_context(NULL); this->shader_mem_ctx = NULL; this->acp = new(mem_ctx) exec_list; @@ -108,6 +111,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); @@ -133,6 +137,8 @@ public: void *shader_mem_ctx; }; +} /* unnamed namespace */ + ir_visitor_status ir_copy_propagation_elements_visitor::visit_enter(ir_function_signature *ir) { @@ -161,9 +167,16 @@ ir_visitor_status ir_copy_propagation_elements_visitor::visit_leave(ir_assignment *ir) { ir_dereference_variable *lhs = ir->lhs->as_dereference_variable(); + ir_variable *var = ir->lhs->variable_referenced(); + + if (var->type->is_scalar() || var->type->is_vector()) { + kill_entry *k; + + if (lhs) + k = new(mem_ctx) kill_entry(var, ir->write_mask); + else + k = new(mem_ctx) kill_entry(var, ~0); - if (lhs && (lhs->type->is_scalar() || lhs->type->is_vector())) { - kill_entry *k = new(mem_ctx) kill_entry(lhs->var, ir->write_mask); kill(k); } @@ -172,6 +185,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. * @@ -271,11 +293,12 @@ 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(); - if (sig_param->mode != ir_var_out && sig_param->mode != ir_var_inout) { + if (sig_param->mode != ir_var_function_out + && sig_param->mode != ir_var_function_inout) { ir->accept(this); } sig_param_iter.next(); @@ -383,8 +406,10 @@ ir_copy_propagation_elements_visitor::kill(kill_entry *k) if (entry->lhs == k->var) { entry->write_mask = entry->write_mask & ~k->write_mask; - if (entry->write_mask == 0) + if (entry->write_mask == 0) { entry->remove(); + continue; + } } if (entry->rhs == k->var) { entry->remove(); @@ -442,7 +467,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); }