Merge "ART: Use StackReference in Quick Stack Frame"
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 @@
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 @@
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 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 @@
*/
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 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 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 @@
}
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 @@
}
/* 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 @@
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 @@
/* 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 @@
* 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 @@
}
}
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 @@
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::ComputeTopologicalSortOrder() {
- std::queue<BasicBlock *> q;
+ std::queue<BasicBlock*> q;
std::map<int, int> visited_cnt_values;
// Clear the nodes.
@@ -1510,7 +1492,7 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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..574a6ba
--- /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_POST_OPT_H_
+#define ART_COMPILER_DEX_PASS_DRIVER_ME_POST_OPT_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_POST_OPT_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 @@
* @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 @@
/** @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..f203505
--- /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_POST_OPT_PASSES_H_
+#define ART_COMPILER_DEX_POST_OPT_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_POST_OPT_PASSES_H_
diff --git a/compiler/dex/ssa_transformation.cc b/compiler/dex/ssa_transformation.cc
index 0c5a4ca..bd6bc225 100644
--- a/compiler/dex/ssa_transformation.cc
+++ b/compiler/dex/ssa_transformation.cc
@@ -244,9 +244,9 @@
/* 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);
}
}
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 4d3d664..c6b1aa5 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -33,7 +33,7 @@
#include "compiler.h"
#include "compiler_callbacks.h"
#include "dex_file-inl.h"
-#include "dex/pass_driver_me.h"
+#include "dex/pass_driver_me_opts.h"
#include "dex/verification_results.h"
#include "driver/compiler_callbacks_impl.h"
#include "driver/compiler_driver.h"
@@ -919,18 +919,18 @@
} else if (option == "--no-profile-file") {
// No profile
} else if (option == "--print-pass-names") {
- PassDriverME::PrintPassNames();
+ PassDriverMEOpts::PrintPassNames();
} else if (option.starts_with("--disable-passes=")) {
std::string disable_passes = option.substr(strlen("--disable-passes=")).data();
- PassDriverME::CreateDefaultPassList(disable_passes);
+ PassDriverMEOpts::CreateDefaultPassList(disable_passes);
} else if (option.starts_with("--print-passes=")) {
std::string print_passes = option.substr(strlen("--print-passes=")).data();
- PassDriverME::SetPrintPassList(print_passes);
+ PassDriverMEOpts::SetPrintPassList(print_passes);
} else if (option == "--print-all-passes") {
- PassDriverME::SetPrintAllPasses();
+ PassDriverMEOpts::SetPrintAllPasses();
} else if (option.starts_with("--dump-cfg-passes=")) {
std::string dump_passes = option.substr(strlen("--dump-cfg-passes=")).data();
- PassDriverME::SetDumpPassList(dump_passes);
+ PassDriverMEOpts::SetDumpPassList(dump_passes);
} else {
Usage("Unknown argument %s", option.data());
}
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index e03b6f7..a962f06 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -1161,7 +1161,7 @@
}
ptr = TryToAllocate<true, true>(self, allocator, alloc_size, bytes_allocated, usable_size);
if (ptr == nullptr) {
- ThrowOutOfMemoryError(self, alloc_size, false);
+ ThrowOutOfMemoryError(self, alloc_size, allocator == kAllocatorTypeLOS);
}
return ptr;
}
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index e11671b..e568b36 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -408,7 +408,7 @@
// Implements java.lang.Runtime.freeMemory.
size_t GetFreeMemory() const {
- return GetTotalMemory() - num_bytes_allocated_.LoadSequentiallyConsistent();
+ return GetMaxMemory() - num_bytes_allocated_.LoadSequentiallyConsistent();
}
// get the space that corresponds to an object's address. Current implementation searches all