Home | History | Annotate | Download | only in dex
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ART_COMPILER_DEX_POST_OPT_PASSES_H_
     18 #define ART_COMPILER_DEX_POST_OPT_PASSES_H_
     19 
     20 #include "compiler_internals.h"
     21 #include "pass_me.h"
     22 
     23 namespace art {
     24 
     25 /**
     26  * @class InitializeData
     27  * @brief There is some data that needs to be initialized before performing
     28  * the post optimization passes.
     29  */
     30 class InitializeData : public PassME {
     31  public:
     32   InitializeData() : PassME("InitializeData") {
     33   }
     34 
     35   void Start(PassDataHolder* data) const {
     36     // New blocks may have been inserted so the first thing we do is ensure that
     37     // the c_unit's number of blocks matches the actual count of basic blocks.
     38     DCHECK(data != nullptr);
     39     CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
     40     DCHECK(c_unit != nullptr);
     41     c_unit->mir_graph.get()->InitializeBasicBlockData();
     42     c_unit->mir_graph.get()->SSATransformationStart();
     43   }
     44 };
     45 
     46 /**
     47  * @class MethodUseCount
     48  * @brief Count the register uses of the method
     49  */
     50 class MethodUseCount : public PassME {
     51  public:
     52   MethodUseCount() : PassME("UseCount") {
     53   }
     54 
     55   bool Worker(const PassDataHolder* data) const;
     56 
     57   bool Gate(const PassDataHolder* data) const;
     58 };
     59 
     60 /**
     61  * @class ClearPhiInformation
     62  * @brief Clear the PHI nodes from the CFG.
     63  */
     64 class ClearPhiInstructions : public PassME {
     65  public:
     66   ClearPhiInstructions() : PassME("ClearPhiInstructions") {
     67   }
     68 
     69   bool Worker(const PassDataHolder* data) const;
     70 };
     71 
     72 /**
     73  * @class CalculatePredecessors
     74  * @brief Calculate the predecessor BitVector of each Basicblock.
     75  */
     76 class CalculatePredecessors : public PassME {
     77  public:
     78   CalculatePredecessors() : PassME("CalculatePredecessors") {
     79   }
     80 
     81   void Start(PassDataHolder* data) const;
     82 };
     83 
     84 /**
     85  * @class DFSOrders
     86  * @brief Compute the DFS order of the MIR graph
     87  */
     88 class DFSOrders : public PassME {
     89  public:
     90   DFSOrders() : PassME("DFSOrders") {
     91   }
     92 
     93   void Start(PassDataHolder* data) const {
     94     DCHECK(data != nullptr);
     95     CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
     96     DCHECK(c_unit != nullptr);
     97     c_unit->mir_graph.get()->ComputeDFSOrders();
     98   }
     99 };
    100 
    101 /**
    102  * @class BuildDomination
    103  * @brief Build the domination information of the MIR Graph
    104  */
    105 class BuildDomination : public PassME {
    106  public:
    107   BuildDomination() : PassME("BuildDomination") {
    108   }
    109 
    110   void Start(PassDataHolder* data) const {
    111     DCHECK(data != nullptr);
    112     CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
    113     DCHECK(c_unit != nullptr);
    114     c_unit->mir_graph.get()->ComputeDominators();
    115     c_unit->mir_graph.get()->CompilerInitializeSSAConversion();
    116   }
    117 
    118   void End(PassDataHolder* data) const {
    119     DCHECK(data != nullptr);
    120     CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
    121     DCHECK(c_unit != nullptr);
    122     // Verify the dataflow information after the pass.
    123     if (c_unit->enable_debug & (1 << kDebugVerifyDataflow)) {
    124       c_unit->mir_graph->VerifyDataflow();
    125     }
    126   }
    127 };
    128 
    129 /**
    130  * @class TopologicalSortOrders
    131  * @brief Compute the topological sort order of the MIR graph
    132  */
    133 class TopologicalSortOrders : public PassME {
    134  public:
    135   TopologicalSortOrders() : PassME("TopologicalSortOrders") {
    136   }
    137 
    138   void Start(PassDataHolder* data) const {
    139     DCHECK(data != nullptr);
    140     CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
    141     DCHECK(c_unit != nullptr);
    142     c_unit->mir_graph.get()->ComputeTopologicalSortOrder();
    143   }
    144 };
    145 
    146 /**
    147  * @class DefBlockMatrix
    148  * @brief Calculate the matrix of definition per basic block
    149  */
    150 class DefBlockMatrix : public PassME {
    151  public:
    152   DefBlockMatrix() : PassME("DefBlockMatrix") {
    153   }
    154 
    155   void Start(PassDataHolder* data) const {
    156     DCHECK(data != nullptr);
    157     CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
    158     DCHECK(c_unit != nullptr);
    159     c_unit->mir_graph.get()->ComputeDefBlockMatrix();
    160   }
    161 };
    162 
    163 /**
    164  * @class CreatePhiNodes
    165  * @brief Pass to create the phi nodes after SSA calculation
    166  */
    167 class CreatePhiNodes : public PassME {
    168  public:
    169   CreatePhiNodes() : PassME("CreatePhiNodes") {
    170   }
    171 
    172   void Start(PassDataHolder* data) const {
    173     DCHECK(data != nullptr);
    174     CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
    175     DCHECK(c_unit != nullptr);
    176     c_unit->mir_graph.get()->InsertPhiNodes();
    177   }
    178 };
    179 
    180 /**
    181  * @class ClearVisitedFlag
    182  * @brief Pass to clear the visited flag for all basic blocks.
    183  */
    184 
    185 class ClearVisitedFlag : public PassME {
    186  public:
    187   ClearVisitedFlag() : PassME("ClearVisitedFlag") {
    188   }
    189 
    190   void Start(PassDataHolder* data) const {
    191     DCHECK(data != nullptr);
    192     CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
    193     DCHECK(c_unit != nullptr);
    194     c_unit->mir_graph.get()->ClearAllVisitedFlags();
    195   }
    196 };
    197 
    198 /**
    199  * @class SSAConversion
    200  * @brief Pass for SSA conversion of MIRs
    201  */
    202 class SSAConversion : public PassME {
    203  public:
    204   SSAConversion() : PassME("SSAConversion") {
    205   }
    206 
    207   void Start(PassDataHolder* data) const {
    208     DCHECK(data != nullptr);
    209     CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
    210     DCHECK(c_unit != nullptr);
    211     MIRGraph *mir_graph = c_unit->mir_graph.get();
    212     mir_graph->DoDFSPreOrderSSARename(mir_graph->GetEntryBlock());
    213   }
    214 };
    215 
    216 /**
    217  * @class PhiNodeOperands
    218  * @brief Pass to insert the Phi node operands to basic blocks
    219  */
    220 class PhiNodeOperands : public PassME {
    221  public:
    222   PhiNodeOperands() : PassME("PhiNodeOperands", kPreOrderDFSTraversal) {
    223   }
    224 
    225   bool Worker(const PassDataHolder* data) const {
    226     DCHECK(data != nullptr);
    227     CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
    228     DCHECK(c_unit != nullptr);
    229     BasicBlock* bb = down_cast<const PassMEDataHolder*>(data)->bb;
    230     DCHECK(bb != nullptr);
    231     c_unit->mir_graph->InsertPhiNodeOperands(bb);
    232     // No need of repeating, so just return false.
    233     return false;
    234   }
    235 };
    236 
    237 /**
    238  * @class InitRegLocations
    239  * @brief Initialize Register Locations.
    240  */
    241 class PerformInitRegLocations : public PassME {
    242  public:
    243   PerformInitRegLocations() : PassME("PerformInitRegLocation") {
    244   }
    245 
    246   void Start(PassDataHolder* data) const {
    247     DCHECK(data != nullptr);
    248     CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
    249     DCHECK(c_unit != nullptr);
    250     c_unit->mir_graph->InitRegLocations();
    251   }
    252 };
    253 
    254 /**
    255  * @class ConstantPropagation
    256  * @brief Perform a constant propagation pass.
    257  */
    258 class ConstantPropagation : public PassME {
    259  public:
    260   ConstantPropagation() : PassME("ConstantPropagation") {
    261   }
    262 
    263   bool Worker(const PassDataHolder* data) const {
    264     DCHECK(data != nullptr);
    265     CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
    266     DCHECK(c_unit != nullptr);
    267     BasicBlock* bb = down_cast<const PassMEDataHolder*>(data)->bb;
    268     DCHECK(bb != nullptr);
    269     c_unit->mir_graph->DoConstantPropagation(bb);
    270     // No need of repeating, so just return false.
    271     return false;
    272   }
    273 
    274   void Start(PassDataHolder* data) const {
    275     DCHECK(data != nullptr);
    276     CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
    277     DCHECK(c_unit != nullptr);
    278     c_unit->mir_graph->InitializeConstantPropagation();
    279   }
    280 };
    281 
    282 /**
    283  * @class FreeData
    284  * @brief There is some data that needs to be freed after performing the post optimization passes.
    285  */
    286 class FreeData : public PassME {
    287  public:
    288   FreeData() : PassME("FreeData") {
    289   }
    290 
    291   void End(PassDataHolder* data) const {
    292     DCHECK(data != nullptr);
    293     CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
    294     DCHECK(c_unit != nullptr);
    295     c_unit->mir_graph.get()->SSATransformationEnd();
    296   }
    297 };
    298 
    299 }  // namespace art
    300 
    301 #endif  // ART_COMPILER_DEX_POST_OPT_PASSES_H_
    302