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_BB_OPTIMIZATIONS_H_
     18 #define ART_COMPILER_DEX_BB_OPTIMIZATIONS_H_
     19 
     20 #include "compiler_internals.h"
     21 #include "pass_me.h"
     22 
     23 namespace art {
     24 
     25 /**
     26  * @class CacheFieldLoweringInfo
     27  * @brief Cache the lowering info for fields used by IGET/IPUT/SGET/SPUT insns.
     28  */
     29 class CacheFieldLoweringInfo : public PassME {
     30  public:
     31   CacheFieldLoweringInfo() : PassME("CacheFieldLoweringInfo", kNoNodes) {
     32   }
     33 
     34   void Start(PassDataHolder* data) const {
     35     DCHECK(data != nullptr);
     36     CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
     37     DCHECK(cUnit != nullptr);
     38     cUnit->mir_graph->DoCacheFieldLoweringInfo();
     39   }
     40 
     41   bool Gate(const PassDataHolder* data) const {
     42     DCHECK(data != nullptr);
     43     CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
     44     DCHECK(cUnit != nullptr);
     45     return cUnit->mir_graph->HasFieldAccess();
     46   }
     47 };
     48 
     49 /**
     50  * @class CacheMethodLoweringInfo
     51  * @brief Cache the lowering info for methods called by INVOKEs.
     52  */
     53 class CacheMethodLoweringInfo : public PassME {
     54  public:
     55   CacheMethodLoweringInfo() : PassME("CacheMethodLoweringInfo", kNoNodes) {
     56   }
     57 
     58   void Start(PassDataHolder* data) const {
     59     DCHECK(data != nullptr);
     60     CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
     61     DCHECK(cUnit != nullptr);
     62     cUnit->mir_graph->DoCacheMethodLoweringInfo();
     63   }
     64 
     65   bool Gate(const PassDataHolder* data) const {
     66     DCHECK(data != nullptr);
     67     CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
     68     DCHECK(cUnit != nullptr);
     69     return cUnit->mir_graph->HasInvokes();
     70   }
     71 };
     72 
     73 /**
     74  * @class SpecialMethodInliner
     75  * @brief Performs method inlining pass on special kinds of methods.
     76  * @details Special methods are methods that fall in one of the following categories:
     77  * empty, instance getter, instance setter, argument return, and constant return.
     78  */
     79 class SpecialMethodInliner : public PassME {
     80  public:
     81   SpecialMethodInliner() : PassME("SpecialMethodInliner") {
     82   }
     83 
     84   bool Gate(const PassDataHolder* data) const {
     85     DCHECK(data != nullptr);
     86     CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
     87     DCHECK(cUnit != nullptr);
     88     return cUnit->mir_graph->InlineSpecialMethodsGate();
     89   }
     90 
     91   void Start(PassDataHolder* data) const {
     92     DCHECK(data != nullptr);
     93     CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
     94     DCHECK(cUnit != nullptr);
     95     cUnit->mir_graph->InlineSpecialMethodsStart();
     96   }
     97 
     98   bool Worker(const PassDataHolder* data) const {
     99     DCHECK(data != nullptr);
    100     const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data);
    101     CompilationUnit* cUnit = pass_me_data_holder->c_unit;
    102     DCHECK(cUnit != nullptr);
    103     BasicBlock* bb = pass_me_data_holder->bb;
    104     DCHECK(bb != nullptr);
    105     cUnit->mir_graph->InlineSpecialMethods(bb);
    106     // No need of repeating, so just return false.
    107     return false;
    108   }
    109 
    110   void End(PassDataHolder* data) const {
    111     DCHECK(data != nullptr);
    112     CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
    113     DCHECK(cUnit != nullptr);
    114     cUnit->mir_graph->InlineSpecialMethodsEnd();
    115   }
    116 };
    117 
    118 /**
    119  * @class CodeLayout
    120  * @brief Perform the code layout pass.
    121  */
    122 class CodeLayout : public PassME {
    123  public:
    124   CodeLayout() : PassME("CodeLayout", kAllNodes, kOptimizationBasicBlockChange, "2_post_layout_cfg") {
    125   }
    126 
    127   void Start(PassDataHolder* data) const {
    128     DCHECK(data != nullptr);
    129     CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
    130     DCHECK(cUnit != nullptr);
    131     cUnit->mir_graph->VerifyDataflow();
    132   }
    133 
    134   bool Worker(const PassDataHolder* data) const;
    135 };
    136 
    137 /**
    138  * @class NullCheckEliminationAndTypeInference
    139  * @brief Null check elimination and type inference.
    140  */
    141 class NullCheckEliminationAndTypeInference : public PassME {
    142  public:
    143   NullCheckEliminationAndTypeInference()
    144     : PassME("NCE_TypeInference", kRepeatingTopologicalSortTraversal, "4_post_nce_cfg") {
    145   }
    146 
    147   void Start(PassDataHolder* data) const {
    148     DCHECK(data != nullptr);
    149     CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
    150     DCHECK(cUnit != nullptr);
    151     cUnit->mir_graph->EliminateNullChecksAndInferTypesStart();
    152   }
    153 
    154   bool Worker(const PassDataHolder* data) const {
    155     DCHECK(data != nullptr);
    156     const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data);
    157     CompilationUnit* cUnit = pass_me_data_holder->c_unit;
    158     DCHECK(cUnit != nullptr);
    159     BasicBlock* bb = pass_me_data_holder->bb;
    160     DCHECK(bb != nullptr);
    161     return cUnit->mir_graph->EliminateNullChecksAndInferTypes(bb);
    162   }
    163 
    164   void End(PassDataHolder* data) const {
    165     DCHECK(data != nullptr);
    166     CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
    167     DCHECK(cUnit != nullptr);
    168     cUnit->mir_graph->EliminateNullChecksAndInferTypesEnd();
    169   }
    170 };
    171 
    172 class ClassInitCheckElimination : public PassME {
    173  public:
    174   ClassInitCheckElimination()
    175     : PassME("ClInitCheckElimination", kLoopRepeatingTopologicalSortTraversal) {
    176   }
    177 
    178   bool Gate(const PassDataHolder* data) const {
    179     DCHECK(data != nullptr);
    180     CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
    181     DCHECK(cUnit != nullptr);
    182     return cUnit->mir_graph->EliminateClassInitChecksGate();
    183   }
    184 
    185   bool Worker(const PassDataHolder* data) const {
    186     DCHECK(data != nullptr);
    187     const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data);
    188     CompilationUnit* cUnit = pass_me_data_holder->c_unit;
    189     DCHECK(cUnit != nullptr);
    190     BasicBlock* bb = pass_me_data_holder->bb;
    191     DCHECK(bb != nullptr);
    192     return cUnit->mir_graph->EliminateClassInitChecks(bb);
    193   }
    194 
    195   void End(PassDataHolder* data) const {
    196     DCHECK(data != nullptr);
    197     CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
    198     DCHECK(cUnit != nullptr);
    199     cUnit->mir_graph->EliminateClassInitChecksEnd();
    200   }
    201 };
    202 
    203 /**
    204  * @class GlobalValueNumberingPass
    205  * @brief Performs the global value numbering pass.
    206  */
    207 class GlobalValueNumberingPass : public PassME {
    208  public:
    209   GlobalValueNumberingPass()
    210     : PassME("GVN", kLoopRepeatingTopologicalSortTraversal, "4_post_gvn_cfg") {
    211   }
    212 
    213   bool Gate(const PassDataHolder* data) const OVERRIDE {
    214     DCHECK(data != nullptr);
    215     CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
    216     DCHECK(cUnit != nullptr);
    217     return cUnit->mir_graph->ApplyGlobalValueNumberingGate();
    218   }
    219 
    220   bool Worker(const PassDataHolder* data) const OVERRIDE {
    221     DCHECK(data != nullptr);
    222     const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data);
    223     CompilationUnit* cUnit = pass_me_data_holder->c_unit;
    224     DCHECK(cUnit != nullptr);
    225     BasicBlock* bb = pass_me_data_holder->bb;
    226     DCHECK(bb != nullptr);
    227     return cUnit->mir_graph->ApplyGlobalValueNumbering(bb);
    228   }
    229 
    230   void End(PassDataHolder* data) const OVERRIDE {
    231     DCHECK(data != nullptr);
    232     CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
    233     DCHECK(cUnit != nullptr);
    234     cUnit->mir_graph->ApplyGlobalValueNumberingEnd();
    235   }
    236 };
    237 
    238 /**
    239  * @class BBCombine
    240  * @brief Perform the basic block combination pass.
    241  */
    242 class BBCombine : public PassME {
    243  public:
    244   BBCombine() : PassME("BBCombine", kPreOrderDFSTraversal, "5_post_bbcombine_cfg") {
    245   }
    246 
    247   bool Gate(const PassDataHolder* data) const {
    248     DCHECK(data != nullptr);
    249     CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
    250     DCHECK(cUnit != nullptr);
    251     return ((cUnit->disable_opt & (1 << kSuppressExceptionEdges)) != 0);
    252   }
    253 
    254   bool Worker(const PassDataHolder* data) const;
    255 };
    256 
    257 /**
    258  * @class BasicBlock Optimizations
    259  * @brief Any simple BasicBlock optimization can be put here.
    260  */
    261 class BBOptimizations : public PassME {
    262  public:
    263   BBOptimizations() : PassME("BBOptimizations", kNoNodes, "5_post_bbo_cfg") {
    264   }
    265 
    266   bool Gate(const PassDataHolder* data) const {
    267     DCHECK(data != nullptr);
    268     CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
    269     DCHECK(cUnit != nullptr);
    270     return ((cUnit->disable_opt & (1 << kBBOpt)) == 0);
    271   }
    272 
    273   void Start(PassDataHolder* data) const;
    274 };
    275 
    276 }  // namespace art
    277 
    278 #endif  // ART_COMPILER_DEX_BB_OPTIMIZATIONS_H_
    279