glsl: Convert constant folding to the rvalue visitor.
authorEric Anholt <eric@anholt.net>
Mon, 23 Aug 2010 01:15:20 +0000 (18:15 -0700)
committerEric Anholt <eric@anholt.net>
Mon, 23 Aug 2010 01:34:46 +0000 (18:34 -0700)
This should be mostly a noop, except that a plain dereference of a
variable that is not part of a constant expression could now get
"constant folded".  I expect that for all current backends this will
be either a noop, or possibly a win when it provokes more
ir_algebraic.  It'll also ensure that when new features are added,
tree walking will work normally.  Before this, constants weren't
getting folded inside of loops.

src/glsl/ir_constant_folding.cpp

index 11260423d90b81ccb0dc7669f7332b502509b6a4..90135b5807a15f5562f293f22069e5dd7dc7b09f 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "ir.h"
 #include "ir_visitor.h"
+#include "ir_rvalue_visitor.h"
 #include "ir_optimization.h"
 #include "glsl_types.h"
 
@@ -35,7 +36,7 @@
  * Visitor class for replacing expressions with ir_constant values.
  */
 
-class ir_constant_folding_visitor : public ir_visitor {
+class ir_constant_folding_visitor : public ir_rvalue_visitor {
 public:
    ir_constant_folding_visitor()
    {
@@ -47,40 +48,15 @@ public:
       /* empty */
    }
 
-   /**
-    * \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_function_signature *);
-   virtual void visit(ir_function *);
-   virtual void visit(ir_expression *);
-   virtual void visit(ir_texture *);
-   virtual void visit(ir_swizzle *);
-   virtual void visit(ir_dereference_variable *);
-   virtual void visit(ir_dereference_array *);
-   virtual void visit(ir_dereference_record *);
-   virtual void visit(ir_assignment *);
-   virtual void visit(ir_constant *);
-   virtual void visit(ir_call *);
-   virtual void visit(ir_return *);
-   virtual void visit(ir_discard *);
-   virtual void visit(ir_if *);
-   virtual void visit(ir_loop *);
-   virtual void visit(ir_loop_jump *);
-   /*@}*/
+   virtual ir_visitor_status visit_enter(ir_assignment *ir);
 
-   void fold_constant(ir_rvalue **rvalue);
+   virtual void handle_rvalue(ir_rvalue **rvalue);
 
    bool progress;
 };
 
 void
-ir_constant_folding_visitor::fold_constant(ir_rvalue **rvalue)
+ir_constant_folding_visitor::handle_rvalue(ir_rvalue **rvalue)
 {
    if (*rvalue == NULL || (*rvalue)->ir_type == ir_type_constant)
       return;
@@ -94,104 +70,20 @@ ir_constant_folding_visitor::fold_constant(ir_rvalue **rvalue)
    }
 }
 
-void
-ir_constant_folding_visitor::visit(ir_variable *ir)
-{
-   (void) ir;
-}
-
-
-void
-ir_constant_folding_visitor::visit(ir_function_signature *ir)
-{
-   visit_exec_list(&ir->body, this);
-}
-
-
-void
-ir_constant_folding_visitor::visit(ir_function *ir)
-{
-   foreach_iter(exec_list_iterator, iter, *ir) {
-      ir_function_signature *const sig = (ir_function_signature *) iter.get();
-      sig->accept(this);
-   }
-}
-
-void
-ir_constant_folding_visitor::visit(ir_expression *ir)
-{
-   unsigned int operand;
-
-   for (operand = 0; operand < ir->get_num_operands(); operand++) {
-      fold_constant(&ir->operands[operand]);
-   }
-}
-
-
-void
-ir_constant_folding_visitor::visit(ir_texture *ir)
-{
-   fold_constant(&ir->coordinate);
-   fold_constant(&ir->projector);
-   fold_constant(&ir->shadow_comparitor);
-
-   switch (ir->op) {
-   case ir_tex:
-      break;
-   case ir_txb:
-      fold_constant(&ir->lod_info.bias);
-      break;
-   case ir_txf:
-   case ir_txl:
-      fold_constant(&ir->lod_info.lod);
-      break;
-   case ir_txd:
-      fold_constant(&ir->lod_info.grad.dPdx);
-      fold_constant(&ir->lod_info.grad.dPdy);
-      break;
-   }
-}
-
-
-void
-ir_constant_folding_visitor::visit(ir_swizzle *ir)
+ir_visitor_status
+ir_constant_folding_visitor::visit_enter(ir_assignment *ir)
 {
-   fold_constant(&ir->val);
-}
-
-
-void
-ir_constant_folding_visitor::visit(ir_dereference_variable *ir)
-{
-   (void) ir;
-}
-
-
-void
-ir_constant_folding_visitor::visit(ir_dereference_array *ir)
-{
-   fold_constant(&ir->array_index);
-   ir->array->accept(this);
-}
-
-
-void
-ir_constant_folding_visitor::visit(ir_dereference_record *ir)
-{
-   ir->record->accept(this);
-}
-
-
-void
-ir_constant_folding_visitor::visit(ir_assignment *ir)
-{
-   fold_constant(&ir->rhs);
+   ir->rhs->accept(this);
+   handle_rvalue(&ir->rhs);
 
    if (ir->condition) {
+      ir->condition->accept(this);
+      handle_rvalue(&ir->condition);
+
+      ir_constant *const_val = ir->condition->as_constant();
       /* If the condition is constant, either remove the condition or
        * remove the never-executed assignment.
        */
-      ir_constant *const_val = ir->condition->constant_expression_value();
       if (const_val) {
         if (const_val->value.b[0])
            ir->condition = NULL;
@@ -200,66 +92,12 @@ ir_constant_folding_visitor::visit(ir_assignment *ir)
         this->progress = true;
       }
    }
-}
-
-
-void
-ir_constant_folding_visitor::visit(ir_constant *ir)
-{
-   (void) ir;
-}
 
-
-void
-ir_constant_folding_visitor::visit(ir_call *ir)
-{
-   foreach_iter(exec_list_iterator, iter, *ir) {
-      ir_rvalue *param = (ir_rvalue *)iter.get();
-      ir_rvalue *new_param = param;
-      fold_constant(&new_param);
-
-      if (new_param != param) {
-        param->replace_with(new_param);
-      }
-   }
-}
-
-
-void
-ir_constant_folding_visitor::visit(ir_return *ir)
-{
-   fold_constant(&ir->value);
-}
-
-
-void
-ir_constant_folding_visitor::visit(ir_discard *ir)
-{
-   (void) ir;
-}
-
-
-void
-ir_constant_folding_visitor::visit(ir_if *ir)
-{
-   fold_constant(&ir->condition);
-
-   visit_exec_list(&ir->then_instructions, this);
-   visit_exec_list(&ir->else_instructions, this);
-}
-
-
-void
-ir_constant_folding_visitor::visit(ir_loop *ir)
-{
-   (void) ir;
-}
-
-
-void
-ir_constant_folding_visitor::visit(ir_loop_jump *ir)
-{
-   (void) ir;
+   /* Don't descend into the LHS because we want it to stay as a
+    * variable dereference.  FINISHME: We probably should to get array
+    * indices though.
+    */
+   return visit_continue_with_parent;
 }
 
 bool
@@ -267,7 +105,7 @@ do_constant_folding(exec_list *instructions)
 {
    ir_constant_folding_visitor constant_folding;
 
-   visit_exec_list(instructions, &constant_folding);
+   visit_list_elements(&constant_folding, instructions);
 
    return constant_folding.progress;
 }