X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fprogramcompiler.cpp;h=4e4b4814f171b531bfffedea17c9b9d46101fab1;hb=ced18c244f874638dc17ae486802bb3bb01ecf71;hp=7224df1efba672d4afb7ecb12923a0109ae9f6f6;hpb=00be85f53c5bec0be00a7ed6271e1f5a38e0b534;p=libs%2Fgl.git diff --git a/source/programcompiler.cpp b/source/programcompiler.cpp index 7224df1e..4e4b4814 100644 --- a/source/programcompiler.cpp +++ b/source/programcompiler.cpp @@ -173,6 +173,9 @@ bool ProgramCompiler::optimize(Stage &stage) { apply(stage); + set inlineable = apply(stage); + apply(stage, inlineable); + set unused = apply(stage); set unused2 = apply(stage); unused.insert(unused2.begin(), unused2.end()); @@ -449,6 +452,12 @@ void ProgramCompiler::Formatter::visit(Return &ret) formatted += ';'; } +void ProgramCompiler::Formatter::visit(Jump &jump) +{ + formatted += jump.keyword; + formatted += ';'; +} + ProgramCompiler::DeclarationCombiner::DeclarationCombiner(): toplevel(true), @@ -957,6 +966,108 @@ void ProgramCompiler::DeclarationReorderer::visit(Block &block) } +ProgramCompiler::InlineableFunctionLocator::InlineableFunctionLocator(): + in_function(0) +{ } + +void ProgramCompiler::InlineableFunctionLocator::visit(FunctionCall &call) +{ + FunctionDeclaration *def = call.declaration; + if(def && def->definition!=def) + def = def->definition; + + if(def) + { + unsigned &count = refcounts[def]; + ++count; + if(count>1 || def==in_function) + inlineable.erase(def); + } + + TraversingVisitor::visit(call); +} + +void ProgramCompiler::InlineableFunctionLocator::visit(FunctionDeclaration &func) +{ + unsigned &count = refcounts[func.definition]; + if(!count && func.parameters.empty()) + inlineable.insert(func.definition); + + SetForScope set(in_function, &func); + TraversingVisitor::visit(func); +} + + +ProgramCompiler::FunctionInliner::FunctionInliner(): + extract_result(0) +{ } + +ProgramCompiler::FunctionInliner::FunctionInliner(const set &in): + inlineable(in), + extract_result(0) +{ } + +void ProgramCompiler::FunctionInliner::visit_and_inline(RefPtr &ptr) +{ + inline_result = 0; + ptr->visit(*this); + if(inline_result) + ptr = inline_result; +} + +void ProgramCompiler::FunctionInliner::visit(Block &block) +{ + if(extract_result) + --extract_result; + + for(list >::iterator i=block.body.begin(); i!=block.body.end(); ++i) + { + (*i)->visit(*this); + if(extract_result) + --extract_result; + } +} + +void ProgramCompiler::FunctionInliner::visit(UnaryExpression &unary) +{ + visit_and_inline(unary.expression); + inline_result = 0; +} + +void ProgramCompiler::FunctionInliner::visit(BinaryExpression &binary) +{ + visit_and_inline(binary.left); + visit_and_inline(binary.right); + inline_result = 0; +} + +void ProgramCompiler::FunctionInliner::visit(FunctionCall &call) +{ + for(vector >::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i) + visit_and_inline(*i); + + FunctionDeclaration *def = call.declaration; + if(def && def->definition!=def) + def = def->definition; + + if(def && inlineable.count(def)) + { + extract_result = 2; + def->visit(*this); + } + else + inline_result = 0; +} + +void ProgramCompiler::FunctionInliner::visit(Return &ret) +{ + TraversingVisitor::visit(ret); + + if(extract_result) + inline_result = ret.expression->clone(); +} + + ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator(): variable_values(0), result(0.0f), @@ -1101,7 +1212,8 @@ void ProgramCompiler::ConstantConditionEliminator::visit(Iteration &iter) ProgramCompiler::UnusedVariableLocator::UnusedVariableLocator(): aggregate(0), assignment(0), - assignment_target(false) + assignment_target(false), + iteration(false) { } void ProgramCompiler::UnusedVariableLocator::apply(Stage &s) @@ -1122,6 +1234,9 @@ void ProgramCompiler::UnusedVariableLocator::visit(VariableReference &var) if(assignment_target) return; + if(iteration) + used_in_iteration.insert(var.declaration); + for(vector::iterator j=assignments.end(); j!=assignments.begin(); ) { --j; @@ -1166,7 +1281,8 @@ void ProgramCompiler::UnusedVariableLocator::visit(Assignment &assign) void ProgramCompiler::UnusedVariableLocator::record_assignment(VariableDeclaration &var, Node &node, bool self_ref) { - unused_nodes.insert(&node); + if(!used_in_iteration.count(&var)) + unused_nodes.insert(&node); BlockAssignmentMap &block_assignments = assignments.back(); AssignmentList &var_assignments = block_assignments[&var]; if(!self_ref) @@ -1293,8 +1409,13 @@ void ProgramCompiler::UnusedVariableLocator::visit(Conditional &cond) void ProgramCompiler::UnusedVariableLocator::visit(Iteration &iter) { assignments.push_back(BlockAssignmentMap()); - TraversingVisitor::visit(iter); + { + SetFlag set(iteration); + TraversingVisitor::visit(iter); + } merge_down_assignments(); + if(!iteration) + used_in_iteration.clear(); }