diff options
author | Jean Christophe Beyler <jean.christophe.beyler@intel.com> | 2014-01-07 10:07:18 -0800 |
---|---|---|
committer | Ian Rogers <irogers@google.com> | 2014-01-13 19:34:52 -0800 |
commit | 4e97c539408f47145526f0062c1c06df99146a73 (patch) | |
tree | f196db2807a8e3640ad86e1d8026f2007348db19 /compiler/dex/pass_driver.cc | |
parent | 121f6a1ebaf8abd2b7ec99df8347ec87b78548f7 (diff) | |
download | art-4e97c539408f47145526f0062c1c06df99146a73.tar.gz art-4e97c539408f47145526f0062c1c06df99146a73.tar.bz2 art-4e97c539408f47145526f0062c1c06df99146a73.zip |
Added pass framework
The patch adds a Middle-End pass system and normalizes the current
passes into the pass framework.
Passes have:
- A start, work, and end functions.
- A gate to determine to apply the pass.
- Can provide a CFG dump folder.
mir_dataflow.cc, mir_graph.cc, mir_optimization.cc, ssa_transformation.cc:
- Changed due to moving code into bb_optimizations.cc.
- Moved certain functions from private to public due to needed from the passes.
pass.cc, pass.h:
- Pass base class
pass_driver.cc, pass_driver.h:
- The pass driver implementation.
frontend.cc:
- Replace the function calls to the passes with the pass driver.
Change-Id: I88cd82efbf6499df9e6c7f135d7e294dd724a079
Signed-off-by: Jean Christophe Beyler <jean.christophe.beyler@intel.com>
Diffstat (limited to 'compiler/dex/pass_driver.cc')
-rw-r--r-- | compiler/dex/pass_driver.cc | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/compiler/dex/pass_driver.cc b/compiler/dex/pass_driver.cc new file mode 100644 index 0000000000..b20d7283af --- /dev/null +++ b/compiler/dex/pass_driver.cc @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <dlfcn.h> + +#include "bb_optimizations.h" +#include "compiler_internals.h" +#include "dataflow_iterator.h" +#include "dataflow_iterator-inl.h" +#include "pass.h" +#include "pass_driver.h" + +namespace art { + +PassDriver::PassDriver(CompilationUnit* const cu, bool create_default_passes) : cu_(cu) { + dump_cfg_folder_ = "/sdcard/"; + + // If need be, create the default passes. + if (create_default_passes == true) { + CreatePasses(); + } +} + +PassDriver::~PassDriver() { + // Clear the map: done to remove any chance of having a pointer after freeing below + pass_map_.clear(); +} + +void PassDriver::InsertPass(Pass* new_pass, bool warn_override) { + assert(new_pass != 0); + + // Get name here to not do it all over the method. + const std::string& name = new_pass->GetName(); + + // Do we want to warn the user about squashing a pass? + if (warn_override == false) { + SafeMap<std::string, Pass* >::iterator it = pass_map_.find(name); + + if (it != pass_map_.end()) { + LOG(INFO) << "Pass name " << name << " already used, overwriting pass"; + } + } + + // Now add to map and list. + pass_map_.Put(name, new_pass); + pass_list_.push_back(new_pass); +} + +void PassDriver::CreatePasses() { + /* + * Create the pass list: + * - These passes are immutable and are shared across the threads: + * - This is achieved via: + * - The UniquePtr used here. + * - DISALLOW_COPY_AND_ASSIGN in the base Pass class. + * + * Advantage is that there will be no race conditions here. + * Disadvantage is the passes can't change their internal states depending on CompilationUnit: + * - This is not yet an issue: no current pass would require it. + */ + static UniquePtr<Pass> *passes[] = { + new UniquePtr<Pass>(new CodeLayout()), + new UniquePtr<Pass>(new SSATransformation()), + new UniquePtr<Pass>(new ConstantPropagation()), + new UniquePtr<Pass>(new InitRegLocations()), + new UniquePtr<Pass>(new MethodUseCount()), + new UniquePtr<Pass>(new NullCheckEliminationAndTypeInferenceInit()), + new UniquePtr<Pass>(new NullCheckEliminationAndTypeInference()), + new UniquePtr<Pass>(new BBCombine()), + new UniquePtr<Pass>(new BBOptimizations()), + }; + + // Get number of elements in the array. + unsigned int nbr = (sizeof(passes) / sizeof(passes[0])); + + // Insert each pass into the map and into the list via the InsertPass method: + // - Map is used for the lookup + // - List is used for the pass walk + for (unsigned int i = 0; i < nbr; i++) { + InsertPass(passes[i]->get()); + } +} + +void PassDriver::HandlePassFlag(CompilationUnit* c_unit, Pass* pass) { + // Unused parameters for the moment. + UNUSED(c_unit); + UNUSED(pass); +} + +void PassDriver::DispatchPass(CompilationUnit* c_unit, Pass* curPass) { + DataflowIterator* iterator = 0; + + LOG(DEBUG) << "Dispatching " << curPass->GetName(); + + MIRGraph* mir_graph = c_unit->mir_graph.get(); + ArenaAllocator *arena = &(c_unit->arena); + + // Let us start by getting the right iterator. + DataFlowAnalysisMode mode = curPass->GetTraversal(); + + switch (mode) { + case kPreOrderDFSTraversal: + iterator = new (arena) PreOrderDfsIterator(mir_graph); + break; + case kRepeatingPreOrderDFSTraversal: + iterator = new (arena) RepeatingPreOrderDfsIterator(mir_graph); + break; + case kRepeatingPostOrderDFSTraversal: + iterator = new (arena) RepeatingPostOrderDfsIterator(mir_graph); + break; + case kReversePostOrderDFSTraversal: + iterator = new (arena) ReversePostOrderDfsIterator(mir_graph); + break; + case kRepeatingReversePostOrderDFSTraversal: + iterator = new (arena) RepeatingReversePostOrderDfsIterator(mir_graph); + break; + case kPostOrderDOMTraversal: + iterator = new (arena) PostOrderDOMIterator(mir_graph); + break; + case kAllNodes: + iterator = new (arena) AllNodesIterator(mir_graph); + break; + default: + LOG(DEBUG) << "Iterator mode not handled in dispatcher: " << mode; + return; + } + + // Paranoid: Check the iterator before walking the BasicBlocks. + assert(iterator != 0); + + bool change = false; + for (BasicBlock *bb = iterator->Next(change); bb != 0; bb = iterator->Next(change)) { + change = curPass->WalkBasicBlocks(c_unit, bb); + } +} + +void PassDriver::ApplyPass(CompilationUnit* c_unit, Pass* curPass) { + curPass->Start(c_unit); + DispatchPass(c_unit, curPass); + curPass->End(c_unit); +} + +bool PassDriver::RunPass(CompilationUnit* c_unit, Pass* curPass, bool time_split) { + // Paranoid: c_unit or curPass cannot be 0, and the pass should have a name. + if (c_unit == 0 || curPass == 0 || (strcmp(curPass->GetName(), "") == 0)) { + return false; + } + + // Do we perform a time split + if (time_split == true) { + std::string name = "MIROpt:"; + name += curPass->GetName(); + c_unit->NewTimingSplit(name.c_str()); + } + + // Check the pass gate first. + bool shouldApplyPass = curPass->Gate(c_unit); + + if (shouldApplyPass == true) { + // Applying the pass: first start, doWork, and end calls. + ApplyPass(c_unit, curPass); + + // Clean up if need be. + HandlePassFlag(c_unit, curPass); + + // Do we want to log it? + if ((c_unit->enable_debug& (1 << kDebugDumpCFG)) != 0) { + // Do we have a pass folder? + const std::string& passFolder = curPass->GetDumpCFGFolder(); + + if (passFolder != "") { + // Create directory prefix. + std::string prefix = GetDumpCFGFolder(); + prefix += passFolder; + prefix += "/"; + + c_unit->mir_graph->DumpCFG(prefix.c_str(), false); + } + } + } + + // If the pass gate passed, we can declare success. + return shouldApplyPass; +} + +bool PassDriver::RunPass(CompilationUnit* c_unit, const std::string& pass_name) { + // Paranoid: c_unit cannot be 0 and we need a pass name. + if (c_unit == 0 || pass_name == "") { + return false; + } + + Pass* curPass = GetPass(pass_name); + + if (curPass != 0) { + return RunPass(c_unit, curPass); + } + + // Return false, we did not find the pass. + return false; +} + +void PassDriver::Launch() { + for (std::list<Pass* >::iterator it = pass_list_.begin(); it != pass_list_.end(); it++) { + Pass* curPass = *it; + RunPass(cu_, curPass, true); + } +} + +void PassDriver::PrintPassNames() const { + LOG(INFO) << "Loop Passes are:"; + + for (std::list<Pass* >::const_iterator it = pass_list_.begin(); it != pass_list_.end(); it++) { + const Pass* curPass = *it; + LOG(INFO) << "\t-" << curPass->GetName(); + } +} + +Pass* PassDriver::GetPass(const std::string& name) const { + SafeMap<std::string, Pass*>::const_iterator it = pass_map_.find(name); + + if (it != pass_map_.end()) { + return it->second; + } + + return 0; +} + +} // namespace art |