It used to optimize based on the initial values of variables, ignoring
the fact that they may change between loop iterations. A stop-gap fix
was implemented in
8e14c29, but it prevented optimizations of some
conditionals that could safely have been removed. It also caused the
optimizer to ignore any assignments made to any variables after
declaration when evaluating the loop condition, potentially causing
entire loops to be erroneously removed. Finally, unary expressions were
not being handled so ++ and -- operators did not mark the variable as
modified.
ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator():
variable_values(0),
ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator():
variable_values(0),
result(0.0f),
result_valid(false)
{ }
result(0.0f),
result_valid(false)
{ }
-ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator(const ValueMap *v, bool c):
- variable_values(v),
- const_only(c),
+ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator(const ValueMap &v):
+ variable_values(&v),
result(0.0f),
result_valid(false)
{ }
result(0.0f),
result_valid(false)
{ }
{
if(!var.declaration)
return;
{
if(!var.declaration)
return;
- if(const_only && !var.declaration->constant)
- return;
ProgramCompiler::ConstantConditionEliminator::ConstantConditionEliminator():
scope_level(0),
ProgramCompiler::ConstantConditionEliminator::ConstantConditionEliminator():
scope_level(0),
{ }
void ProgramCompiler::ConstantConditionEliminator::visit(Block &block)
{ }
void ProgramCompiler::ConstantConditionEliminator::visit(Block &block)
variable_values.erase(i->second);
}
variable_values.erase(i->second);
}
+void ProgramCompiler::ConstantConditionEliminator::visit(UnaryExpression &unary)
+{
+ if(VariableReference *var = dynamic_cast<VariableReference *>(unary.expression.get()))
+ if(unary.oper=="++" || unary.oper=="--")
+ variable_values.erase(var->declaration);
+}
+
void ProgramCompiler::ConstantConditionEliminator::visit(Assignment &assign)
{
variable_values.erase(assign.target_declaration);
void ProgramCompiler::ConstantConditionEliminator::visit(Assignment &assign)
{
variable_values.erase(assign.target_declaration);
void ProgramCompiler::ConstantConditionEliminator::visit(Conditional &cond)
{
void ProgramCompiler::ConstantConditionEliminator::visit(Conditional &cond)
{
- ExpressionEvaluator eval(&variable_values, in_loop);
- cond.condition->visit(eval);
- if(eval.result_valid)
- flatten_block(eval.result ? cond.body : cond.else_body);
- else
- TraversingVisitor::visit(cond);
+ if(!record_only)
+ {
+ ExpressionEvaluator eval(variable_values);
+ cond.condition->visit(eval);
+ if(eval.result_valid)
+ {
+ flatten_block(eval.result ? cond.body : cond.else_body);
+ return;
+ }
+ }
+
+ TraversingVisitor::visit(cond);
}
void ProgramCompiler::ConstantConditionEliminator::visit(Iteration &iter)
{
}
void ProgramCompiler::ConstantConditionEliminator::visit(Iteration &iter)
{
- // XXX Should this not visit init_statement first?
- if(iter.condition)
- ExpressionEvaluator eval(0, in_loop);
- iter.condition->visit(eval);
- if(eval.result_valid && !eval.result)
- remove_node = true;
- return;
+ /* If the loop condition is always false on the first iteration, the
+ entire loop can be removed */
+ if(iter.init_statement)
+ iter.init_statement->visit(*this);
+ ExpressionEvaluator eval(variable_values);
+ iter.condition->visit(eval);
+ if(eval.result_valid && !eval.result)
+ {
+ remove_node = true;
+ return;
+ }
+
+ /* Record all assignments that occur inside the loop body so those
+ variables won't be considered as constant */
+ SetFlag set_record(record_only);
+ TraversingVisitor::visit(iter);
- SetFlag set_loop(in_loop);
TraversingVisitor::visit(iter);
TraversingVisitor::visit(iter);
+
+ if(VariableDeclaration *init_decl = dynamic_cast<VariableDeclaration *>(iter.init_statement.get()))
+ variable_values.erase(init_decl);
typedef std::map<ProgramSyntax::VariableDeclaration *, ProgramSyntax::Expression *> ValueMap;
const ValueMap *variable_values;
typedef std::map<ProgramSyntax::VariableDeclaration *, ProgramSyntax::Expression *> ValueMap;
const ValueMap *variable_values;
float result;
bool result_valid;
ExpressionEvaluator();
float result;
bool result_valid;
ExpressionEvaluator();
- ExpressionEvaluator(const ValueMap *, bool);
+ ExpressionEvaluator(const ValueMap &);
using ProgramSyntax::NodeVisitor::visit;
virtual void visit(ProgramSyntax::Literal &);
using ProgramSyntax::NodeVisitor::visit;
virtual void visit(ProgramSyntax::Literal &);
struct ConstantConditionEliminator: BlockModifier
{
unsigned scope_level;
struct ConstantConditionEliminator: BlockModifier
{
unsigned scope_level;
ExpressionEvaluator::ValueMap variable_values;
ConstantConditionEliminator();
using Visitor::visit;
virtual void visit(ProgramSyntax::Block &);
ExpressionEvaluator::ValueMap variable_values;
ConstantConditionEliminator();
using Visitor::visit;
virtual void visit(ProgramSyntax::Block &);
+ virtual void visit(ProgramSyntax::UnaryExpression &);
virtual void visit(ProgramSyntax::Assignment &);
virtual void visit(ProgramSyntax::VariableDeclaration &);
virtual void visit(ProgramSyntax::Conditional &);
virtual void visit(ProgramSyntax::Assignment &);
virtual void visit(ProgramSyntax::VariableDeclaration &);
virtual void visit(ProgramSyntax::Conditional &);