From e6824add54056141e7507a33e821af01d1398973 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 10 Dec 2016 19:24:58 +0200 Subject: [PATCH] Refactor and improve unused variable detection in ProgramCompiler It now recognizes and marks for removal assignments to global variables if the variable is not read in any function. --- source/programcompiler.cpp | 170 +++++++++++++++++++------------------ source/programcompiler.h | 20 +++-- 2 files changed, 99 insertions(+), 91 deletions(-) diff --git a/source/programcompiler.cpp b/source/programcompiler.cpp index 4e4b4814..5f8c6f9b 100644 --- a/source/programcompiler.cpp +++ b/source/programcompiler.cpp @@ -1213,41 +1213,39 @@ ProgramCompiler::UnusedVariableLocator::UnusedVariableLocator(): aggregate(0), assignment(0), assignment_target(false), - iteration(false) + global_scope(true) { } void ProgramCompiler::UnusedVariableLocator::apply(Stage &s) { - assignments.push_back(BlockAssignmentMap()); + variables.push_back(BlockVariableMap()); Visitor::apply(s); - assignments.pop_back(); + BlockVariableMap &global_variables = variables.back(); + for(BlockVariableMap::iterator i=global_variables.begin(); i!=global_variables.end(); ++i) + { + if(i->first->interface=="out" && (s.type==FRAGMENT || i->first->linked_declaration || !i->first->name.compare(0, 3, "gl_"))) + continue; + if(!i->second.referenced) + { + unused_nodes.insert(i->first); + for(vector::iterator j=i->second.assignments.begin(); j!=i->second.assignments.end(); ++j) + unused_nodes.insert(*j); + } + } + variables.pop_back(); } void ProgramCompiler::UnusedVariableLocator::visit(VariableReference &var) { - unused_nodes.erase(var.declaration); - map::iterator i = aggregates.find(var.declaration); if(i!=aggregates.end()) unused_nodes.erase(i->second); - if(assignment_target) - return; - - if(iteration) - used_in_iteration.insert(var.declaration); - - for(vector::iterator j=assignments.end(); j!=assignments.begin(); ) + if(var.declaration && !assignment_target) { - --j; - BlockAssignmentMap::iterator k = j->find(var.declaration); - if(k!=j->end()) - { - for(vector::iterator l=k->second.nodes.begin(); l!=k->second.nodes.end(); ++l) - unused_nodes.erase(*l); - j->erase(k); - break; - } + VariableInfo &var_info = variables.back()[var.declaration]; + var_info.assignments.clear(); + var_info.referenced = true; } } @@ -1281,15 +1279,11 @@ void ProgramCompiler::UnusedVariableLocator::visit(Assignment &assign) void ProgramCompiler::UnusedVariableLocator::record_assignment(VariableDeclaration &var, Node &node, bool self_ref) { - if(!used_in_iteration.count(&var)) - unused_nodes.insert(&node); - BlockAssignmentMap &block_assignments = assignments.back(); - AssignmentList &var_assignments = block_assignments[&var]; + VariableInfo &var_info = variables.back()[&var]; if(!self_ref) - var_assignments.nodes.clear(); - var_assignments.nodes.push_back(&node); - var_assignments.conditional = false; - var_assignments.self_referencing = self_ref; + var_info.assignments.clear(); + var_info.assignments.push_back(&node); + var_info.conditionally_assigned = false; } void ProgramCompiler::UnusedVariableLocator::visit(ExpressionStatement &expr) @@ -1313,7 +1307,7 @@ void ProgramCompiler::UnusedVariableLocator::visit(VariableDeclaration &var) aggregates[&var] = aggregate; else { - unused_nodes.insert(&var); + variables.back()[&var].local = true; if(var.init_expression) record_assignment(var, *var.init_expression, false); } @@ -1330,95 +1324,107 @@ void ProgramCompiler::UnusedVariableLocator::visit(InterfaceBlock &iface) void ProgramCompiler::UnusedVariableLocator::visit(FunctionDeclaration &func) { - assignments.push_back(BlockAssignmentMap()); - - for(vector >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i) - (*i)->visit(*this); - func.body.visit(*this); + variables.push_back(BlockVariableMap()); - BlockAssignmentMap &block_assignments = assignments.back(); - for(map::iterator i=func.body.variables.begin(); i!=func.body.variables.end(); ++i) - block_assignments.erase(i->second); - for(BlockAssignmentMap::iterator i=block_assignments.begin(); i!=block_assignments.end(); ++i) { - if(i->first->interface=="out" && stage->type!=FRAGMENT && !i->first->linked_declaration) - continue; - - for(vector::iterator j=i->second.nodes.begin(); j!=i->second.nodes.end(); ++j) - unused_nodes.erase(*j); + SetForScope set(global_scope, false); + for(vector >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i) + (*i)->visit(*this); + func.body.visit(*this); } - assignments.pop_back(); + BlockVariableMap &block_variables = variables.back(); + for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i) + i->second.conditionally_assigned = true; + merge_down_variables(); } -void ProgramCompiler::UnusedVariableLocator::merge_down_assignments() +void ProgramCompiler::UnusedVariableLocator::merge_down_variables() { - BlockAssignmentMap &parent_assignments = assignments[assignments.size()-2]; - BlockAssignmentMap &block_assignments = assignments.back(); - for(BlockAssignmentMap::iterator i=block_assignments.begin(); i!=block_assignments.end(); ++i) + BlockVariableMap &parent_variables = variables[variables.size()-2]; + BlockVariableMap &block_variables = variables.back(); + for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i) { - BlockAssignmentMap::iterator j = parent_assignments.find(i->first); - if(j==parent_assignments.end()) - parent_assignments.insert(*i); - else if(i->second.self_referencing || i->second.conditional) + if(i->second.local) { - j->second.nodes.insert(j->second.nodes.end(), i->second.nodes.begin(), i->second.nodes.end()); - j->second.conditional |= i->second.conditional; - j->second.self_referencing |= i->second.self_referencing; + if(!i->second.referenced) + unused_nodes.insert(i->first); + for(vector::iterator j=i->second.assignments.begin(); j!=i->second.assignments.end(); ++j) + unused_nodes.insert(*j); + continue; } + + BlockVariableMap::iterator j = parent_variables.find(i->first); + if(j==parent_variables.end()) + parent_variables.insert(*i); else - j->second = i->second; + { + if(!i->second.conditionally_assigned) + { + j->second.assignments.clear(); + j->second.conditionally_assigned = true; + } + j->second.referenced |= i->second.referenced; + j->second.assignments.insert(j->second.assignments.end(), i->second.assignments.begin(), i->second.assignments.end()); + } } - assignments.pop_back(); + variables.pop_back(); } void ProgramCompiler::UnusedVariableLocator::visit(Conditional &cond) { cond.condition->visit(*this); - assignments.push_back(BlockAssignmentMap()); + variables.push_back(BlockVariableMap()); cond.body.visit(*this); - BlockAssignmentMap if_assignments; - swap(assignments.back(), if_assignments); + BlockVariableMap if_variables; + swap(variables.back(), if_variables); cond.else_body.visit(*this); - BlockAssignmentMap &else_assignments = assignments.back(); - for(BlockAssignmentMap::iterator i=else_assignments.begin(); i!=else_assignments.end(); ++i) + BlockVariableMap &else_variables = variables.back(); + for(BlockVariableMap::iterator i=else_variables.begin(); i!=else_variables.end(); ++i) { - BlockAssignmentMap::iterator j = if_assignments.find(i->first); - if(j!=if_assignments.end()) + BlockVariableMap::iterator j = if_variables.find(i->first); + if(j!=if_variables.end()) { - i->second.nodes.insert(i->second.nodes.end(), j->second.nodes.begin(), j->second.nodes.end()); - i->second.conditional |= j->second.conditional; - i->second.self_referencing |= j->second.self_referencing; - if_assignments.erase(j); + i->second.assignments.insert(i->second.assignments.end(), j->second.assignments.begin(), j->second.assignments.end()); + i->second.conditionally_assigned |= j->second.conditionally_assigned; + if_variables.erase(j); } else - i->second.conditional = true; + i->second.conditionally_assigned = true; } - for(BlockAssignmentMap::iterator i=if_assignments.begin(); i!=if_assignments.end(); ++i) + for(BlockVariableMap::iterator i=if_variables.begin(); i!=if_variables.end(); ++i) { - i->second.conditional = true; - else_assignments.insert(*i); + i->second.conditionally_assigned = true; + else_variables.insert(*i); } - merge_down_assignments(); + merge_down_variables(); } void ProgramCompiler::UnusedVariableLocator::visit(Iteration &iter) { - assignments.push_back(BlockAssignmentMap()); - { - SetFlag set(iteration); - TraversingVisitor::visit(iter); - } - merge_down_assignments(); - if(!iteration) - used_in_iteration.clear(); + variables.push_back(BlockVariableMap()); + TraversingVisitor::visit(iter); + + BlockVariableMap &block_variables = variables.back(); + for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i) + if(!i->second.local && i->second.referenced) + i->second.assignments.clear(); + + merge_down_variables(); } +ProgramCompiler::UnusedVariableLocator::VariableInfo::VariableInfo(): + local(false), + conditionally_assigned(false), + referenced(false) +{ } + + void ProgramCompiler::UnusedFunctionLocator::visit(FunctionCall &call) { TraversingVisitor::visit(call); diff --git a/source/programcompiler.h b/source/programcompiler.h index db63eb36..0ff4f667 100644 --- a/source/programcompiler.h +++ b/source/programcompiler.h @@ -246,24 +246,26 @@ private: struct UnusedVariableLocator: Visitor { - struct AssignmentList + struct VariableInfo { - std::vector nodes; - bool conditional; - bool self_referencing; + bool local; + std::vector assignments; + bool conditionally_assigned; + bool referenced; + + VariableInfo(); }; typedef std::set ResultType; - typedef std::map BlockAssignmentMap; + typedef std::map BlockVariableMap; std::set unused_nodes; std::map aggregates; ProgramSyntax::Node *aggregate; - std::vector assignments; + std::vector variables; ProgramSyntax::Assignment *assignment; bool assignment_target; - bool iteration; - std::set used_in_iteration; + bool global_scope; UnusedVariableLocator(); @@ -279,7 +281,7 @@ private: virtual void visit(ProgramSyntax::VariableDeclaration &); virtual void visit(ProgramSyntax::InterfaceBlock &); virtual void visit(ProgramSyntax::FunctionDeclaration &); - void merge_down_assignments(); + void merge_down_variables(); virtual void visit(ProgramSyntax::Conditional &); virtual void visit(ProgramSyntax::Iteration &); }; -- 2.45.2