From 6606fde3ec18288ecc4c6ce6d3fd32224a6c5248 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sun, 22 Aug 2010 18:15:20 -0700 Subject: [PATCH] glsl: Convert constant folding to the rvalue visitor. 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 | 200 +++---------------------------- 1 file changed, 19 insertions(+), 181 deletions(-) diff --git a/src/glsl/ir_constant_folding.cpp b/src/glsl/ir_constant_folding.cpp index 11260423d90..90135b5807a 100644 --- a/src/glsl/ir_constant_folding.cpp +++ b/src/glsl/ir_constant_folding.cpp @@ -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; } -- 2.30.2