Added pass framework
The patch adds a Middle-End pass system and normalizes the current
passes into the pass framework.
Passes have:
- A start, work, and end functions.
- A gate to determine to apply the pass.
- Can provide a CFG dump folder.
mir_dataflow.cc, mir_graph.cc, mir_optimization.cc, ssa_transformation.cc:
- Changed due to moving code into bb_optimizations.cc.
- Moved certain functions from private to public due to needed from the passes.
pass.cc, pass.h:
- Pass base class
pass_driver.cc, pass_driver.h:
- The pass driver implementation.
frontend.cc:
- Replace the function calls to the passes with the pass driver.
Change-Id: I88cd82efbf6499df9e6c7f135d7e294dd724a079
Signed-off-by: Jean Christophe Beyler <jean.christophe.beyler@intel.com>
diff --git a/compiler/Android.mk b/compiler/Android.mk
index d9a573f..4340929 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -54,6 +54,8 @@
dex/dex_to_dex_compiler.cc \
dex/mir_dataflow.cc \
dex/mir_optimization.cc \
+ dex/pass_driver.cc \
+ dex/bb_optimizations.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
new file mode 100644
index 0000000..f013067
--- /dev/null
+++ b/compiler/dex/bb_optimizations.cc
@@ -0,0 +1,121 @@
+/*
+ * 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 "bb_optimizations.h"
+#include "dataflow_iterator.h"
+#include "dataflow_iterator-inl.h"
+
+namespace art {
+
+/*
+ * Code Layout pass implementation start.
+ */
+bool CodeLayout::WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const {
+ cUnit->mir_graph->LayoutBlocks(bb);
+ // No need of repeating, so just return false.
+ return false;
+}
+
+/*
+ * SSATransformation pass implementation start.
+ */
+bool SSATransformation::WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const {
+ cUnit->mir_graph->InsertPhiNodeOperands(bb);
+ // No need of repeating, so just return false.
+ return false;
+}
+
+void SSATransformation::End(CompilationUnit *cUnit) const {
+ // Verify the dataflow information after the pass.
+ if (cUnit->enable_debug & (1 << kDebugVerifyDataflow)) {
+ cUnit->mir_graph->VerifyDataflow();
+ }
+}
+
+/*
+ * ConstantPropagation pass implementation start
+ */
+bool ConstantPropagation::WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const {
+ cUnit->mir_graph->DoConstantPropagation(bb);
+ // No need of repeating, so just return false.
+ return false;
+}
+
+/*
+ * MethodUseCount pass implementation start.
+ */
+bool MethodUseCount::Gate(const CompilationUnit *cUnit) const {
+ // 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::WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const {
+ cUnit->mir_graph->CountUses(bb);
+ // No need of repeating, so just return false.
+ return false;
+}
+
+/*
+ * Null Check Elimination and Type Inference Initialization pass implementation start.
+ */
+
+bool NullCheckEliminationAndTypeInferenceInit::Gate(const CompilationUnit *cUnit) const {
+ // First check the ssa register vector
+ cUnit->mir_graph->CheckSSARegisterVector();
+
+ // Did we disable the pass?
+ bool performInit = ((cUnit->disable_opt & (1 << kNullCheckElimination)) == 0);
+
+ return performInit;
+}
+
+bool NullCheckEliminationAndTypeInferenceInit::WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const {
+ cUnit->mir_graph->NullCheckEliminationInit(bb);
+ // No need of repeating, so just return false.
+ return false;
+}
+
+/*
+ * BasicBlock Combine pass implementation start.
+ */
+bool BBCombine::WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const {
+ cUnit->mir_graph->CombineBlocks(bb);
+
+ // No need of repeating, so just return false.
+ return false;
+}
+
+/*
+ * BasicBlock Optimization pass implementation start.
+ */
+void BBOptimizations::Start(CompilationUnit *cUnit) const {
+ DCHECK_EQ(cUnit->num_compiler_temps, 0);
+
+ /*
+ * 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();
+}
+
+} // namespace art
diff --git a/compiler/dex/bb_optimizations.h b/compiler/dex/bb_optimizations.h
new file mode 100644
index 0000000..768b273
--- /dev/null
+++ b/compiler/dex/bb_optimizations.h
@@ -0,0 +1,165 @@
+/*
+ * 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_BB_OPTIMIZATIONS_H_
+#define ART_COMPILER_DEX_BB_OPTIMIZATIONS_H_
+
+#include "compiler_internals.h"
+#include "pass.h"
+
+namespace art {
+
+/**
+ * @class CodeLayout
+ * @brief Perform the code layout pass.
+ */
+class CodeLayout : public Pass {
+ public:
+ CodeLayout():Pass("CodeLayout", "2_post_layout_cfg") {
+ }
+
+ void Start(CompilationUnit *cUnit) const {
+ cUnit->mir_graph->VerifyDataflow();
+ }
+
+ bool WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const;
+};
+
+/**
+ * @class SSATransformation
+ * @brief Perform an SSA representation pass on the CompilationUnit.
+ */
+class SSATransformation : public Pass {
+ public:
+ SSATransformation():Pass("SSATransformation", kPreOrderDFSTraversal, "3_post_ssa_cfg") {
+ }
+
+ bool WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const;
+
+ void Start(CompilationUnit *cUnit) const {
+ cUnit->mir_graph->InitializeSSATransformation();
+ }
+
+ void End(CompilationUnit *cUnit) const;
+};
+
+/**
+ * @class ConstantPropagation
+ * @brief Perform a constant propagation pass.
+ */
+class ConstantPropagation : public Pass {
+ public:
+ ConstantPropagation():Pass("ConstantPropagation") {
+ }
+
+ bool WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const;
+
+ void Start(CompilationUnit *cUnit) const {
+ cUnit->mir_graph->InitializeConstantPropagation();
+ }
+};
+
+/**
+ * @class InitRegLocations
+ * @brief Initialize Register Locations.
+ */
+class InitRegLocations : public Pass {
+ public:
+ InitRegLocations():Pass("InitRegLocation") {
+ }
+
+ void Start(CompilationUnit *cUnit) const {
+ cUnit->mir_graph->InitRegLocations();
+ }
+};
+
+/**
+ * @class MethodUseCount
+ * @brief Count the register uses of the method
+ */
+class MethodUseCount : public Pass {
+ public:
+ MethodUseCount():Pass("UseCount") {
+ }
+
+ bool WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const;
+
+ bool Gate(const CompilationUnit *cUnit) const;
+};
+
+/**
+ * @class NullCheckEliminationAndTypeInferenceInit
+ * @brief Null check elimination and type inference initialization step.
+ */
+class NullCheckEliminationAndTypeInferenceInit : public Pass {
+ public:
+ NullCheckEliminationAndTypeInferenceInit():Pass("NCE_TypeInferenceInit") {
+ }
+
+ bool WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const;
+
+ bool Gate(const CompilationUnit *cUnit) const;
+};
+
+/**
+ * @class NullCheckEliminationAndTypeInference
+ * @brief Null check elimination and type inference.
+ */
+class NullCheckEliminationAndTypeInference : public Pass {
+ public:
+ NullCheckEliminationAndTypeInference():Pass("NCE_TypeInference", kRepeatingPreOrderDFSTraversal, "4_post_nce_cfg") {
+ }
+
+ bool WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const {
+ return cUnit->mir_graph->EliminateNullChecksAndInferTypes(bb);
+ }
+};
+
+/**
+ * @class NullCheckEliminationAndTypeInference
+ * @brief Null check elimination and type inference.
+ */
+class BBCombine : public Pass {
+ public:
+ BBCombine():Pass("BBCombine", kPreOrderDFSTraversal, "5_post_bbcombine_cfg") {
+ }
+
+ bool Gate(const CompilationUnit *cUnit) const {
+ return ((cUnit->disable_opt & (1 << kSuppressExceptionEdges)) != 0);
+ }
+
+ bool WalkBasicBlocks(CompilationUnit *cUnit, BasicBlock *bb) const;
+};
+
+/**
+ * @class BasicBlock Optimizations
+ * @brief Any simple BasicBlock optimization can be put here.
+ */
+class BBOptimizations : public Pass {
+ public:
+ BBOptimizations():Pass("BBOptimizations", "5_post_bbo_cfg") {
+ }
+
+ bool Gate(const CompilationUnit *cUnit) const {
+ return ((cUnit->disable_opt & (1 << kBBOpt)) == 0);
+ }
+
+ void Start(CompilationUnit *cUnit) const;
+};
+
+} // namespace art
+
+#endif // ART_COMPILER_DEX_BB_OPTIMIZATIONS_H_
diff --git a/compiler/dex/dataflow_iterator.h b/compiler/dex/dataflow_iterator.h
index 12f924e..658a9b1 100644
--- a/compiler/dex/dataflow_iterator.h
+++ b/compiler/dex/dataflow_iterator.h
@@ -138,6 +138,21 @@
return ForwardSingleNext();
}
+
+ /**
+ * @brief Redefine the new operator to use the arena
+ * @param size actually unused, we use our own class size
+ * @param arena the arena to perform the actual allocation
+ * @return the pointer to the newly allocated object
+ */
+ static void* operator new(size_t size, ArenaAllocator* arena) {
+ return arena->Alloc(sizeof(PreOrderDfsIterator), ArenaAllocator::kAllocGrowableBitMap);
+ }
+
+ /**
+ * @brief Redefine delete to not actually delete anything since we are using the arena
+ */
+ static void operator delete(void* p) {}
};
/**
@@ -169,6 +184,21 @@
return ForwardRepeatNext();
}
+
+ /**
+ * @brief Redefine the new operator to use the arena
+ * @param size actually unused, we use our own class size
+ * @param arena the arena to perform the actual allocation
+ * @return the pointer to the newly allocated object
+ */
+ static void* operator new(size_t size, ArenaAllocator* arena) {
+ return arena->Alloc(sizeof(RepeatingPreOrderDfsIterator), ArenaAllocator::kAllocGrowableBitMap);
+ }
+
+ /**
+ * @brief Redefine delete to not actually delete anything since we are using the arena
+ */
+ static void operator delete(void* p) {}
};
/**
@@ -200,6 +230,21 @@
return ForwardRepeatNext();
}
+
+ /**
+ * @brief Redefine the new operator to use the arena
+ * @param size actually unused, we use our own class size
+ * @param arena the arena to perform the actual allocation
+ * @return the pointer to the newly allocated object
+ */
+ static void* operator new(size_t size, ArenaAllocator* arena) {
+ return arena->Alloc(sizeof(RepeatingPostOrderDfsIterator), ArenaAllocator::kAllocGrowableBitMap);
+ }
+
+ /**
+ * @brief Redefine delete to not actually delete anything since we are using the arena
+ */
+ static void operator delete(void* p) {}
};
/**
@@ -230,6 +275,21 @@
return ReverseSingleNext();
}
+
+ /**
+ * @brief Redefine the new operator to use the arena
+ * @param size actually unused, we use our own class size
+ * @param arena the arena to perform the actual allocation
+ * @return the pointer to the newly allocated object
+ */
+ static void* operator new(size_t size, ArenaAllocator* arena) {
+ return arena->Alloc(sizeof(ReversePostOrderDfsIterator), ArenaAllocator::kAllocGrowableBitMap);
+ }
+
+ /**
+ * @brief Redefine delete to not actually delete anything since we are using the arena
+ */
+ static void operator delete(void* p) {}
};
/**
@@ -261,6 +321,21 @@
return ReverseRepeatNext();
}
+
+ /**
+ * @brief Redefine the new operator to use the arena
+ * @param size actually unused, we use our own class size
+ * @param arena the arena to perform the actual allocation
+ * @return the pointer to the newly allocated object
+ */
+ static void* operator new(size_t size, ArenaAllocator* arena) {
+ return arena->Alloc(sizeof(RepeatingReversePostOrderDfsIterator), ArenaAllocator::kAllocGrowableBitMap);
+ }
+
+ /**
+ * @brief Redefine delete to not actually delete anything since we are using the arena
+ */
+ static void operator delete(void* p) {}
};
/**
@@ -291,6 +366,21 @@
return ForwardSingleNext();
}
+
+ /**
+ * @brief Redefine the new operator to use the arena
+ * @param size actually unused, we use our own class size
+ * @param arena the arena to perform the actual allocation
+ * @return the pointer to the newly allocated object
+ */
+ static void* operator new(size_t size, ArenaAllocator* arena) {
+ return arena->Alloc(sizeof(PostOrderDOMIterator), ArenaAllocator::kAllocGrowableBitMap);
+ }
+
+ /**
+ * @brief Redefine delete to not actually delete anything since we are using the arena
+ */
+ static void operator delete(void* p) {}
};
/**
@@ -323,6 +413,21 @@
*/
virtual BasicBlock* Next(bool had_change = false) ALWAYS_INLINE;
+ /**
+ * @brief Redefine the new operator to use the arena
+ * @param size actually unused, we use our own class size
+ * @param arena the arena to perform the actual allocation
+ * @return the pointer to the newly allocated object
+ */
+ static void* operator new(size_t size, ArenaAllocator* arena) {
+ return arena->Alloc(sizeof(AllNodesIterator), ArenaAllocator::kAllocGrowableBitMap);
+ }
+
+ /**
+ * @brief Redefine delete to not actually delete anything since we are using the arena
+ */
+ static void operator delete(void* p) {}
+
private:
GrowableArray<BasicBlock*>::Iterator* all_nodes_iterator_; /**< @brief The list of all the nodes */
};
diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc
index adfbf2f..f5bb85a 100644
--- a/compiler/dex/frontend.cc
+++ b/compiler/dex/frontend.cc
@@ -21,6 +21,7 @@
#include "dataflow_iterator-inl.h"
#include "leb128.h"
#include "mirror/object.h"
+#include "pass_driver.h"
#include "runtime.h"
#include "backend.h"
#include "base/logging.h"
@@ -251,36 +252,9 @@
}
#endif
- /* Do a code layout pass */
- cu.NewTimingSplit("MIROpt:CodeLayout");
- cu.mir_graph->CodeLayout();
-
- /* Perform SSA transformation for the whole method */
- cu.NewTimingSplit("MIROpt:SSATransform");
- cu.mir_graph->SSATransformation();
-
- /* Do constant propagation */
- cu.NewTimingSplit("MIROpt:ConstantProp");
- cu.mir_graph->PropagateConstants();
-
- cu.NewTimingSplit("MIROpt:InitRegLoc");
- cu.mir_graph->InitRegLocations();
-
- /* Count uses */
- cu.NewTimingSplit("MIROpt:UseCount");
- cu.mir_graph->MethodUseCount();
-
- /* Perform null check elimination and type inference*/
- cu.NewTimingSplit("MIROpt:NCE_TypeInference");
- cu.mir_graph->NullCheckEliminationAndTypeInference();
-
- /* Combine basic blocks where possible */
- cu.NewTimingSplit("MIROpt:BBCombine");
- cu.mir_graph->BasicBlockCombine();
-
- /* Do some basic block optimizations */
- cu.NewTimingSplit("MIROpt:BBOpt");
- cu.mir_graph->BasicBlockOptimization();
+ /* Create the pass driver and launch it */
+ PassDriver driver(&cu);
+ driver.Launch();
if (cu.enable_debug & (1 << kDebugDumpCheckStats)) {
cu.mir_graph->DumpCheckStats();
diff --git a/compiler/dex/mir_dataflow.cc b/compiler/dex/mir_dataflow.cc
index 728d48a..c235448 100644
--- a/compiler/dex/mir_dataflow.cc
+++ b/compiler/dex/mir_dataflow.cc
@@ -1235,9 +1235,9 @@
* counts explicitly used s_regs. A later phase will add implicit
* counts for things such as Method*, null-checked references, etc.
*/
-bool MIRGraph::CountUses(struct BasicBlock* bb) {
+void MIRGraph::CountUses(struct BasicBlock* bb) {
if (bb->block_type != kDalvikByteCode) {
- return false;
+ return;
}
// Each level of nesting adds *100 to count, up to 3 levels deep.
uint32_t depth = std::min(3U, static_cast<uint32_t>(bb->nesting_depth));
@@ -1269,26 +1269,6 @@
}
}
}
- return false;
-}
-
-void MIRGraph::MethodUseCount() {
- // Now that we know, resize the lists.
- int num_ssa_regs = GetNumSSARegs();
- use_counts_.Resize(num_ssa_regs + 32);
- raw_use_counts_.Resize(num_ssa_regs + 32);
- // Initialize list
- for (int i = 0; i < num_ssa_regs; i++) {
- use_counts_.Insert(0);
- raw_use_counts_.Insert(0);
- }
- if (cu_->disable_opt & (1 << kPromoteRegs)) {
- return;
- }
- AllNodesIterator iter(this);
- for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
- CountUses(bb);
- }
}
/* Verify if all the successor is connected with all the claimed predecessors */
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc
index b1c0b28..8d1653f 100644
--- a/compiler/dex/mir_graph.cc
+++ b/compiler/dex/mir_graph.cc
@@ -1147,4 +1147,53 @@
return bb;
}
+void MIRGraph::InitializeConstantPropagation() {
+ is_constant_v_ = new (arena_) ArenaBitVector(arena_, GetNumSSARegs(), false);
+ constant_values_ = static_cast<int*>(arena_->Alloc(sizeof(int) * GetNumSSARegs(), ArenaAllocator::kAllocDFInfo));
+}
+
+void MIRGraph::InitializeMethodUses() {
+ // The gate starts by initializing the use counts
+ int num_ssa_regs = GetNumSSARegs();
+ use_counts_.Resize(num_ssa_regs + 32);
+ raw_use_counts_.Resize(num_ssa_regs + 32);
+ // Initialize list
+ for (int i = 0; i < num_ssa_regs; i++) {
+ use_counts_.Insert(0);
+ raw_use_counts_.Insert(0);
+ }
+}
+
+void MIRGraph::InitializeSSATransformation() {
+ /* 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());
+
+ /*
+ * Shared temp bit vector used by each block to count the number of defs
+ * from all the predecessor blocks.
+ */
+ temp_ssa_register_v_ =
+ new (arena_) ArenaBitVector(arena_, GetNumSSARegs(), false, kBitMapTempSSARegisterV);
+}
+
+void MIRGraph::CheckSSARegisterVector() {
+ DCHECK(temp_ssa_register_v_ != nullptr);
+}
+
} // namespace art
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index d080e39..b68e699 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -615,17 +615,12 @@
return opcode >= static_cast<int>(kMirOpFirst);
}
- void BasicBlockCombine();
- void CodeLayout();
void DumpCheckStats();
- void PropagateConstants();
MIR* FindMoveResult(BasicBlock* bb, MIR* mir);
int SRegToVReg(int ssa_reg) const;
void VerifyDataflow();
- void MethodUseCount();
- void SSATransformation();
void CheckForDominanceFrontier(BasicBlock* dom_bb, const BasicBlock* succ_bb);
- void NullCheckEliminationAndTypeInference();
+ bool EliminateNullChecksAndInferTypes(BasicBlock *bb);
/*
* Type inference handling helpers. Because Dalvik's bytecode is not fully typed,
* we have to do some work to figure out the sreg type. For some operations it is
@@ -670,6 +665,58 @@
BasicBlock* NextDominatedBlock(BasicBlock* bb);
bool LayoutBlocks(BasicBlock* bb);
+ /**
+ * @brief Perform the initial preparation for the Method Uses.
+ */
+ void InitializeMethodUses();
+
+ /**
+ * @brief Perform the initial preparation for the Constant Propagation.
+ */
+ void InitializeConstantPropagation();
+
+ /**
+ * @brief Perform the initial preparation for the SSA Transformation.
+ */
+ void InitializeSSATransformation();
+
+ /**
+ * @brief Insert a the operands for the Phi nodes.
+ * @param bb the considered BasicBlock.
+ * @return true
+ */
+ bool InsertPhiNodeOperands(BasicBlock* bb);
+
+ /**
+ * @brief Perform constant propagation on a BasicBlock.
+ * @param bb the considered BasicBlock.
+ */
+ void DoConstantPropagation(BasicBlock* bb);
+
+ /**
+ * @brief Count the uses in the BasicBlock
+ * @param bb the BasicBlock
+ */
+ void CountUses(struct BasicBlock* bb);
+
+ /**
+ * @brief Initialize the data structures with Null Check data
+ * @param bb the considered BasicBlock
+ */
+ void NullCheckEliminationInit(BasicBlock* bb);
+
+ /**
+ * @brief Check if the temporary ssa register vector is allocated
+ */
+ void CheckSSARegisterVector();
+
+ /**
+ * @brief Combine BasicBlocks
+ * @param the BasicBlock we are considering
+ */
+ void CombineBlocks(BasicBlock* bb);
+
+ void ClearAllVisitedFlags();
/*
* IsDebugBuild sanity check: keep track of the Dex PCs for catch entries so that later on
* we can verify that all catch entries have native PC entries.
@@ -715,8 +762,6 @@
void DataFlowSSAFormat35C(MIR* mir);
void DataFlowSSAFormat3RC(MIR* mir);
bool FindLocalLiveIn(BasicBlock* bb);
- void ClearAllVisitedFlags();
- bool CountUses(struct BasicBlock* bb);
bool InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed);
bool VerifyPredInfo(BasicBlock* bb);
BasicBlock* NeedsVisit(BasicBlock* bb);
@@ -733,8 +778,6 @@
void SetConstantWide(int ssa_reg, int64_t value);
int GetSSAUseCount(int s_reg);
bool BasicBlockOpt(BasicBlock* bb);
- bool EliminateNullChecksAndInferTypes(BasicBlock* bb);
- void NullCheckEliminationInit(BasicBlock* bb);
bool BuildExtendedBBList(struct BasicBlock* bb);
bool FillDefBlockMatrix(BasicBlock* bb);
void InitializeDominationInfo(BasicBlock* bb);
@@ -742,11 +785,9 @@
bool ComputeBlockDominators(BasicBlock* bb);
bool SetDominators(BasicBlock* bb);
bool ComputeBlockLiveIns(BasicBlock* bb);
- bool InsertPhiNodeOperands(BasicBlock* bb);
bool ComputeDominanceFrontier(BasicBlock* bb);
- void DoConstantPropogation(BasicBlock* bb);
+
void CountChecks(BasicBlock* bb);
- bool CombineBlocks(BasicBlock* bb);
void AnalyzeBlock(BasicBlock* bb, struct MethodStats* stats);
bool ComputeSkipCompilation(struct MethodStats* stats, bool skip_default);
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index 5d83991..ee9f28e 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -36,7 +36,7 @@
constant_values_[ssa_reg + 1] = High32Bits(value);
}
-void MIRGraph::DoConstantPropogation(BasicBlock* bb) {
+void MIRGraph::DoConstantPropagation(BasicBlock* bb) {
MIR* mir;
for (mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
@@ -92,16 +92,6 @@
/* TODO: implement code to handle arithmetic operations */
}
-void MIRGraph::PropagateConstants() {
- is_constant_v_ = new (arena_) ArenaBitVector(arena_, GetNumSSARegs(), false);
- constant_values_ = static_cast<int*>(arena_->Alloc(sizeof(int) * GetNumSSARegs(),
- ArenaAllocator::kAllocDFInfo));
- AllNodesIterator iter(this);
- for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
- DoConstantPropogation(bb);
- }
-}
-
/* Advance to next strictly dominated MIR node in an extended basic block */
MIR* MIRGraph::AdvanceMIR(BasicBlock** p_bb, MIR* mir) {
BasicBlock* bb = *p_bb;
@@ -557,7 +547,7 @@
}
/* Combine any basic blocks terminated by instructions that we now know can't throw */
-bool MIRGraph::CombineBlocks(struct BasicBlock* bb) {
+void MIRGraph::CombineBlocks(struct BasicBlock* bb) {
// Loop here to allow combining a sequence of blocks
while (true) {
// Check termination conditions
@@ -621,14 +611,13 @@
// Now, loop back and see if we can keep going
}
- return false;
}
/*
* Eliminate unnecessary null checks for a basic block. Also, while we're doing
* an iterative walk go ahead and perform type and size inference.
*/
-bool MIRGraph::EliminateNullChecksAndInferTypes(struct BasicBlock* bb) {
+bool MIRGraph::EliminateNullChecksAndInferTypes(BasicBlock* bb) {
if (bb->data_flow_info == NULL) return false;
bool infer_changed = false;
bool do_nce = ((cu_->disable_opt & (1 << kNullCheckElimination)) == 0);
@@ -810,49 +799,6 @@
return infer_changed | nce_changed;
}
-void MIRGraph::NullCheckEliminationAndTypeInference() {
- DCHECK(temp_ssa_register_v_ != NULL);
- if ((cu_->disable_opt & (1 << kNullCheckElimination)) == 0) {
- AllNodesIterator iter(this);
- for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
- NullCheckEliminationInit(bb);
- }
- }
- RepeatingPreOrderDfsIterator iter2(this);
- bool change = false;
- for (BasicBlock* bb = iter2.Next(change); bb != NULL; bb = iter2.Next(change)) {
- change = EliminateNullChecksAndInferTypes(bb);
- }
- if (cu_->enable_debug & (1 << kDebugDumpCFG)) {
- DumpCFG("/sdcard/4_post_nce_cfg/", false);
- }
-}
-
-void MIRGraph::BasicBlockCombine() {
- if ((cu_->disable_opt & (1 << kSuppressExceptionEdges)) != 0) {
- PreOrderDfsIterator iter(this);
- for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
- CombineBlocks(bb);
- }
- if (cu_->enable_debug & (1 << kDebugDumpCFG)) {
- DumpCFG("/sdcard/5_post_bbcombine_cfg/", false);
- }
- }
-}
-
-void MIRGraph::CodeLayout() {
- if (cu_->enable_debug & (1 << kDebugVerifyDataflow)) {
- VerifyDataflow();
- }
- AllNodesIterator iter(this);
- for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
- LayoutBlocks(bb);
- }
- if (cu_->enable_debug & (1 << kDebugDumpCFG)) {
- DumpCFG("/sdcard/2_post_layout_cfg/", true);
- }
-}
-
void MIRGraph::DumpCheckStats() {
Checkstats* stats =
static_cast<Checkstats*>(arena_->Alloc(sizeof(Checkstats), ArenaAllocator::kAllocDFInfo));
@@ -909,29 +855,22 @@
return false; // Not iterative - return value will be ignored
}
-
void MIRGraph::BasicBlockOptimization() {
- if (!(cu_->disable_opt & (1 << kBBOpt))) {
- DCHECK_EQ(cu_->num_compiler_temps, 0);
- if ((cu_->disable_opt & (1 << kSuppressExceptionEdges)) != 0) {
- ClearAllVisitedFlags();
- PreOrderDfsIterator iter2(this);
- for (BasicBlock* bb = iter2.Next(); bb != NULL; bb = iter2.Next()) {
- BuildExtendedBBList(bb);
- }
- // Perform extended basic block optimizations.
- for (unsigned int i = 0; i < extended_basic_blocks_.size(); i++) {
- BasicBlockOpt(GetBasicBlock(extended_basic_blocks_[i]));
- }
- } else {
- PreOrderDfsIterator iter(this);
- for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
- BasicBlockOpt(bb);
- }
+ if ((cu_->disable_opt & (1 << kSuppressExceptionEdges)) != 0) {
+ ClearAllVisitedFlags();
+ PreOrderDfsIterator iter2(this);
+ for (BasicBlock* bb = iter2.Next(); bb != NULL; bb = iter2.Next()) {
+ BuildExtendedBBList(bb);
}
- }
- if (cu_->enable_debug & (1 << kDebugDumpCFG)) {
- DumpCFG("/sdcard/6_post_bbo_cfg/", false);
+ // Perform extended basic block optimizations.
+ for (unsigned int i = 0; i < extended_basic_blocks_.size(); i++) {
+ BasicBlockOpt(GetBasicBlock(extended_basic_blocks_[i]));
+ }
+ } else {
+ PreOrderDfsIterator iter(this);
+ for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
+ BasicBlockOpt(bb);
+ }
}
}
diff --git a/compiler/dex/pass.h b/compiler/dex/pass.h
new file mode 100644
index 0000000..c52ddf5
--- /dev/null
+++ b/compiler/dex/pass.h
@@ -0,0 +1,145 @@
+/*
+ * 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_H_
+#define ART_COMPILER_DEX_PASS_H_
+
+#include <string>
+
+namespace art {
+
+// Forward declarations.
+class BasicBlock;
+class CompilationUnit;
+class Pass;
+
+/**
+ * @brief OptimizationFlag is an enumeration to perform certain tasks for a given pass.
+ * @details Each enum should be a power of 2 to be correctly used.
+ */
+enum OptimizationFlag {
+};
+
+enum DataFlowAnalysisMode {
+ kAllNodes = 0, /**< @brief All nodes. */
+ kPreOrderDFSTraversal, /**< @brief Depth-First-Search / Pre-Order. */
+ kRepeatingPreOrderDFSTraversal, /**< @brief Depth-First-Search / Repeating Pre-Order. */
+ kReversePostOrderDFSTraversal, /**< @brief Depth-First-Search / Reverse Post-Order. */
+ kRepeatingPostOrderDFSTraversal, /**< @brief Depth-First-Search / Repeating Post-Order. */
+ kRepeatingReversePostOrderDFSTraversal, /**< @brief Depth-First-Search / Repeating Reverse Post-Order. */
+ kPostOrderDOMTraversal, /**< @brief Dominator tree / Post-Order. */
+};
+
+/**
+ * @class Pass
+ * @brief Pass is the Pass structure for the optimizations.
+ * @details The following structure has the different optimization passes that we are going to do.
+ */
+class Pass {
+ public:
+ Pass(const char *name, DataFlowAnalysisMode type, bool freed, const unsigned int f, const char *dump): pass_name_(name), traversal_type_(type), flags_(f), dump_cfg_folder_(dump) {
+ }
+
+ Pass(const char *name, const char *dump): pass_name_(name), traversal_type_(kAllNodes), flags_(0), dump_cfg_folder_(dump) {
+ }
+
+ explicit Pass(const char *name):pass_name_(name), traversal_type_(kAllNodes), flags_(0), dump_cfg_folder_("") {
+ }
+
+ Pass(const char *name, DataFlowAnalysisMode type, const char *dump):pass_name_(name), traversal_type_(type), flags_(false), dump_cfg_folder_(dump) {
+ }
+
+ virtual ~Pass() {}
+
+ virtual const char* GetName() const {
+ return pass_name_;
+ }
+
+ virtual DataFlowAnalysisMode GetTraversal() const {
+ return traversal_type_;
+ }
+
+ virtual bool GetFlag(OptimizationFlag flag) const {
+ return (flags_ & flag);
+ }
+
+ const char* GetDumpCFGFolder() const {return dump_cfg_folder_;}
+
+ /**
+ * @brief Gate for the pass: determines whether to execute the pass or not considering a CompilationUnit
+ * @param c_unit the CompilationUnit.
+ * @return whether or not to execute the pass
+ */
+ virtual bool Gate(const CompilationUnit *c_unit) const {
+ // Unused parameter.
+ UNUSED(c_unit);
+
+ // Base class says yes.
+ return true;
+ }
+
+ /**
+ * @brief Start of the pass: called before the WalkBasicBlocks function
+ * @param c_unit the considered CompilationUnit.
+ */
+ virtual void Start(CompilationUnit *c_unit) const {
+ // Unused parameter.
+ UNUSED(c_unit);
+ }
+
+ /**
+ * @brief End of the pass: called after the WalkBasicBlocks function
+ * @param c_unit the considered CompilationUnit.
+ */
+ virtual void End(CompilationUnit *c_unit) const {
+ // Unused parameter.
+ UNUSED(c_unit);
+ }
+
+ /**
+ * @brief Actually walk the BasicBlocks following a particular traversal type.
+ * @param c_unit the CompilationUnit.
+ * @param bb the BasicBlock.
+ * @return whether or not there is a change when walking the BasicBlock
+ */
+ virtual bool WalkBasicBlocks(CompilationUnit *c_unit, BasicBlock *bb) const {
+ // Unused parameters.
+ UNUSED(c_unit);
+ UNUSED(bb);
+
+ // BasicBlock did not change.
+ return false;
+ }
+
+ protected:
+ /** @brief The pass name: used for searching for a pass when running a particular pass or debugging. */
+ const char* const pass_name_;
+
+ /** @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. */
+ const unsigned int flags_;
+
+ /** @brief CFG Dump Folder: what sub-folder to use for dumping the CFGs post pass. */
+ const char* const dump_cfg_folder_;
+
+ private:
+ // In order to make the all passes not copy-friendly.
+ DISALLOW_COPY_AND_ASSIGN(Pass);
+};
+} // namespace art
+#endif // ART_COMPILER_DEX_PASS_H_
diff --git a/compiler/dex/pass_driver.cc b/compiler/dex/pass_driver.cc
new file mode 100644
index 0000000..b20d728
--- /dev/null
+++ b/compiler/dex/pass_driver.cc
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dlfcn.h>
+
+#include "bb_optimizations.h"
+#include "compiler_internals.h"
+#include "dataflow_iterator.h"
+#include "dataflow_iterator-inl.h"
+#include "pass.h"
+#include "pass_driver.h"
+
+namespace art {
+
+PassDriver::PassDriver(CompilationUnit* const cu, bool create_default_passes) : cu_(cu) {
+ dump_cfg_folder_ = "/sdcard/";
+
+ // If need be, create the default passes.
+ if (create_default_passes == true) {
+ CreatePasses();
+ }
+}
+
+PassDriver::~PassDriver() {
+ // Clear the map: done to remove any chance of having a pointer after freeing below
+ pass_map_.clear();
+}
+
+void PassDriver::InsertPass(Pass* new_pass, bool warn_override) {
+ assert(new_pass != 0);
+
+ // Get name here to not do it all over the method.
+ const std::string& name = new_pass->GetName();
+
+ // Do we want to warn the user about squashing a pass?
+ if (warn_override == false) {
+ SafeMap<std::string, Pass* >::iterator it = pass_map_.find(name);
+
+ if (it != pass_map_.end()) {
+ LOG(INFO) << "Pass name " << name << " already used, overwriting pass";
+ }
+ }
+
+ // Now add to map and list.
+ pass_map_.Put(name, new_pass);
+ pass_list_.push_back(new_pass);
+}
+
+void PassDriver::CreatePasses() {
+ /*
+ * Create the pass list:
+ * - These passes are immutable and are shared across the threads:
+ * - This is achieved via:
+ * - The UniquePtr used here.
+ * - DISALLOW_COPY_AND_ASSIGN in the base Pass class.
+ *
+ * Advantage is that there will be no race conditions here.
+ * Disadvantage is the passes can't change their internal states depending on CompilationUnit:
+ * - This is not yet an issue: no current pass would require it.
+ */
+ static UniquePtr<Pass> *passes[] = {
+ new UniquePtr<Pass>(new CodeLayout()),
+ new UniquePtr<Pass>(new SSATransformation()),
+ new UniquePtr<Pass>(new ConstantPropagation()),
+ new UniquePtr<Pass>(new InitRegLocations()),
+ new UniquePtr<Pass>(new MethodUseCount()),
+ new UniquePtr<Pass>(new NullCheckEliminationAndTypeInferenceInit()),
+ new UniquePtr<Pass>(new NullCheckEliminationAndTypeInference()),
+ new UniquePtr<Pass>(new BBCombine()),
+ new UniquePtr<Pass>(new BBOptimizations()),
+ };
+
+ // Get number of elements in the array.
+ unsigned int nbr = (sizeof(passes) / sizeof(passes[0]));
+
+ // Insert each pass into the map and into the list via the InsertPass method:
+ // - Map is used for the lookup
+ // - List is used for the pass walk
+ for (unsigned int i = 0; i < nbr; i++) {
+ InsertPass(passes[i]->get());
+ }
+}
+
+void PassDriver::HandlePassFlag(CompilationUnit* c_unit, Pass* pass) {
+ // Unused parameters for the moment.
+ UNUSED(c_unit);
+ UNUSED(pass);
+}
+
+void PassDriver::DispatchPass(CompilationUnit* c_unit, Pass* curPass) {
+ DataflowIterator* iterator = 0;
+
+ LOG(DEBUG) << "Dispatching " << curPass->GetName();
+
+ MIRGraph* mir_graph = c_unit->mir_graph.get();
+ ArenaAllocator *arena = &(c_unit->arena);
+
+ // Let us start by getting the right iterator.
+ DataFlowAnalysisMode mode = curPass->GetTraversal();
+
+ switch (mode) {
+ case kPreOrderDFSTraversal:
+ iterator = new (arena) PreOrderDfsIterator(mir_graph);
+ break;
+ case kRepeatingPreOrderDFSTraversal:
+ iterator = new (arena) RepeatingPreOrderDfsIterator(mir_graph);
+ break;
+ case kRepeatingPostOrderDFSTraversal:
+ iterator = new (arena) RepeatingPostOrderDfsIterator(mir_graph);
+ break;
+ case kReversePostOrderDFSTraversal:
+ iterator = new (arena) ReversePostOrderDfsIterator(mir_graph);
+ break;
+ case kRepeatingReversePostOrderDFSTraversal:
+ iterator = new (arena) RepeatingReversePostOrderDfsIterator(mir_graph);
+ break;
+ case kPostOrderDOMTraversal:
+ iterator = new (arena) PostOrderDOMIterator(mir_graph);
+ break;
+ case kAllNodes:
+ iterator = new (arena) AllNodesIterator(mir_graph);
+ break;
+ default:
+ LOG(DEBUG) << "Iterator mode not handled in dispatcher: " << mode;
+ return;
+ }
+
+ // Paranoid: Check the iterator before walking the BasicBlocks.
+ assert(iterator != 0);
+
+ bool change = false;
+ for (BasicBlock *bb = iterator->Next(change); bb != 0; bb = iterator->Next(change)) {
+ change = curPass->WalkBasicBlocks(c_unit, bb);
+ }
+}
+
+void PassDriver::ApplyPass(CompilationUnit* c_unit, Pass* curPass) {
+ curPass->Start(c_unit);
+ DispatchPass(c_unit, curPass);
+ curPass->End(c_unit);
+}
+
+bool PassDriver::RunPass(CompilationUnit* c_unit, Pass* curPass, bool time_split) {
+ // Paranoid: c_unit or curPass cannot be 0, and the pass should have a name.
+ if (c_unit == 0 || curPass == 0 || (strcmp(curPass->GetName(), "") == 0)) {
+ return false;
+ }
+
+ // Do we perform a time split
+ if (time_split == true) {
+ std::string name = "MIROpt:";
+ name += curPass->GetName();
+ c_unit->NewTimingSplit(name.c_str());
+ }
+
+ // Check the pass gate first.
+ bool shouldApplyPass = curPass->Gate(c_unit);
+
+ if (shouldApplyPass == true) {
+ // Applying the pass: first start, doWork, and end calls.
+ ApplyPass(c_unit, curPass);
+
+ // Clean up if need be.
+ HandlePassFlag(c_unit, curPass);
+
+ // Do we want to log it?
+ if ((c_unit->enable_debug& (1 << kDebugDumpCFG)) != 0) {
+ // Do we have a pass folder?
+ const std::string& passFolder = curPass->GetDumpCFGFolder();
+
+ if (passFolder != "") {
+ // Create directory prefix.
+ std::string prefix = GetDumpCFGFolder();
+ prefix += passFolder;
+ prefix += "/";
+
+ c_unit->mir_graph->DumpCFG(prefix.c_str(), false);
+ }
+ }
+ }
+
+ // If the pass gate passed, we can declare success.
+ return shouldApplyPass;
+}
+
+bool PassDriver::RunPass(CompilationUnit* c_unit, const std::string& pass_name) {
+ // Paranoid: c_unit cannot be 0 and we need a pass name.
+ if (c_unit == 0 || pass_name == "") {
+ return false;
+ }
+
+ Pass* curPass = GetPass(pass_name);
+
+ if (curPass != 0) {
+ return RunPass(c_unit, curPass);
+ }
+
+ // Return false, we did not find the pass.
+ return false;
+}
+
+void PassDriver::Launch() {
+ for (std::list<Pass* >::iterator it = pass_list_.begin(); it != pass_list_.end(); it++) {
+ Pass* curPass = *it;
+ RunPass(cu_, curPass, true);
+ }
+}
+
+void PassDriver::PrintPassNames() const {
+ LOG(INFO) << "Loop Passes are:";
+
+ for (std::list<Pass* >::const_iterator it = pass_list_.begin(); it != pass_list_.end(); it++) {
+ const Pass* curPass = *it;
+ LOG(INFO) << "\t-" << curPass->GetName();
+ }
+}
+
+Pass* PassDriver::GetPass(const std::string& name) const {
+ SafeMap<std::string, Pass*>::const_iterator it = pass_map_.find(name);
+
+ if (it != pass_map_.end()) {
+ return it->second;
+ }
+
+ return 0;
+}
+
+} // namespace art
diff --git a/compiler/dex/pass_driver.h b/compiler/dex/pass_driver.h
new file mode 100644
index 0000000..29da351
--- /dev/null
+++ b/compiler/dex/pass_driver.h
@@ -0,0 +1,101 @@
+/*
+ * 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_H_
+#define ART_COMPILER_DEX_PASS_DRIVER_H_
+
+#include <list>
+#include "pass.h"
+#include "safe_map.h"
+
+// Forward Declarations.
+class CompilationUnit;
+class Pass;
+
+namespace art {
+
+/**
+ * @class PassDriver
+ * @brief PassDriver is the wrapper around all Pass instances in order to execute them from the Middle-End
+ */
+class PassDriver {
+ public:
+ explicit PassDriver(CompilationUnit* const cu, bool create_default_passes = true);
+
+ ~PassDriver();
+
+ /**
+ * @brief Insert a Pass: can warn if multiple passes have the same name.
+ * @param new_pass the new Pass to insert in the map and list.
+ * @param warn_override warn if the name of the Pass is already used.
+ */
+ void InsertPass(Pass *new_pass, bool warn_override = true);
+
+ /**
+ * @brief Run a pass using the name as key.
+ * @param c_unit the considered CompilationUnit.
+ * @param pass_name the Pass name.
+ * @return whether the pass was applied.
+ */
+ bool RunPass(CompilationUnit* c_unit, const std::string& pass_name);
+
+ /**
+ * @brief Run a pass using the Pass itself.
+ * @param time_split do we want a time split request(default: false)?
+ * @return whether the pass was applied.
+ */
+ bool RunPass(CompilationUnit* c_unit, Pass* pass, bool time_split = false);
+
+ void Launch();
+
+ void HandlePassFlag(CompilationUnit* c_unit, Pass* pass);
+
+ /**
+ * @brief Apply a patch: perform start/work/end functions.
+ */
+ void ApplyPass(CompilationUnit* c_unit, Pass* pass);
+
+ /**
+ * @brief Dispatch a patch: walk the BasicBlocks depending on the traversal mode
+ */
+ void DispatchPass(CompilationUnit* c_unit, Pass* pass);
+
+ void PrintPassNames() const;
+
+ Pass* GetPass(const std::string& name) const;
+
+ const char *GetDumpCFGFolder() const {
+ return dump_cfg_folder_;
+ }
+
+ protected:
+ void CreatePasses();
+
+ /** @brief The Pass Map: contains name -> pass for quick lookup. */
+ SafeMap<std::string, Pass*> pass_map_;
+
+ /** @brief List of passes: provides the order to execute the passes. */
+ std::list<Pass*> pass_list_;
+
+ /** @brief The CompilationUnit on which to execute the passes on. */
+ CompilationUnit* const cu_;
+
+ /** @brief Dump CFG base folder: where is the base folder for dumping CFGs. */
+ const char* dump_cfg_folder_;
+};
+
+} // namespace art
+#endif // ART_COMPILER_DEX_PASS_DRIVER_H_
diff --git a/compiler/dex/ssa_transformation.cc b/compiler/dex/ssa_transformation.cc
index 0d8bd07..502df1e 100644
--- a/compiler/dex/ssa_transformation.cc
+++ b/compiler/dex/ssa_transformation.cc
@@ -669,46 +669,4 @@
return;
}
-/* Perform SSA transformation for the whole method */
-void MIRGraph::SSATransformation() {
- /* 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());
-
- /*
- * Shared temp bit vector used by each block to count the number of defs
- * from all the predecessor blocks.
- */
- temp_ssa_register_v_ =
- new (arena_) ArenaBitVector(arena_, GetNumSSARegs(), false, kBitMapTempSSARegisterV);
-
- /* Insert phi-operands with latest SSA names from predecessor blocks */
- PreOrderDfsIterator iter2(this);
- for (BasicBlock* bb = iter2.Next(); bb != NULL; bb = iter2.Next()) {
- InsertPhiNodeOperands(bb);
- }
-
- if (cu_->enable_debug & (1 << kDebugDumpCFG)) {
- DumpCFG("/sdcard/3_post_ssa_cfg/", false);
- }
- if (cu_->enable_debug & (1 << kDebugVerifyDataflow)) {
- VerifyDataflow();
- }
-}
-
} // namespace art