X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fprogramcompiler.cpp;h=a3691b112fd4fc22d8121f04c4d37024037f8470;hp=a1be91ca4f575228fe2f48ccb374fb0097c6dccb;hb=20af6dd2f04caa224d8cae00befc97d010a1ed08;hpb=e37d3b91500994df3de4fe47bd3d3e75d3104b46 diff --git a/source/programcompiler.cpp b/source/programcompiler.cpp index a1be91ca..a3691b11 100644 --- a/source/programcompiler.cpp +++ b/source/programcompiler.cpp @@ -35,8 +35,6 @@ namespace GL { using namespace ProgramSyntax; -// XXX For some reason global declarations are emitted for otherwise undeclared local variables - ProgramCompiler::ProgramCompiler(): resources(0), module(0) @@ -1210,14 +1208,12 @@ void ProgramCompiler::FunctionInliner::visit(Return &ret) ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator(): variable_values(0), - const_only(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) { } @@ -1242,8 +1238,6 @@ void ProgramCompiler::ExpressionEvaluator::visit(VariableReference &var) { if(!var.declaration) return; - if(const_only && !var.declaration->constant) - return; if(variable_values) { @@ -1304,7 +1298,7 @@ void ProgramCompiler::ExpressionEvaluator::visit(BinaryExpression &binary) ProgramCompiler::ConstantConditionEliminator::ConstantConditionEliminator(): scope_level(0), - in_loop(false) + record_only(false) { } void ProgramCompiler::ConstantConditionEliminator::visit(Block &block) @@ -1316,6 +1310,13 @@ void ProgramCompiler::ConstantConditionEliminator::visit(Block &block) variable_values.erase(i->second); } +void ProgramCompiler::ConstantConditionEliminator::visit(UnaryExpression &unary) +{ + if(VariableReference *var = dynamic_cast(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); @@ -1329,30 +1330,49 @@ void ProgramCompiler::ConstantConditionEliminator::visit(VariableDeclaration &va 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) { - // XXX Should this not visit init_statement first? - if(iter.condition) + if(!record_only) { - ExpressionEvaluator eval(0, in_loop); - iter.condition->visit(eval); - if(eval.result_valid && !eval.result) + if(iter.condition) { - 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); + + if(VariableDeclaration *init_decl = dynamic_cast(iter.init_statement.get())) + variable_values.erase(init_decl); }