* help anyway by triggering other optimizations that live in the HIR.
*/
-#include <stdio.h>
#include "ir.h"
#include "ir_visitor.h"
-#include "ir_print_visitor.h"
#include "ir_basic_block.h"
#include "ir_optimization.h"
#include "glsl_types.h"
ir_variable *rhs;
};
-class ir_copy_propagation_visitor : public ir_visitor {
+class ir_copy_propagation_visitor : public ir_hierarchical_visitor {
public:
ir_copy_propagation_visitor(exec_list *acp)
{
progress = false;
+ in_lhs = false;
this->acp = acp;
}
- /**
- * \name Visit methods
- *
- * As typical for the visitor pattern, there must be one \c visit method for
- * each concrete subclass of \c ir_instruction. Virtual base classes within
- * the hierarchy should not have \c visit methods.
- */
- /*@{*/
- virtual void visit(ir_variable *);
- virtual void visit(ir_loop *);
- virtual void visit(ir_loop_jump *);
- virtual void visit(ir_function_signature *);
- virtual void visit(ir_function *);
- virtual void visit(ir_expression *);
- virtual void visit(ir_swizzle *);
- virtual void visit(ir_dereference *);
- virtual void visit(ir_assignment *);
- virtual void visit(ir_constant *);
- virtual void visit(ir_call *);
- virtual void visit(ir_return *);
- virtual void visit(ir_if *);
- /*@}*/
+ virtual ir_visitor_status visit(class ir_dereference_variable *);
+ virtual ir_visitor_status visit_enter(class ir_loop *);
+ virtual ir_visitor_status visit_enter(class ir_function_signature *);
+ virtual ir_visitor_status visit_enter(class ir_function *);
+ virtual ir_visitor_status visit_enter(class ir_assignment *);
+ virtual ir_visitor_status visit_enter(class ir_call *);
+ virtual ir_visitor_status visit_enter(class ir_if *);
/** List of acp_entry */
exec_list *acp;
bool progress;
+
+ /** Currently in the LHS of an assignment? */
+ bool in_lhs;
};
-void
-ir_copy_propagation_visitor::visit(ir_variable *ir)
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_loop *ir)
{
(void)ir;
+ return visit_continue_with_parent;
}
-
-void
-ir_copy_propagation_visitor::visit(ir_loop *ir)
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_function_signature *ir)
{
(void)ir;
+ return visit_continue_with_parent;
}
-void
-ir_copy_propagation_visitor::visit(ir_loop_jump *ir)
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_assignment *ir)
{
(void) ir;
+ this->in_lhs = true;
+ return visit_continue;
}
-
-void
-ir_copy_propagation_visitor::visit(ir_function_signature *ir)
-{
- (void)ir;
-}
-
-void
-ir_copy_propagation_visitor::visit(ir_function *ir)
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_function *ir)
{
(void) ir;
-}
-
-void
-ir_copy_propagation_visitor::visit(ir_expression *ir)
-{
- unsigned int operand;
-
- for (operand = 0; operand < ir->get_num_operands(); operand++) {
- ir->operands[operand]->accept(this);
- }
-}
-
-
-void
-ir_copy_propagation_visitor::visit(ir_swizzle *ir)
-{
- ir->val->accept(this);
+ return visit_continue_with_parent;
}
/**
* rewriting of ir_dereference means that the ir_dereference instance
* must not be shared by multiple IR operations!
*/
-void
-ir_copy_propagation_visitor::visit(ir_dereference *ir)
+ir_visitor_status
+ir_copy_propagation_visitor::visit(ir_dereference_variable *ir)
{
- ir_variable *var;
-
- if (ir->mode == ir_dereference::ir_reference_array) {
- ir->selector.array_index->accept(this);
- }
-
- var = ir->var->as_variable();
- if (var) {
- foreach_iter(exec_list_iterator, iter, *this->acp) {
- acp_entry *entry = (acp_entry *)iter.get();
-
- if (var == entry->lhs) {
- ir->var = entry->rhs;
- this->progress = true;
- break;
- }
- }
- } else {
- ir->var->accept(this);
- }
-}
-
-void
-ir_copy_propagation_visitor::visit(ir_assignment *ir)
-{
- if (ir->condition)
- ir->condition->accept(this);
-
/* Ignores the LHS. Don't want to rewrite the LHS to point at some
* other storage!
*/
+ if (this->in_lhs) {
+ this->in_lhs = false;
+ return visit_continue;
+ }
- ir->rhs->accept(this);
-}
+ ir_variable *var = ir->variable_referenced();
+ foreach_iter(exec_list_iterator, iter, *this->acp) {
+ acp_entry *entry = (acp_entry *)iter.get();
-void
-ir_copy_propagation_visitor::visit(ir_constant *ir)
-{
- (void) ir;
+ if (var == entry->lhs) {
+ ir->var = entry->rhs;
+ this->progress = true;
+ break;
+ }
+ }
+
+ return visit_continue;
}
-void
-ir_copy_propagation_visitor::visit(ir_call *ir)
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_call *ir)
{
(void)ir;
/* Note, if we were to do copy propagation to parameters of calls, we'd
* have to be careful about out params.
*/
+ return visit_continue_with_parent;
}
-void
-ir_copy_propagation_visitor::visit(ir_return *ir)
-{
- ir_rvalue *val = ir->get_value();
-
- if (val)
- val->accept(this);
-}
-
-
-void
-ir_copy_propagation_visitor::visit(ir_if *ir)
+ir_visitor_status
+ir_copy_propagation_visitor::visit_enter(ir_if *ir)
{
ir->condition->accept(this);
+
+ /* Do not traverse into the body of the if-statement since that is a
+ * different basic block.
+ */
+ return visit_continue_with_parent;
}
static bool
return;
}
- ir_dereference *lhs_deref = ir->lhs->as_dereference();
- if (!lhs_deref || lhs_deref->mode != ir_dereference::ir_reference_variable)
- return;
- ir_variable *lhs_var = lhs_deref->var->as_variable();
+ ir_variable *lhs_var = ir->lhs->whole_variable_referenced();
+ ir_variable *rhs_var = ir->rhs->whole_variable_referenced();
- ir_dereference *rhs_deref = ir->rhs->as_dereference();
- if (!rhs_deref || rhs_deref->mode != ir_dereference::ir_reference_variable)
- return;
- ir_variable *rhs_var = rhs_deref->var->as_variable();
-
- entry = new acp_entry(lhs_var, rhs_var);
- acp->push_tail(entry);
+ if ((lhs_var != NULL) && (rhs_var != NULL)) {
+ entry = new acp_entry(lhs_var, rhs_var);
+ acp->push_tail(entry);
+ }
}
static void