/* * 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 "dex/quick/mir_to_lir.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(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(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(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(PassDataHolder* data) const; }; /** * @class CalculatePredecessors * @brief Calculate the predecessor BitVector of each Basicblock. */ class CalculatePredecessors : public PassME { public: CalculatePredecessors() : PassME("CalculatePredecessors") { } void Start(PassDataHolder* data) const; }; /** * @class DFSOrders * @brief Compute the DFS order of the MIR graph */ class DFSOrders : public PassME { public: DFSOrders() : PassME("DFSOrders") { } void Start(PassDataHolder* data) const { DCHECK(data != nullptr); CompilationUnit* c_unit = down_cast(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(PassDataHolder* data) const { DCHECK(data != nullptr); CompilationUnit* c_unit = down_cast(data)->c_unit; DCHECK(c_unit != nullptr); c_unit->mir_graph.get()->ComputeDominators(); c_unit->mir_graph.get()->CompilerInitializeSSAConversion(); } void End(PassDataHolder* data) const { DCHECK(data != nullptr); CompilationUnit* c_unit = down_cast(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 TopologicalSortOrders * @brief Compute the topological sort order of the MIR graph */ class TopologicalSortOrders : public PassME { public: TopologicalSortOrders() : PassME("TopologicalSortOrders") { } void Start(PassDataHolder* data) const { DCHECK(data != nullptr); CompilationUnit* c_unit = down_cast(data)->c_unit; DCHECK(c_unit != nullptr); c_unit->mir_graph.get()->ComputeTopologicalSortOrder(); } }; /** * @class DefBlockMatrix * @brief Calculate the matrix of definition per basic block */ class DefBlockMatrix : public PassME { public: DefBlockMatrix() : PassME("DefBlockMatrix") { } void Start(PassDataHolder* data) const { DCHECK(data != nullptr); CompilationUnit* c_unit = down_cast(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(PassDataHolder* data) const { DCHECK(data != nullptr); CompilationUnit* c_unit = down_cast(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(PassDataHolder* data) const { DCHECK(data != nullptr); CompilationUnit* c_unit = down_cast(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(PassDataHolder* data) const { DCHECK(data != nullptr); CompilationUnit* c_unit = down_cast(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(PassDataHolder* data) const { DCHECK(data != nullptr); CompilationUnit* c_unit = down_cast(data)->c_unit; DCHECK(c_unit != nullptr); BasicBlock* bb = down_cast(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(PassDataHolder* data) const { DCHECK(data != nullptr); CompilationUnit* c_unit = down_cast(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(PassDataHolder* data) const { DCHECK(data != nullptr); CompilationUnit* c_unit = down_cast(data)->c_unit; DCHECK(c_unit != nullptr); BasicBlock* bb = down_cast(data)->bb; DCHECK(bb != nullptr); c_unit->mir_graph->DoConstantPropagation(bb); // No need of repeating, so just return false. return false; } void Start(PassDataHolder* data) const { DCHECK(data != nullptr); CompilationUnit* c_unit = down_cast(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(PassDataHolder* data) const { DCHECK(data != nullptr); CompilationUnit* c_unit = down_cast(data)->c_unit; DCHECK(c_unit != nullptr); c_unit->mir_graph.get()->SSATransformationEnd(); } }; } // namespace art #endif // ART_COMPILER_DEX_POST_OPT_PASSES_H_