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* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
     37     DCHECK(c_unit != nullptr);
     38     c_unit->mir_graph->DoCacheFieldLoweringInfo();
     39   }
     40 
     41   bool Gate(const PassDataHolder* data) const {
     42     DCHECK(data != nullptr);
     43     CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
     44     DCHECK(c_unit != nullptr);
     45     return c_unit->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* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
     61     DCHECK(c_unit != nullptr);
     62     c_unit->mir_graph->DoCacheMethodLoweringInfo();
     63   }
     64 
     65   bool Gate(const PassDataHolder* data) const {
     66     DCHECK(data != nullptr);
     67     CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
     68     DCHECK(c_unit != nullptr);
     69     return c_unit->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* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
     87     DCHECK(c_unit != nullptr);
     88     return c_unit->mir_graph->InlineSpecialMethodsGate();
     89   }
     90 
     91   void Start(PassDataHolder* data) const {
     92     DCHECK(data != nullptr);
     93     CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
     94     DCHECK(c_unit != nullptr);
     95     c_unit->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* c_unit = pass_me_data_holder->c_unit;
    102     DCHECK(c_unit != nullptr);
    103     BasicBlock* bb = pass_me_data_holder->bb;
    104     DCHECK(bb != nullptr);
    105     c_unit->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* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
    113     DCHECK(c_unit != nullptr);
    114     c_unit->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* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
    130     DCHECK(c_unit != nullptr);
    131     c_unit->mir_graph->VerifyDataflow();
    132     c_unit->mir_graph->ClearAllVisitedFlags();
    133   }
    134 
    135   bool Worker(const PassDataHolder* data) const;
    136 };
    137 
    138 /**
    139  * @class NullCheckEliminationAndTypeInference
    140  * @brief Null check elimination and type inference.
    141  */
    142 class NullCheckEliminationAndTypeInference : public PassME {
    143  public:
    144   NullCheckEliminationAndTypeInference()
    145     : PassME("NCE_TypeInference", kRepeatingTopologicalSortTraversal, "4_post_nce_cfg") {
    146   }
    147 
    148   void Start(PassDataHolder* data) const {
    149     DCHECK(data != nullptr);
    150     CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
    151     DCHECK(c_unit != nullptr);
    152     c_unit->mir_graph->EliminateNullChecksAndInferTypesStart();
    153   }
    154 
    155   bool Worker(const PassDataHolder* data) const {
    156     DCHECK(data != nullptr);
    157     const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data);
    158     CompilationUnit* c_unit = pass_me_data_holder->c_unit;
    159     DCHECK(c_unit != nullptr);
    160     BasicBlock* bb = pass_me_data_holder->bb;
    161     DCHECK(bb != nullptr);
    162     return c_unit->mir_graph->EliminateNullChecksAndInferTypes(bb);
    163   }
    164 
    165   void End(PassDataHolder* data) const {
    166     DCHECK(data != nullptr);
    167     CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
    168     DCHECK(c_unit != nullptr);
    169     c_unit->mir_graph->EliminateNullChecksAndInferTypesEnd();
    170   }
    171 };
    172 
    173 class ClassInitCheckElimination : public PassME {
    174  public:
    175   ClassInitCheckElimination()
    176     : PassME("ClInitCheckElimination", kLoopRepeatingTopologicalSortTraversal) {
    177   }
    178 
    179   bool Gate(const PassDataHolder* data) const {
    180     DCHECK(data != nullptr);
    181     CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
    182     DCHECK(c_unit != nullptr);
    183     return c_unit->mir_graph->EliminateClassInitChecksGate();
    184   }
    185 
    186   bool Worker(const PassDataHolder* data) const {
    187     DCHECK(data != nullptr);
    188     const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data);
    189     CompilationUnit* c_unit = pass_me_data_holder->c_unit;
    190     DCHECK(c_unit != nullptr);
    191     BasicBlock* bb = pass_me_data_holder->bb;
    192     DCHECK(bb != nullptr);
    193     return c_unit->mir_graph->EliminateClassInitChecks(bb);
    194   }
    195 
    196   void End(PassDataHolder* data) const {
    197     DCHECK(data != nullptr);
    198     CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
    199     DCHECK(c_unit != nullptr);
    200     c_unit->mir_graph->EliminateClassInitChecksEnd();
    201   }
    202 };
    203 
    204 /**
    205  * @class GlobalValueNumberingPass
    206  * @brief Performs the global value numbering pass.
    207  */
    208 class GlobalValueNumberingPass : public PassME {
    209  public:
    210   GlobalValueNumberingPass()
    211     : PassME("GVN", kLoopRepeatingTopologicalSortTraversal, "4_post_gvn_cfg") {
    212   }
    213 
    214   bool Gate(const PassDataHolder* data) const OVERRIDE {
    215     DCHECK(data != nullptr);
    216     CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
    217     DCHECK(c_unit != nullptr);
    218     return c_unit->mir_graph->ApplyGlobalValueNumberingGate();
    219   }
    220 
    221   bool Worker(const PassDataHolder* data) const OVERRIDE {
    222     DCHECK(data != nullptr);
    223     const PassMEDataHolder* pass_me_data_holder = down_cast<const PassMEDataHolder*>(data);
    224     CompilationUnit* c_unit = pass_me_data_holder->c_unit;
    225     DCHECK(c_unit != nullptr);
    226     BasicBlock* bb = pass_me_data_holder->bb;
    227     DCHECK(bb != nullptr);
    228     return c_unit->mir_graph->ApplyGlobalValueNumbering(bb);
    229   }
    230 
    231   void End(PassDataHolder* data) const OVERRIDE {
    232     DCHECK(data != nullptr);
    233     CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
    234     DCHECK(c_unit != nullptr);
    235     c_unit->mir_graph->ApplyGlobalValueNumberingEnd();
    236   }
    237 };
    238 
    239 /**
    240  * @class BBCombine
    241  * @brief Perform the basic block combination pass.
    242  */
    243 class BBCombine : public PassME {
    244  public:
    245   BBCombine() : PassME("BBCombine", kPreOrderDFSTraversal, "5_post_bbcombine_cfg") {
    246   }
    247 
    248   bool Gate(const PassDataHolder* data) const {
    249     DCHECK(data != nullptr);
    250     CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
    251     DCHECK(c_unit != nullptr);
    252     return ((c_unit->disable_opt & (1 << kSuppressExceptionEdges)) != 0);
    253   }
    254 
    255   bool Worker(const PassDataHolder* data) const;
    256 };
    257 
    258 /**
    259  * @class BasicBlock Optimizations
    260  * @brief Any simple BasicBlock optimization can be put here.
    261  */
    262 class BBOptimizations : public PassME {
    263  public:
    264   BBOptimizations() : PassME("BBOptimizations", kNoNodes, "5_post_bbo_cfg") {
    265   }
    266 
    267   bool Gate(const PassDataHolder* data) const {
    268     DCHECK(data != nullptr);
    269     CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
    270     DCHECK(c_unit != nullptr);
    271     return ((c_unit->disable_opt & (1 << kBBOpt)) == 0);
    272   }
    273 
    274   void Start(PassDataHolder* data) const;
    275 };
    276 
    277 }  // namespace art
    278 
    279 #endif  // ART_COMPILER_DEX_BB_OPTIMIZATIONS_H_
    280