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.
This commit is contained in:
Eric Anholt
2010-08-22 18:15:20 -07:00
parent 137b8397fa
commit 6606fde3ec

View File

@@ -28,6 +28,7 @@
#include "ir.h" #include "ir.h"
#include "ir_visitor.h" #include "ir_visitor.h"
#include "ir_rvalue_visitor.h"
#include "ir_optimization.h" #include "ir_optimization.h"
#include "glsl_types.h" #include "glsl_types.h"
@@ -35,7 +36,7 @@
* Visitor class for replacing expressions with ir_constant values. * 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: public:
ir_constant_folding_visitor() ir_constant_folding_visitor()
{ {
@@ -47,40 +48,15 @@ public:
/* empty */ /* empty */
} }
/** virtual ir_visitor_status visit_enter(ir_assignment *ir);
* \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 *);
/*@}*/
void fold_constant(ir_rvalue **rvalue); virtual void handle_rvalue(ir_rvalue **rvalue);
bool progress; bool progress;
}; };
void 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) if (*rvalue == NULL || (*rvalue)->ir_type == ir_type_constant)
return; return;
@@ -94,104 +70,20 @@ ir_constant_folding_visitor::fold_constant(ir_rvalue **rvalue)
} }
} }
void ir_visitor_status
ir_constant_folding_visitor::visit(ir_variable *ir) ir_constant_folding_visitor::visit_enter(ir_assignment *ir)
{ {
(void) ir; ir->rhs->accept(this);
} handle_rvalue(&ir->rhs);
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)
{
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);
if (ir->condition) { 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 /* If the condition is constant, either remove the condition or
* remove the never-executed assignment. * remove the never-executed assignment.
*/ */
ir_constant *const_val = ir->condition->constant_expression_value();
if (const_val) { if (const_val) {
if (const_val->value.b[0]) if (const_val->value.b[0])
ir->condition = NULL; ir->condition = NULL;
@@ -200,66 +92,12 @@ ir_constant_folding_visitor::visit(ir_assignment *ir)
this->progress = true; this->progress = true;
} }
} }
}
/* Don't descend into the LHS because we want it to stay as a
void * variable dereference. FINISHME: We probably should to get array
ir_constant_folding_visitor::visit(ir_constant *ir) * indices though.
{ */
(void) ir; return visit_continue_with_parent;
}
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;
} }
bool bool
@@ -267,7 +105,7 @@ do_constant_folding(exec_list *instructions)
{ {
ir_constant_folding_visitor constant_folding; ir_constant_folding_visitor constant_folding;
visit_exec_list(instructions, &constant_folding); visit_list_elements(&constant_folding, instructions);
return constant_folding.progress; return constant_folding.progress;
} }