diff options
author | Jean Christophe Beyler <jean.christophe.beyler@intel.com> | 2014-05-06 20:36:55 -0700 |
---|---|---|
committer | Vladimir Marko <vmarko@google.com> | 2014-05-30 10:15:48 +0100 |
commit | 2469e60e6ff08c2a0b4cd1e209246c5d91027679 (patch) | |
tree | 37b2f537fca7ba56cb787913557ee12d6e533d55 /compiler | |
parent | 29b53d3d715b1ec19349e8cbf7c5e4ff529bd5fe (diff) | |
download | art-2469e60e6ff08c2a0b4cd1e209246c5d91027679.zip art-2469e60e6ff08c2a0b4cd1e209246c5d91027679.tar.gz art-2469e60e6ff08c2a0b4cd1e209246c5d91027679.tar.bz2 |
ART: Setting up cleanup
- Moved code around to actually have the clean-up code in a PassDriver format.
This allows us to better control what is being called after an optimization
It also allows the use of a centralized pass system for both optimizations
and cleanup.
Change-Id: I9d21e9bb9ee663739722f440d82adf04f73e380c
Signed-off-by: Jean Christophe Beyler <jean.christophe.beyler@intel.com>
Signed-off-by: Razvan A Lupusoru <razvan.a.lupusoru@intel.com>
Signed-off-by: Yixin Shou <yixin.shou@intel.com>
Signed-off-by: Chao-ying Fu <chao-ying.fu@intel.com>
Signed-off-by: Udayan Banerji <udayan.banerji@intel.com>
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/Android.mk | 4 | ||||
-rw-r--r-- | compiler/dex/bb_optimizations.cc | 90 | ||||
-rw-r--r-- | compiler/dex/bb_optimizations.h | 68 | ||||
-rw-r--r-- | compiler/dex/frontend.cc | 6 | ||||
-rw-r--r-- | compiler/dex/mir_dataflow.cc | 2 | ||||
-rw-r--r-- | compiler/dex/mir_graph.cc | 41 | ||||
-rw-r--r-- | compiler/dex/mir_graph.h | 16 | ||||
-rw-r--r-- | compiler/dex/mir_optimization_test.cc | 2 | ||||
-rw-r--r-- | compiler/dex/pass_driver_me.cc | 208 | ||||
-rw-r--r-- | compiler/dex/pass_driver_me.h | 147 | ||||
-rw-r--r-- | compiler/dex/pass_driver_me_opts.cc | 88 | ||||
-rw-r--r-- | compiler/dex/pass_driver_me_opts.h | 44 | ||||
-rw-r--r-- | compiler/dex/pass_driver_me_post_opt.cc | 75 | ||||
-rw-r--r-- | compiler/dex/pass_driver_me_post_opt.h | 39 | ||||
-rw-r--r-- | compiler/dex/pass_me.h | 5 | ||||
-rw-r--r-- | compiler/dex/post_opt_passes.cc | 108 | ||||
-rw-r--r-- | compiler/dex/post_opt_passes.h | 284 | ||||
-rw-r--r-- | compiler/dex/ssa_transformation.cc | 4 |
18 files changed, 824 insertions, 407 deletions
diff --git a/compiler/Android.mk b/compiler/Android.mk index f297213..3bed01d 100644 --- a/compiler/Android.mk +++ b/compiler/Android.mk @@ -60,7 +60,9 @@ LIBART_COMPILER_SRC_FILES := \ dex/mir_method_info.cc \ dex/mir_optimization.cc \ dex/bb_optimizations.cc \ - dex/pass_driver_me.cc \ + dex/post_opt_passes.cc \ + dex/pass_driver_me_opts.cc \ + dex/pass_driver_me_post_opt.cc \ dex/frontend.cc \ dex/mir_graph.cc \ dex/mir_analysis.cc \ diff --git a/compiler/dex/bb_optimizations.cc b/compiler/dex/bb_optimizations.cc index 8b5eba0..06e259a 100644 --- a/compiler/dex/bb_optimizations.cc +++ b/compiler/dex/bb_optimizations.cc @@ -26,83 +26,11 @@ namespace art { bool CodeLayout::Worker(const PassDataHolder* data) const { DCHECK(data != nullptr); const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data); - CompilationUnit* cUnit = pass_me_data_holder->c_unit; - DCHECK(cUnit != nullptr); + CompilationUnit* c_unit = pass_me_data_holder->c_unit; + DCHECK(c_unit != nullptr); BasicBlock* bb = pass_me_data_holder->bb; DCHECK(bb != nullptr); - cUnit->mir_graph->LayoutBlocks(bb); - // No need of repeating, so just return false. - return false; -} - -/* - * SSATransformation pass implementation start. - */ -void SSATransformation::Start(const PassDataHolder* data) const { - DCHECK(data != nullptr); - CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit; - DCHECK(cUnit != nullptr); - cUnit->mir_graph->SSATransformationStart(); -} - -bool SSATransformation::Worker(const PassDataHolder* data) const { - DCHECK(data != nullptr); - const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data); - CompilationUnit* cUnit = pass_me_data_holder->c_unit; - DCHECK(cUnit != nullptr); - BasicBlock* bb = pass_me_data_holder->bb; - DCHECK(bb != nullptr); - cUnit->mir_graph->InsertPhiNodeOperands(bb); - // No need of repeating, so just return false. - return false; -} - -void SSATransformation::End(const PassDataHolder* data) const { - DCHECK(data != nullptr); - CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit; - DCHECK(cUnit != nullptr); - cUnit->mir_graph->SSATransformationEnd(); -} - -/* - * ConstantPropagation pass implementation start - */ -bool ConstantPropagation::Worker(const PassDataHolder* data) const { - DCHECK(data != nullptr); - const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data); - CompilationUnit* cUnit = pass_me_data_holder->c_unit; - DCHECK(cUnit != nullptr); - BasicBlock* bb = pass_me_data_holder->bb; - DCHECK(bb != nullptr); - cUnit->mir_graph->DoConstantPropagation(bb); - // No need of repeating, so just return false. - return false; -} - -/* - * MethodUseCount pass implementation start. - */ -bool MethodUseCount::Gate(const PassDataHolder* data) const { - DCHECK(data != nullptr); - CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit; - DCHECK(cUnit != nullptr); - // First initialize the data. - cUnit->mir_graph->InitializeMethodUses(); - - // Now check if the pass is to be ignored. - bool res = ((cUnit->disable_opt & (1 << kPromoteRegs)) == 0); - - return res; -} - -bool MethodUseCount::Worker(const PassDataHolder* data) const { - DCHECK(data != nullptr); - const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data); - CompilationUnit* cUnit = pass_me_data_holder->c_unit; - DCHECK(cUnit != nullptr); - BasicBlock* bb = pass_me_data_holder->bb; - DCHECK(bb != nullptr); - cUnit->mir_graph->CountUses(bb); + c_unit->mir_graph->LayoutBlocks(bb); // No need of repeating, so just return false. return false; } @@ -113,11 +41,11 @@ bool MethodUseCount::Worker(const PassDataHolder* data) const { bool BBCombine::Worker(const PassDataHolder* data) const { DCHECK(data != nullptr); const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data); - CompilationUnit* cUnit = pass_me_data_holder->c_unit; - DCHECK(cUnit != nullptr); + CompilationUnit* c_unit = pass_me_data_holder->c_unit; + DCHECK(c_unit != nullptr); BasicBlock* bb = pass_me_data_holder->bb; DCHECK(bb != nullptr); - cUnit->mir_graph->CombineBlocks(bb); + c_unit->mir_graph->CombineBlocks(bb); // No need of repeating, so just return false. return false; @@ -128,15 +56,15 @@ bool BBCombine::Worker(const PassDataHolder* data) const { */ void BBOptimizations::Start(const PassDataHolder* data) const { DCHECK(data != nullptr); - CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit; - DCHECK(cUnit != nullptr); + CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; + DCHECK(c_unit != nullptr); /* * This pass has a different ordering depEnding on the suppress exception, * so do the pass here for now: * - Later, the Start should just change the ordering and we can move the extended * creation into the pass driver's main job with a new iterator */ - cUnit->mir_graph->BasicBlockOptimization(); + c_unit->mir_graph->BasicBlockOptimization(); } } // namespace art diff --git a/compiler/dex/bb_optimizations.h b/compiler/dex/bb_optimizations.h index 3a529f2..0094790 100644 --- a/compiler/dex/bb_optimizations.h +++ b/compiler/dex/bb_optimizations.h @@ -119,7 +119,7 @@ class CallInlining : public PassME { */ class CodeLayout : public PassME { public: - CodeLayout() : PassME("CodeLayout", "2_post_layout_cfg") { + CodeLayout() : PassME("CodeLayout", kAllNodes, kOptimizationBasicBlockChange, "2_post_layout_cfg") { } void Start(const PassDataHolder* data) const { @@ -133,72 +133,6 @@ class CodeLayout : public PassME { }; /** - * @class SSATransformation - * @brief Perform an SSA representation pass on the CompilationUnit. - */ -class SSATransformation : public PassME { - public: - SSATransformation() : PassME("SSATransformation", kPreOrderDFSTraversal, "3_post_ssa_cfg") { - } - - bool Worker(const PassDataHolder* data) const; - - void Start(const PassDataHolder* data) const; - - void End(const PassDataHolder* data) const; -}; - -/** - * @class ConstantPropagation - * @brief Perform a constant propagation pass. - */ -class ConstantPropagation : public PassME { - public: - ConstantPropagation() : PassME("ConstantPropagation") { - } - - bool Worker(const PassDataHolder* data) const; - - void Start(const PassDataHolder* data) const { - DCHECK(data != nullptr); - CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit; - DCHECK(cUnit != nullptr); - cUnit->mir_graph->InitializeConstantPropagation(); - } -}; - -/** - * @class InitRegLocations - * @brief Initialize Register Locations. - */ -class InitRegLocations : public PassME { - public: - InitRegLocations() : PassME("InitRegLocation", kNoNodes) { - } - - void Start(const PassDataHolder* data) const { - DCHECK(data != nullptr); - CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit; - DCHECK(cUnit != nullptr); - cUnit->mir_graph->InitRegLocations(); - } -}; - -/** - * @class MethodUseCount - * @brief Count the register uses of the method - */ -class MethodUseCount : public PassME { - public: - MethodUseCount() : PassME("UseCount") { - } - - bool Worker(const PassDataHolder* data) const; - - bool Gate(const PassDataHolder* data) const; -}; - -/** * @class NullCheckEliminationAndTypeInference * @brief Null check elimination and type inference. */ diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc index 1d4a9bb..1570c3a 100644 --- a/compiler/dex/frontend.cc +++ b/compiler/dex/frontend.cc @@ -21,7 +21,7 @@ #include "dataflow_iterator-inl.h" #include "leb128.h" #include "mirror/object.h" -#include "pass_driver_me.h" +#include "pass_driver_me_opts.h" #include "runtime.h" #include "base/logging.h" #include "base/timing_logger.h" @@ -750,7 +750,7 @@ static bool CanCompileMethod(uint32_t method_idx, const DexFile& dex_file, } for (int idx = 0; idx < cu.mir_graph->GetNumBlocks(); idx++) { - BasicBlock *bb = cu.mir_graph->GetBasicBlock(idx); + BasicBlock* bb = cu.mir_graph->GetBasicBlock(idx); if (bb == NULL) continue; if (bb->block_type == kDead) continue; for (MIR* mir = bb->first_mir_insn; mir != nullptr; mir = mir->next) { @@ -926,7 +926,7 @@ static CompiledMethod* CompileMethod(CompilerDriver& driver, } /* Create the pass driver and launch it */ - PassDriverME pass_driver(&cu); + PassDriverMEOpts pass_driver(&cu); pass_driver.Launch(); if (cu.enable_debug & (1 << kDebugDumpCheckStats)) { diff --git a/compiler/dex/mir_dataflow.cc b/compiler/dex/mir_dataflow.cc index 47b233b..5ff6274 100644 --- a/compiler/dex/mir_dataflow.cc +++ b/compiler/dex/mir_dataflow.cc @@ -1282,7 +1282,7 @@ bool MIRGraph::VerifyPredInfo(BasicBlock* bb) { GrowableArray<BasicBlockId>::Iterator iter(bb->predecessors); while (true) { - BasicBlock *pred_bb = GetBasicBlock(iter.Next()); + BasicBlock* pred_bb = GetBasicBlock(iter.Next()); if (!pred_bb) break; bool found = false; if (pred_bb->taken == bb->id) { diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc index 0fffa01..99dd50a 100644 --- a/compiler/dex/mir_graph.cc +++ b/compiler/dex/mir_graph.cc @@ -26,6 +26,7 @@ #include "dex/quick/dex_file_to_method_inliner_map.h" #include "dex/quick/dex_file_method_inliner.h" #include "leb128.h" +#include "pass_driver_me_post_opt.h" namespace art { @@ -353,7 +354,7 @@ BasicBlock* MIRGraph::ProcessCanBranch(BasicBlock* cur_block, MIR* insn, DexOffs /* Always terminate the current block for conditional branches */ if (flags & Instruction::kContinue) { - BasicBlock *fallthrough_block = FindBlock(cur_offset + width, + BasicBlock* fallthrough_block = FindBlock(cur_offset + width, /* * If the method is processed * in sequential order from the @@ -541,7 +542,7 @@ BasicBlock* MIRGraph::ProcessCanThrow(BasicBlock* cur_block, MIR* insn, DexOffse * Note also that the dex_pc_to_block_map_ entry for the potentially * throwing instruction will refer to the original basic block. */ - BasicBlock *new_block = NewMemBB(kDalvikByteCode, num_blocks_++); + BasicBlock* new_block = NewMemBB(kDalvikByteCode, num_blocks_++); block_list_.Insert(new_block); new_block->start_offset = insn->offset; cur_block->fall_through = new_block->id; @@ -724,7 +725,7 @@ void MIRGraph::InlineMethod(const DexFile::CodeItem* code_item, uint32_t access_ } } current_offset_ += width; - BasicBlock *next_block = FindBlock(current_offset_, /* split */ false, /* create */ + BasicBlock* next_block = FindBlock(current_offset_, /* split */ false, /* create */ false, /* immed_pred_block_p */ NULL); if (next_block) { /* @@ -1418,25 +1419,6 @@ void MIRGraph::SSATransformationStart() { temp_bit_vector_ = new (temp_scoped_alloc_.get()) ArenaBitVector( temp_scoped_alloc_.get(), temp_bit_vector_size_, false, kBitMapRegisterV); - /* Compute the DFS order */ - ComputeDFSOrders(); - - /* Compute the dominator info */ - ComputeDominators(); - - /* Allocate data structures in preparation for SSA conversion */ - CompilerInitializeSSAConversion(); - - /* Find out the "Dalvik reg def x block" relation */ - ComputeDefBlockMatrix(); - - /* Insert phi nodes to dominance frontiers for all variables */ - InsertPhiNodes(); - - /* Rename register names by local defs and phi nodes */ - ClearAllVisitedFlags(); - DoDFSPreOrderSSARename(GetEntryBlock()); - // Update the maximum number of reachable blocks. max_num_reachable_blocks_ = num_reachable_blocks_; } @@ -1454,7 +1436,7 @@ void MIRGraph::SSATransformationEnd() { } void MIRGraph::ComputeTopologicalSortOrder() { - std::queue<BasicBlock *> q; + std::queue<BasicBlock*> q; std::map<int, int> visited_cnt_values; // Clear the nodes. @@ -1510,7 +1492,7 @@ void MIRGraph::ComputeTopologicalSortOrder() { while (q.size() > 0) { // Get top. - BasicBlock *bb = q.front(); + BasicBlock* bb = q.front(); q.pop(); DCHECK_EQ(bb->hidden, false); @@ -1528,7 +1510,7 @@ void MIRGraph::ComputeTopologicalSortOrder() { // Reduce visitedCnt for all the successors and add into the queue ones with visitedCnt equals to zero. ChildBlockIterator succIter(bb, this); - BasicBlock *successor = succIter.Next(); + BasicBlock* successor = succIter.Next(); while (successor != nullptr) { // one more predecessor was visited. visited_cnt_values[successor->id]--; @@ -1914,4 +1896,13 @@ BasicBlock* MIRGraph::CreateNewBB(BBType block_type) { return res; } +void MIRGraph::CalculateBasicBlockInformation() { + PassDriverMEPostOpt driver(cu_); + driver.Launch(); +} + +void MIRGraph::InitializeBasicBlockData() { + num_blocks_ = block_list_.Size(); +} + } // namespace art diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h index 3655125..b04c16e 100644 --- a/compiler/dex/mir_graph.h +++ b/compiler/dex/mir_graph.h @@ -924,7 +924,7 @@ class MIRGraph { void VerifyDataflow(); void CheckForDominanceFrontier(BasicBlock* dom_bb, const BasicBlock* succ_bb); void EliminateNullChecksAndInferTypesStart(); - bool EliminateNullChecksAndInferTypes(BasicBlock *bb); + bool EliminateNullChecksAndInferTypes(BasicBlock* bb); void EliminateNullChecksAndInferTypesEnd(); bool EliminateClassInitChecksGate(); bool EliminateClassInitChecks(BasicBlock* bb); @@ -1030,6 +1030,14 @@ class MIRGraph { void AllocateSSAUseData(MIR *mir, int num_uses); void AllocateSSADefData(MIR *mir, int num_defs); + void CalculateBasicBlockInformation(); + void InitializeBasicBlockData(); + void ComputeDFSOrders(); + void ComputeDefBlockMatrix(); + void ComputeDominators(); + void CompilerInitializeSSAConversion(); + void InsertPhiNodes(); + void DoDFSPreOrderSSARename(BasicBlock* block); /* * IsDebugBuild sanity check: keep track of the Dex PCs for catch entries so that later on @@ -1046,7 +1054,6 @@ class MIRGraph { void HandleSSADef(int* defs, int dalvik_reg, int reg_index); bool InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed); - void ComputeDFSOrders(); protected: int FindCommonParent(int block1, int block2); @@ -1055,7 +1062,6 @@ class MIRGraph { void HandleLiveInUse(ArenaBitVector* use_v, ArenaBitVector* def_v, ArenaBitVector* live_in_v, int dalvik_reg_id); void HandleDef(ArenaBitVector* def_v, int dalvik_reg_id); - void CompilerInitializeSSAConversion(); bool DoSSAConversion(BasicBlock* bb); bool InvokeUsesMethodStar(MIR* mir); int ParseInsn(const uint16_t* code_ptr, MIR::DecodedInstruction* decoded_instruction); @@ -1082,11 +1088,7 @@ class MIRGraph { BasicBlock* NextUnvisitedSuccessor(BasicBlock* bb); void MarkPreOrder(BasicBlock* bb); void RecordDFSOrders(BasicBlock* bb); - void ComputeDefBlockMatrix(); void ComputeDomPostOrderTraversal(BasicBlock* bb); - void ComputeDominators(); - void InsertPhiNodes(); - void DoDFSPreOrderSSARename(BasicBlock* block); void SetConstant(int32_t ssa_reg, int value); void SetConstantWide(int ssa_reg, int64_t value); int GetSSAUseCount(int s_reg); diff --git a/compiler/dex/mir_optimization_test.cc b/compiler/dex/mir_optimization_test.cc index 86092b6..69c394f 100644 --- a/compiler/dex/mir_optimization_test.cc +++ b/compiler/dex/mir_optimization_test.cc @@ -193,7 +193,7 @@ class ClassInitCheckEliminationTest : public testing::Test { ASSERT_TRUE(gate_result); RepeatingPreOrderDfsIterator iterator(cu_.mir_graph.get()); bool change = false; - for (BasicBlock *bb = iterator.Next(change); bb != 0; bb = iterator.Next(change)) { + for (BasicBlock* bb = iterator.Next(change); bb != nullptr; bb = iterator.Next(change)) { change = cu_.mir_graph->EliminateClassInitChecks(bb); } cu_.mir_graph->EliminateClassInitChecksEnd(); diff --git a/compiler/dex/pass_driver_me.cc b/compiler/dex/pass_driver_me.cc deleted file mode 100644 index e6d90e0..0000000 --- a/compiler/dex/pass_driver_me.cc +++ /dev/null @@ -1,208 +0,0 @@ -/* - * 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 "base/macros.h" -#include "bb_optimizations.h" -#include "compiler_internals.h" -#include "dataflow_iterator.h" -#include "dataflow_iterator-inl.h" -#include "pass_driver_me.h" - -namespace art { - -namespace { // anonymous namespace - -void DoWalkBasicBlocks(PassMEDataHolder* data, const PassME* pass, DataflowIterator* iterator) { - // Paranoid: Check the iterator before walking the BasicBlocks. - DCHECK(iterator != nullptr); - bool change = false; - for (BasicBlock *bb = iterator->Next(change); bb != 0; bb = iterator->Next(change)) { - data->bb = bb; - change = pass->Worker(data); - } -} - -template <typename Iterator> -inline void DoWalkBasicBlocks(PassMEDataHolder* data, const PassME* pass) { - DCHECK(data != nullptr); - CompilationUnit* c_unit = data->c_unit; - DCHECK(c_unit != nullptr); - Iterator iterator(c_unit->mir_graph.get()); - DoWalkBasicBlocks(data, pass, &iterator); -} -} // anonymous namespace - -/* - * Create the pass list. These passes are immutable and are shared across the threads. - * - * 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. - */ -// The initial list of passes to be used by the PassDriveME. -template<> -const Pass* const PassDriver<PassDriverME>::g_passes[] = { - GetPassInstance<CacheFieldLoweringInfo>(), - GetPassInstance<CacheMethodLoweringInfo>(), - GetPassInstance<CallInlining>(), - GetPassInstance<CodeLayout>(), - GetPassInstance<SSATransformation>(), - GetPassInstance<ConstantPropagation>(), - GetPassInstance<InitRegLocations>(), - GetPassInstance<MethodUseCount>(), - GetPassInstance<NullCheckEliminationAndTypeInference>(), - GetPassInstance<ClassInitCheckElimination>(), - GetPassInstance<BBCombine>(), - GetPassInstance<BBOptimizations>(), -}; - -// The number of the passes in the initial list of Passes (g_passes). -template<> -uint16_t const PassDriver<PassDriverME>::g_passes_size = arraysize(PassDriver<PassDriverME>::g_passes); - -// The default pass list is used by the PassDriverME instance of PassDriver to initialize pass_list_. -template<> -std::vector<const Pass*> PassDriver<PassDriverME>::g_default_pass_list(PassDriver<PassDriverME>::g_passes, PassDriver<PassDriverME>::g_passes + PassDriver<PassDriverME>::g_passes_size); - -// By default, do not have a dump pass list. -template<> -std::string PassDriver<PassDriverME>::dump_pass_list_ = std::string(); - -// By default, do not have a print pass list. -template<> -std::string PassDriver<PassDriverME>::print_pass_list_ = std::string(); - -// By default, we do not print the pass' information. -template<> -bool PassDriver<PassDriverME>::default_print_passes_ = false; - - -PassDriverME::PassDriverME(CompilationUnit* cu) - : PassDriver(), pass_me_data_holder_(), dump_cfg_folder_("/sdcard/") { - pass_me_data_holder_.bb = nullptr; - pass_me_data_holder_.c_unit = cu; -} - -PassDriverME::~PassDriverME() { -} - -void PassDriverME::DispatchPass(const Pass* pass) { - VLOG(compiler) << "Dispatching " << pass->GetName(); - const PassME* me_pass = down_cast<const PassME*>(pass); - - DataFlowAnalysisMode mode = me_pass->GetTraversal(); - - switch (mode) { - case kPreOrderDFSTraversal: - DoWalkBasicBlocks<PreOrderDfsIterator>(&pass_me_data_holder_, me_pass); - break; - case kRepeatingPreOrderDFSTraversal: - DoWalkBasicBlocks<RepeatingPreOrderDfsIterator>(&pass_me_data_holder_, me_pass); - break; - case kRepeatingPostOrderDFSTraversal: - DoWalkBasicBlocks<RepeatingPostOrderDfsIterator>(&pass_me_data_holder_, me_pass); - break; - case kReversePostOrderDFSTraversal: - DoWalkBasicBlocks<ReversePostOrderDfsIterator>(&pass_me_data_holder_, me_pass); - break; - case kRepeatingReversePostOrderDFSTraversal: - DoWalkBasicBlocks<RepeatingReversePostOrderDfsIterator>(&pass_me_data_holder_, me_pass); - break; - case kPostOrderDOMTraversal: - DoWalkBasicBlocks<PostOrderDOMIterator>(&pass_me_data_holder_, me_pass); - break; - case kAllNodes: - DoWalkBasicBlocks<AllNodesIterator>(&pass_me_data_holder_, me_pass); - break; - case kNoNodes: - break; - default: - LOG(FATAL) << "Iterator mode not handled in dispatcher: " << mode; - break; - } -} - -bool PassDriverME::RunPass(const Pass* pass, bool time_split) { - // Paranoid: c_unit and pass cannot be nullptr, and the pass should have a name - DCHECK(pass != nullptr); - DCHECK(pass->GetName() != nullptr && pass->GetName()[0] != 0); - CompilationUnit* c_unit = pass_me_data_holder_.c_unit; - DCHECK(c_unit != nullptr); - - // Do we perform a time split - if (time_split) { - c_unit->NewTimingSplit(pass->GetName()); - } - - // Check the pass gate first. - bool should_apply_pass = pass->Gate(&pass_me_data_holder_); - - if (should_apply_pass) { - bool old_print_pass = c_unit->print_pass; - - c_unit->print_pass = default_print_passes_; - - const char* print_pass_list = print_pass_list_.c_str(); - - if (print_pass_list != nullptr && strstr(print_pass_list, pass->GetName()) != nullptr) { - c_unit->print_pass = true; - } - - // Applying the pass: first start, doWork, and end calls. - ApplyPass(&pass_me_data_holder_, pass); - - // Do we want to log it? - bool should_dump = ((c_unit->enable_debug & (1 << kDebugDumpCFG)) != 0); - - const char* dump_pass_list = dump_pass_list_.c_str(); - - if (dump_pass_list != nullptr) { - bool found = strstr(dump_pass_list, pass->GetName()); - should_dump = (should_dump || found); - } - - if (should_dump) { - // Do we want to log it? - if ((c_unit->enable_debug& (1 << kDebugDumpCFG)) != 0) { - // Do we have a pass folder? - const PassME* me_pass = (down_cast<const PassME*>(pass)); - const char* passFolder = me_pass->GetDumpCFGFolder(); - DCHECK(passFolder != nullptr); - - if (passFolder[0] != 0) { - // Create directory prefix. - std::string prefix = GetDumpCFGFolder(); - prefix += passFolder; - prefix += "/"; - - c_unit->mir_graph->DumpCFG(prefix.c_str(), false); - } - } - } - - c_unit->print_pass = old_print_pass; - } - - // If the pass gate passed, we can declare success. - return should_apply_pass; -} - -const char* PassDriverME::GetDumpCFGFolder() const { - return dump_cfg_folder_; -} - - -} // namespace art diff --git a/compiler/dex/pass_driver_me.h b/compiler/dex/pass_driver_me.h index 0142934..7d76fb8 100644 --- a/compiler/dex/pass_driver_me.h +++ b/compiler/dex/pass_driver_me.h @@ -18,28 +18,155 @@ #define ART_COMPILER_DEX_PASS_DRIVER_ME_H_ #include "bb_optimizations.h" +#include "dataflow_iterator.h" +#include "dataflow_iterator-inl.h" #include "pass_driver.h" #include "pass_me.h" namespace art { -class PassDriverME: public PassDriver<PassDriverME> { +template <typename PassDriverType> +class PassDriverME: public PassDriver<PassDriverType> { public: - explicit PassDriverME(CompilationUnit* cu); - ~PassDriverME(); - /** - * @brief Dispatch a patch: walk the BasicBlocks depending on the traversal mode - */ - void DispatchPass(const Pass* pass); - bool RunPass(const Pass* pass, bool time_split = false); - const char* GetDumpCFGFolder() const; + explicit PassDriverME(CompilationUnit* cu) + : pass_me_data_holder_(), dump_cfg_folder_("/sdcard/") { + pass_me_data_holder_.bb = nullptr; + pass_me_data_holder_.c_unit = cu; + } + + ~PassDriverME() { + } + + void DispatchPass(const Pass* pass) { + VLOG(compiler) << "Dispatching " << pass->GetName(); + const PassME* me_pass = down_cast<const PassME*>(pass); + + DataFlowAnalysisMode mode = me_pass->GetTraversal(); + + switch (mode) { + case kPreOrderDFSTraversal: + DoWalkBasicBlocks<PreOrderDfsIterator>(&pass_me_data_holder_, me_pass); + break; + case kRepeatingPreOrderDFSTraversal: + DoWalkBasicBlocks<RepeatingPreOrderDfsIterator>(&pass_me_data_holder_, me_pass); + break; + case kRepeatingPostOrderDFSTraversal: + DoWalkBasicBlocks<RepeatingPostOrderDfsIterator>(&pass_me_data_holder_, me_pass); + break; + case kReversePostOrderDFSTraversal: + DoWalkBasicBlocks<ReversePostOrderDfsIterator>(&pass_me_data_holder_, me_pass); + break; + case kRepeatingReversePostOrderDFSTraversal: + DoWalkBasicBlocks<RepeatingReversePostOrderDfsIterator>(&pass_me_data_holder_, me_pass); + break; + case kPostOrderDOMTraversal: + DoWalkBasicBlocks<PostOrderDOMIterator>(&pass_me_data_holder_, me_pass); + break; + case kAllNodes: + DoWalkBasicBlocks<AllNodesIterator>(&pass_me_data_holder_, me_pass); + break; + case kNoNodes: + break; + default: + LOG(FATAL) << "Iterator mode not handled in dispatcher: " << mode; + break; + } + } + + bool RunPass(const Pass* pass, bool time_split) { + // Paranoid: c_unit and pass cannot be nullptr, and the pass should have a name + DCHECK(pass != nullptr); + DCHECK(pass->GetName() != nullptr && pass->GetName()[0] != 0); + CompilationUnit* c_unit = pass_me_data_holder_.c_unit; + DCHECK(c_unit != nullptr); + + // Do we perform a time split + if (time_split) { + c_unit->NewTimingSplit(pass->GetName()); + } + + // Check the pass gate first. + bool should_apply_pass = pass->Gate(&pass_me_data_holder_); + if (should_apply_pass) { + bool old_print_pass = c_unit->print_pass; + + c_unit->print_pass = PassDriver<PassDriverType>::default_print_passes_; + + const char* print_pass_list = PassDriver<PassDriverType>::print_pass_list_.c_str(); + + if (print_pass_list != nullptr && strstr(print_pass_list, pass->GetName()) != nullptr) { + c_unit->print_pass = true; + } + + // Applying the pass: first start, doWork, and end calls. + this->ApplyPass(&pass_me_data_holder_, pass); + + bool should_dump = ((c_unit->enable_debug & (1 << kDebugDumpCFG)) != 0); + + const char* dump_pass_list = PassDriver<PassDriverType>::dump_pass_list_.c_str(); + + if (dump_pass_list != nullptr) { + bool found = strstr(dump_pass_list, pass->GetName()); + should_dump = (should_dump || found); + } + + if (should_dump) { + // Do we want to log it? + if ((c_unit->enable_debug& (1 << kDebugDumpCFG)) != 0) { + // Do we have a pass folder? + const PassME* me_pass = (down_cast<const PassME*>(pass)); + const char* passFolder = me_pass->GetDumpCFGFolder(); + DCHECK(passFolder != nullptr); + + if (passFolder[0] != 0) { + // Create directory prefix. + std::string prefix = GetDumpCFGFolder(); + prefix += passFolder; + prefix += "/"; + + c_unit->mir_graph->DumpCFG(prefix.c_str(), false); + } + } + } + + c_unit->print_pass = old_print_pass; + } + + // If the pass gate passed, we can declare success. + return should_apply_pass; + } + + const char* GetDumpCFGFolder() const { + return dump_cfg_folder_; + } + protected: /** @brief The data holder that contains data needed for the PassDriverME. */ PassMEDataHolder pass_me_data_holder_; /** @brief Dump CFG base folder: where is the base folder for dumping CFGs. */ const char* dump_cfg_folder_; -}; + static void DoWalkBasicBlocks(PassMEDataHolder* data, const PassME* pass, + DataflowIterator* iterator) { + // Paranoid: Check the iterator before walking the BasicBlocks. + DCHECK(iterator != nullptr); + bool change = false; + for (BasicBlock* bb = iterator->Next(change); bb != nullptr; bb = iterator->Next(change)) { + data->bb = bb; + change = pass->Worker(data); + } + } + + template <typename Iterator> + inline static void DoWalkBasicBlocks(PassMEDataHolder* data, const PassME* pass) { + DCHECK(data != nullptr); + CompilationUnit* c_unit = data->c_unit; + DCHECK(c_unit != nullptr); + Iterator iterator(c_unit->mir_graph.get()); + DoWalkBasicBlocks(data, pass, &iterator); + } +}; } // namespace art #endif // ART_COMPILER_DEX_PASS_DRIVER_ME_H_ + diff --git a/compiler/dex/pass_driver_me_opts.cc b/compiler/dex/pass_driver_me_opts.cc new file mode 100644 index 0000000..52a2273 --- /dev/null +++ b/compiler/dex/pass_driver_me_opts.cc @@ -0,0 +1,88 @@ +/* + * 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 "base/macros.h" +#include "bb_optimizations.h" +#include "compiler_internals.h" +#include "dataflow_iterator.h" +#include "dataflow_iterator-inl.h" +#include "pass_driver_me_opts.h" + +namespace art { + +/* + * Create the pass list. These passes are immutable and are shared across the threads. + * + * 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. + */ +// The initial list of passes to be used by the PassDriveMEOpts. +template<> +const Pass* const PassDriver<PassDriverMEOpts>::g_passes[] = { + GetPassInstance<CacheFieldLoweringInfo>(), + GetPassInstance<CacheMethodLoweringInfo>(), + GetPassInstance<CallInlining>(), + GetPassInstance<CodeLayout>(), + GetPassInstance<NullCheckEliminationAndTypeInference>(), + GetPassInstance<ClassInitCheckElimination>(), + GetPassInstance<BBCombine>(), + GetPassInstance<BBOptimizations>(), +}; + +// The number of the passes in the initial list of Passes (g_passes). +template<> +uint16_t const PassDriver<PassDriverMEOpts>::g_passes_size = + arraysize(PassDriver<PassDriverMEOpts>::g_passes); + +// The default pass list is used by the PassDriverME instance of PassDriver +// to initialize pass_list_. +template<> +std::vector<const Pass*> PassDriver<PassDriverMEOpts>::g_default_pass_list( + PassDriver<PassDriverMEOpts>::g_passes, + PassDriver<PassDriverMEOpts>::g_passes + + PassDriver<PassDriverMEOpts>::g_passes_size); + +// By default, do not have a dump pass list. +template<> +std::string PassDriver<PassDriverMEOpts>::dump_pass_list_ = std::string(); + +// By default, do not have a print pass list. +template<> +std::string PassDriver<PassDriverMEOpts>::print_pass_list_ = std::string(); + +// By default, we do not print the pass' information. +template<> +bool PassDriver<PassDriverMEOpts>::default_print_passes_ = false; + +void PassDriverMEOpts::ApplyPass(PassDataHolder* data, const Pass* pass) { + // First call the base class' version. + PassDriver::ApplyPass(data, pass); + + const PassME* pass_me = down_cast<const PassME*> (pass); + DCHECK(pass_me != nullptr); + + PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data); + + // Now we care about flags. + if ((pass_me->GetFlag(kOptimizationBasicBlockChange) == true) || + (pass_me->GetFlag(kOptimizationDefUsesChange) == true)) { + CompilationUnit* c_unit = pass_me_data_holder->c_unit; + c_unit->mir_graph.get()->CalculateBasicBlockInformation(); + } +} + +} // namespace art diff --git a/compiler/dex/pass_driver_me_opts.h b/compiler/dex/pass_driver_me_opts.h new file mode 100644 index 0000000..0a5b5ae --- /dev/null +++ b/compiler/dex/pass_driver_me_opts.h @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#ifndef ART_COMPILER_DEX_PASS_DRIVER_ME_OPTS_H_ +#define ART_COMPILER_DEX_PASS_DRIVER_ME_OPTS_H_ + +#include "pass_driver_me.h" + +namespace art { + +// Forward Declarations. +struct CompilationUnit; +class Pass; +class PassDataHolder; + +class PassDriverMEOpts : public PassDriverME<PassDriverMEOpts> { + public: + explicit PassDriverMEOpts(CompilationUnit* cu):PassDriverME<PassDriverMEOpts>(cu) { + } + + ~PassDriverMEOpts() { + } + + /** + * @brief Apply a patch: perform start/work/end functions. + */ + virtual void ApplyPass(PassDataHolder* data, const Pass* pass); +}; + +} // namespace art +#endif // ART_COMPILER_DEX_PASS_DRIVER_ME_OPTS_H_ diff --git a/compiler/dex/pass_driver_me_post_opt.cc b/compiler/dex/pass_driver_me_post_opt.cc new file mode 100644 index 0000000..cb63f41 --- /dev/null +++ b/compiler/dex/pass_driver_me_post_opt.cc @@ -0,0 +1,75 @@ +/* + * 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 "base/macros.h" +#include "post_opt_passes.h" +#include "compiler_internals.h" +#include "pass_driver_me_post_opt.h" + +namespace art { + +/* + * Create the pass list. These passes are immutable and are shared across the threads. + * + * 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. + */ +// The initial list of passes to be used by the PassDriveMEPostOpt. +template<> +const Pass* const PassDriver<PassDriverMEPostOpt>::g_passes[] = { + GetPassInstance<InitializeData>(), + GetPassInstance<ClearPhiInstructions>(), + GetPassInstance<CalculatePredecessors>(), + GetPassInstance<DFSOrders>(), + GetPassInstance<BuildDomination>(), + GetPassInstance<DefBlockMatrix>(), + GetPassInstance<CreatePhiNodes>(), + GetPassInstance<ClearVisitedFlag>(), + GetPassInstance<SSAConversion>(), + GetPassInstance<PhiNodeOperands>(), + GetPassInstance<ConstantPropagation>(), + GetPassInstance<PerformInitRegLocations>(), + GetPassInstance<MethodUseCount>(), + GetPassInstance<FreeData>(), +}; + +// The number of the passes in the initial list of Passes (g_passes). +template<> +uint16_t const PassDriver<PassDriverMEPostOpt>::g_passes_size = + arraysize(PassDriver<PassDriverMEPostOpt>::g_passes); + +// The default pass list is used by the PassDriverME instance of PassDriver +// to initialize pass_list_. +template<> +std::vector<const Pass*> PassDriver<PassDriverMEPostOpt>::g_default_pass_list( + PassDriver<PassDriverMEPostOpt>::g_passes, + PassDriver<PassDriverMEPostOpt>::g_passes + + PassDriver<PassDriverMEPostOpt>::g_passes_size); + +// By default, do not have a dump pass list. +template<> +std::string PassDriver<PassDriverMEPostOpt>::dump_pass_list_ = std::string(); + +// By default, do not have a print pass list. +template<> +std::string PassDriver<PassDriverMEPostOpt>::print_pass_list_ = std::string(); + +// By default, we do not print the pass' information. +template<> +bool PassDriver<PassDriverMEPostOpt>::default_print_passes_ = false; + +} // namespace art diff --git a/compiler/dex/pass_driver_me_post_opt.h b/compiler/dex/pass_driver_me_post_opt.h new file mode 100644 index 0000000..adba363 --- /dev/null +++ b/compiler/dex/pass_driver_me_post_opt.h @@ -0,0 +1,39 @@ +/* + * 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. + */ + +#ifndef ART_COMPILER_DEX_PASS_DRIVER_ME_CLEANUP_H_ +#define ART_COMPILER_DEX_PASS_DRIVER_ME_CLEANUP_H_ + +#include "pass_driver_me.h" + +namespace art { + +// Forward Declarations. +struct CompilationUnit; +class Pass; +class PassDataHolder; + +class PassDriverMEPostOpt : public PassDriverME<PassDriverMEPostOpt> { + public: + explicit PassDriverMEPostOpt(CompilationUnit* cu) : PassDriverME<PassDriverMEPostOpt>(cu) { + } + + ~PassDriverMEPostOpt() { + } +}; + +} // namespace art +#endif // ART_COMPILER_DEX_PASS_DRIVER_ME_CLEANUP_H_ diff --git a/compiler/dex/pass_me.h b/compiler/dex/pass_me.h index 069fb45..9efd5ae 100644 --- a/compiler/dex/pass_me.h +++ b/compiler/dex/pass_me.h @@ -32,6 +32,9 @@ class Pass; * @details Each enum should be a power of 2 to be correctly used. */ enum OptimizationFlag { + kOptimizationBasicBlockChange = 1, /**< @brief Has there been a change to a BasicBlock? */ + kOptimizationDefUsesChange = 2, /**< @brief Has there been a change to a def-use? */ + kLoopStructureChange = 4, /**< @brief Has there been a loop structural change? */ }; // Data holder class. @@ -93,7 +96,7 @@ class PassME: public Pass { /** @brief Type of traversal: determines the order to execute the pass on the BasicBlocks. */ const DataFlowAnalysisMode traversal_type_; - /** @brief Flags for additional directives: used to determine if a particular clean-up is necessary post pass. */ + /** @brief Flags for additional directives: used to determine if a particular post-optimization pass is necessary. */ const unsigned int flags_; /** @brief CFG Dump Folder: what sub-folder to use for dumping the CFGs post pass. */ diff --git a/compiler/dex/post_opt_passes.cc b/compiler/dex/post_opt_passes.cc new file mode 100644 index 0000000..58700a4 --- /dev/null +++ b/compiler/dex/post_opt_passes.cc @@ -0,0 +1,108 @@ +/* + * 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 "post_opt_passes.h" +#include "dataflow_iterator.h" +#include "dataflow_iterator-inl.h" + +namespace art { + +/* + * MethodUseCount pass implementation start. + */ +bool MethodUseCount::Gate(const PassDataHolder* data) const { + DCHECK(data != nullptr); + CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; + DCHECK(c_unit != nullptr); + // First initialize the data. + c_unit->mir_graph->InitializeMethodUses(); + + // Now check if the pass is to be ignored. + bool res = ((c_unit->disable_opt & (1 << kPromoteRegs)) == 0); + + return res; +} + +bool MethodUseCount::Worker(const PassDataHolder* data) const { + DCHECK(data != nullptr); + const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data); + CompilationUnit* c_unit = pass_me_data_holder->c_unit; + DCHECK(c_unit != nullptr); + BasicBlock* bb = pass_me_data_holder->bb; + DCHECK(bb != nullptr); + c_unit->mir_graph->CountUses(bb); + // No need of repeating, so just return false. + return false; +} + + +bool ClearPhiInstructions::Worker(const PassDataHolder* data) const { + DCHECK(data != nullptr); + const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data); + CompilationUnit* c_unit = pass_me_data_holder->c_unit; + DCHECK(c_unit != nullptr); + BasicBlock* bb = pass_me_data_holder->bb; + DCHECK(bb != nullptr); + MIR* mir = bb->first_mir_insn; + + while (mir != nullptr) { + MIR* next = mir->next; + + Instruction::Code opcode = mir->dalvikInsn.opcode; + + if (opcode == static_cast<Instruction::Code> (kMirOpPhi)) { + bb->RemoveMIR(mir); + } + + mir = next; + } + + // We do not care in reporting a change or not in the MIR. + return false; +} + +void CalculatePredecessors::Start(const PassDataHolder* data) const { + DCHECK(data != nullptr); + CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; + DCHECK(c_unit != nullptr); + // First get the MIRGraph here to factorize a bit the code. + MIRGraph *mir_graph = c_unit->mir_graph.get(); + + // First clear all predecessors. + AllNodesIterator first(mir_graph); + for (BasicBlock* bb = first.Next(); bb != nullptr; bb = first.Next()) { + bb->predecessors->Reset(); + } + + // Now calculate all predecessors. + AllNodesIterator second(mir_graph); + for (BasicBlock* bb = second.Next(); bb != nullptr; bb = second.Next()) { + // We only care about non hidden blocks. + if (bb->hidden == true) { + continue; + } + + // Create iterator for visiting children. + ChildBlockIterator child_iter(bb, mir_graph); + + // Now iterate through the children to set the predecessor bits. + for (BasicBlock* child = child_iter.Next(); child != nullptr; child = child_iter.Next()) { + child->predecessors->Insert(bb->id); + } + } +} + +} // namespace art diff --git a/compiler/dex/post_opt_passes.h b/compiler/dex/post_opt_passes.h new file mode 100644 index 0000000..e101fb5 --- /dev/null +++ b/compiler/dex/post_opt_passes.h @@ -0,0 +1,284 @@ +/* + * 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. + */ + +#ifndef ART_COMPILER_DEX_CLEAN_UP_PASSES_H_ +#define ART_COMPILER_DEX_CLEAN_UP_PASSES_H_ + +#include "compiler_internals.h" +#include "pass_me.h" + +namespace art { + +/** + * @class InitializeData + * @brief There is some data that needs to be initialized before performing + * the post optimization passes. + */ +class InitializeData : public PassME { + public: + InitializeData() : PassME("InitializeData") { + } + + void Start(const PassDataHolder* data) const { + // New blocks may have been inserted so the first thing we do is ensure that + // the c_unit's number of blocks matches the actual count of basic blocks. + DCHECK(data != nullptr); + CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; + DCHECK(c_unit != nullptr); + c_unit->mir_graph.get()->InitializeBasicBlockData(); + c_unit->mir_graph.get()->SSATransformationStart(); + } +}; + +/** + * @class MethodUseCount + * @brief Count the register uses of the method + */ +class MethodUseCount : public PassME { + public: + MethodUseCount() : PassME("UseCount") { + } + + bool Worker(const PassDataHolder* data) const; + + bool Gate(const PassDataHolder* data) const; +}; + +/** + * @class ClearPhiInformation + * @brief Clear the PHI nodes from the CFG. + */ +class ClearPhiInstructions : public PassME { + public: + ClearPhiInstructions() : PassME("ClearPhiInstructions") { + } + + bool Worker(const PassDataHolder* data) const; +}; + +/** + * @class CalculatePredecessors + * @brief Calculate the predecessor BitVector of each Basicblock. + */ +class CalculatePredecessors : public PassME { + public: + CalculatePredecessors() : PassME("CalculatePredecessors") { + } + + void Start(const PassDataHolder* data) const; +}; + +/** + * @class DFSOrders + * @brief Compute the DFS order of the MIR graph + */ +class DFSOrders : public PassME { + public: + DFSOrders() : PassME("DFSOrders") { + } + + void Start(const PassDataHolder* data) const { + DCHECK(data != nullptr); + CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; + DCHECK(c_unit != nullptr); + c_unit->mir_graph.get()->ComputeDFSOrders(); + } +}; + +/** + * @class BuildDomination + * @brief Build the domination information of the MIR Graph + */ +class BuildDomination : public PassME { + public: + BuildDomination() : PassME("BuildDomination") { + } + + void Start(const PassDataHolder* data) const { + DCHECK(data != nullptr); + CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; + DCHECK(c_unit != nullptr); + c_unit->mir_graph.get()->ComputeDominators(); + c_unit->mir_graph.get()->CompilerInitializeSSAConversion(); + } + + void End(const PassDataHolder* data) const { + DCHECK(data != nullptr); + CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; + DCHECK(c_unit != nullptr); + // Verify the dataflow information after the pass. + if (c_unit->enable_debug & (1 << kDebugVerifyDataflow)) { + c_unit->mir_graph->VerifyDataflow(); + } + } +}; + +/** + * @class DefBlockMatrix + * @brief Calculate the matrix of definition per basic block + */ +class DefBlockMatrix : public PassME { + public: + DefBlockMatrix() : PassME("DefBlockMatrix") { + } + + void Start(const PassDataHolder* data) const { + DCHECK(data != nullptr); + CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; + DCHECK(c_unit != nullptr); + c_unit->mir_graph.get()->ComputeDefBlockMatrix(); + } +}; + +/** + * @class CreatePhiNodes + * @brief Pass to create the phi nodes after SSA calculation + */ +class CreatePhiNodes : public PassME { + public: + CreatePhiNodes() : PassME("CreatePhiNodes") { + } + + void Start(const PassDataHolder* data) const { + DCHECK(data != nullptr); + CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; + DCHECK(c_unit != nullptr); + c_unit->mir_graph.get()->InsertPhiNodes(); + } +}; + +/** + * @class ClearVisitedFlag + * @brief Pass to clear the visited flag for all basic blocks. + */ + +class ClearVisitedFlag : public PassME { + public: + ClearVisitedFlag() : PassME("ClearVisitedFlag") { + } + + void Start(const PassDataHolder* data) const { + DCHECK(data != nullptr); + CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; + DCHECK(c_unit != nullptr); + c_unit->mir_graph.get()->ClearAllVisitedFlags(); + } +}; + +/** + * @class SSAConversion + * @brief Pass for SSA conversion of MIRs + */ +class SSAConversion : public PassME { + public: + SSAConversion() : PassME("SSAConversion") { + } + + void Start(const PassDataHolder* data) const { + DCHECK(data != nullptr); + CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; + DCHECK(c_unit != nullptr); + MIRGraph *mir_graph = c_unit->mir_graph.get(); + mir_graph->DoDFSPreOrderSSARename(mir_graph->GetEntryBlock()); + } +}; + +/** + * @class PhiNodeOperands + * @brief Pass to insert the Phi node operands to basic blocks + */ +class PhiNodeOperands : public PassME { + public: + PhiNodeOperands() : PassME("PhiNodeOperands", kPreOrderDFSTraversal) { + } + + bool Worker(const PassDataHolder* data) const { + DCHECK(data != nullptr); + CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; + DCHECK(c_unit != nullptr); + BasicBlock* bb = down_cast<const PassMEDataHolder*>(data)->bb; + DCHECK(bb != nullptr); + c_unit->mir_graph->InsertPhiNodeOperands(bb); + // No need of repeating, so just return false. + return false; + } +}; + +/** + * @class InitRegLocations + * @brief Initialize Register Locations. + */ +class PerformInitRegLocations : public PassME { + public: + PerformInitRegLocations() : PassME("PerformInitRegLocation") { + } + + void Start(const PassDataHolder* data) const { + DCHECK(data != nullptr); + CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; + DCHECK(c_unit != nullptr); + c_unit->mir_graph->InitRegLocations(); + } +}; + +/** + * @class ConstantPropagation + * @brief Perform a constant propagation pass. + */ +class ConstantPropagation : public PassME { + public: + ConstantPropagation() : PassME("ConstantPropagation") { + } + + bool Worker(const PassDataHolder* data) const { + DCHECK(data != nullptr); + CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; + DCHECK(c_unit != nullptr); + BasicBlock* bb = down_cast<const PassMEDataHolder*>(data)->bb; + DCHECK(bb != nullptr); + c_unit->mir_graph->DoConstantPropagation(bb); + // No need of repeating, so just return false. + return false; + } + + void Start(const PassDataHolder* data) const { + DCHECK(data != nullptr); + CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; + DCHECK(c_unit != nullptr); + c_unit->mir_graph->InitializeConstantPropagation(); + } +}; + +/** + * @class FreeData + * @brief There is some data that needs to be freed after performing the post optimization passes. + */ +class FreeData : public PassME { + public: + FreeData() : PassME("FreeData") { + } + + void End(const PassDataHolder* data) const { + DCHECK(data != nullptr); + CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit; + DCHECK(c_unit != nullptr); + c_unit->mir_graph.get()->SSATransformationEnd(); + } +}; + +} // namespace art + +#endif // ART_COMPILER_DEX_CLEAN_UP_PASSES_H_ diff --git a/compiler/dex/ssa_transformation.cc b/compiler/dex/ssa_transformation.cc index 0c5a4ca..bd6bc22 100644 --- a/compiler/dex/ssa_transformation.cc +++ b/compiler/dex/ssa_transformation.cc @@ -244,9 +244,9 @@ bool MIRGraph::ComputeDominanceFrontier(BasicBlock* bb) { /* Calculate DF_up */ for (uint32_t dominated_idx : bb->i_dominated->Indexes()) { - BasicBlock *dominated_bb = GetBasicBlock(dominated_idx); + BasicBlock* dominated_bb = GetBasicBlock(dominated_idx); for (uint32_t df_up_block_idx : dominated_bb->dom_frontier->Indexes()) { - BasicBlock *df_up_block = GetBasicBlock(df_up_block_idx); + BasicBlock* df_up_block = GetBasicBlock(df_up_block_idx); CheckForDominanceFrontier(bb, df_up_block); } } |