1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker #ifndef ART_COMPILER_OPTIMIZING_DEAD_CODE_ELIMINATION_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_OPTIMIZING_DEAD_CODE_ELIMINATION_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include "base/macros.h" 21*795d594fSAndroid Build Coastguard Worker #include "nodes.h" 22*795d594fSAndroid Build Coastguard Worker #include "optimization.h" 23*795d594fSAndroid Build Coastguard Worker #include "optimizing_compiler_stats.h" 24*795d594fSAndroid Build Coastguard Worker 25*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN { 26*795d594fSAndroid Build Coastguard Worker 27*795d594fSAndroid Build Coastguard Worker /** 28*795d594fSAndroid Build Coastguard Worker * Optimization pass performing dead code elimination (removal of 29*795d594fSAndroid Build Coastguard Worker * unused variables/instructions) on the SSA form. 30*795d594fSAndroid Build Coastguard Worker */ 31*795d594fSAndroid Build Coastguard Worker class HDeadCodeElimination : public HOptimization { 32*795d594fSAndroid Build Coastguard Worker public: HDeadCodeElimination(HGraph * graph,OptimizingCompilerStats * stats,const char * name)33*795d594fSAndroid Build Coastguard Worker HDeadCodeElimination(HGraph* graph, OptimizingCompilerStats* stats, const char* name) 34*795d594fSAndroid Build Coastguard Worker : HOptimization(graph, name, stats) {} 35*795d594fSAndroid Build Coastguard Worker 36*795d594fSAndroid Build Coastguard Worker bool Run() override; 37*795d594fSAndroid Build Coastguard Worker 38*795d594fSAndroid Build Coastguard Worker static constexpr const char* kDeadCodeEliminationPassName = "dead_code_elimination"; 39*795d594fSAndroid Build Coastguard Worker 40*795d594fSAndroid Build Coastguard Worker private: 41*795d594fSAndroid Build Coastguard Worker void MaybeRecordDeadBlock(HBasicBlock* block); 42*795d594fSAndroid Build Coastguard Worker void MaybeRecordSimplifyIf(); 43*795d594fSAndroid Build Coastguard Worker // Detects and remove ifs that are empty e.g. it turns 44*795d594fSAndroid Build Coastguard Worker // 1 45*795d594fSAndroid Build Coastguard Worker // / \ 46*795d594fSAndroid Build Coastguard Worker // 2 3 47*795d594fSAndroid Build Coastguard Worker // \ / 48*795d594fSAndroid Build Coastguard Worker // 4 49*795d594fSAndroid Build Coastguard Worker // where 2 and 3 are single goto blocks and 4 doesn't contain a Phi into: 50*795d594fSAndroid Build Coastguard Worker // 1 51*795d594fSAndroid Build Coastguard Worker // | 52*795d594fSAndroid Build Coastguard Worker // 4 53*795d594fSAndroid Build Coastguard Worker bool RemoveEmptyIfs(); 54*795d594fSAndroid Build Coastguard Worker // If `force_recomputation` is true, we will recompute the dominance information even when we 55*795d594fSAndroid Build Coastguard Worker // didn't delete any blocks. `force_loop_recomputation` is similar but it also forces the loop 56*795d594fSAndroid Build Coastguard Worker // information recomputation. 57*795d594fSAndroid Build Coastguard Worker bool RemoveDeadBlocks(bool force_recomputation = false, bool force_loop_recomputation = false); 58*795d594fSAndroid Build Coastguard Worker void RemoveDeadInstructions(); 59*795d594fSAndroid Build Coastguard Worker bool SimplifyAlwaysThrows(); 60*795d594fSAndroid Build Coastguard Worker // Simplify the pattern: 61*795d594fSAndroid Build Coastguard Worker // 62*795d594fSAndroid Build Coastguard Worker // B1 B2 ... 63*795d594fSAndroid Build Coastguard Worker // goto goto goto 64*795d594fSAndroid Build Coastguard Worker // \ | / 65*795d594fSAndroid Build Coastguard Worker // \ | / 66*795d594fSAndroid Build Coastguard Worker // B3 67*795d594fSAndroid Build Coastguard Worker // i1 = phi(input, input) 68*795d594fSAndroid Build Coastguard Worker // (i2 = condition on i1) 69*795d594fSAndroid Build Coastguard Worker // if i1 (or i2) 70*795d594fSAndroid Build Coastguard Worker // / \ 71*795d594fSAndroid Build Coastguard Worker // / \ 72*795d594fSAndroid Build Coastguard Worker // B4 B5 73*795d594fSAndroid Build Coastguard Worker // 74*795d594fSAndroid Build Coastguard Worker // Into: 75*795d594fSAndroid Build Coastguard Worker // 76*795d594fSAndroid Build Coastguard Worker // B1 B2 ... 77*795d594fSAndroid Build Coastguard Worker // | | | 78*795d594fSAndroid Build Coastguard Worker // B4 B5 B? 79*795d594fSAndroid Build Coastguard Worker // 80*795d594fSAndroid Build Coastguard Worker // Note that individual edges can be redirected (for example B2->B3 81*795d594fSAndroid Build Coastguard Worker // can be redirected as B2->B5) without applying this optimization 82*795d594fSAndroid Build Coastguard Worker // to other incoming edges. 83*795d594fSAndroid Build Coastguard Worker // 84*795d594fSAndroid Build Coastguard Worker // Note that we rely on the dead code elimination to get rid of B3. 85*795d594fSAndroid Build Coastguard Worker bool SimplifyIfs(); 86*795d594fSAndroid Build Coastguard Worker void ConnectSuccessiveBlocks(); 87*795d594fSAndroid Build Coastguard Worker // Updates the graph flags related to instructions (e.g. HasSIMD()) since we may have eliminated 88*795d594fSAndroid Build Coastguard Worker // the relevant instructions. There's no need to update `SetHasTryCatch` since we do that in 89*795d594fSAndroid Build Coastguard Worker // `ComputeTryBlockInformation`. Similarly with `HasLoops` and `HasIrreducibleLoops`: They are 90*795d594fSAndroid Build Coastguard Worker // cleared in `ClearLoopInformation` and then set as true as part of `HLoopInformation::Populate`, 91*795d594fSAndroid Build Coastguard Worker // if needed. 92*795d594fSAndroid Build Coastguard Worker void UpdateGraphFlags(); 93*795d594fSAndroid Build Coastguard Worker 94*795d594fSAndroid Build Coastguard Worker // Helper struct to eliminate tries. 95*795d594fSAndroid Build Coastguard Worker struct TryBelongingInformation; 96*795d594fSAndroid Build Coastguard Worker // Disconnects `block`'s handlers and update its `TryBoundary` instruction to a `Goto`. 97*795d594fSAndroid Build Coastguard Worker // Sets `any_block_in_loop` to true if any block is currently a loop to later update the loop 98*795d594fSAndroid Build Coastguard Worker // information if needed. 99*795d594fSAndroid Build Coastguard Worker void DisconnectHandlersAndUpdateTryBoundary(HBasicBlock* block, 100*795d594fSAndroid Build Coastguard Worker /* out */ bool* any_block_in_loop); 101*795d594fSAndroid Build Coastguard Worker // Returns true iff the try doesn't contain throwing instructions. 102*795d594fSAndroid Build Coastguard Worker bool CanPerformTryRemoval(const TryBelongingInformation& try_belonging_info); 103*795d594fSAndroid Build Coastguard Worker // Removes the try by disconnecting all try entries and exits from their handlers. Also updates 104*795d594fSAndroid Build Coastguard Worker // the graph in the case that a `TryBoundary` instruction of kind `exit` has the Exit block as 105*795d594fSAndroid Build Coastguard Worker // its successor. 106*795d594fSAndroid Build Coastguard Worker void RemoveTry(HBasicBlock* try_entry, 107*795d594fSAndroid Build Coastguard Worker const TryBelongingInformation& try_belonging_info, 108*795d594fSAndroid Build Coastguard Worker bool* any_block_in_loop); 109*795d594fSAndroid Build Coastguard Worker // Checks which tries (if any) are currently in the graph, coalesces the different try entries 110*795d594fSAndroid Build Coastguard Worker // that are referencing the same try, and removes the tries which don't contain any throwing 111*795d594fSAndroid Build Coastguard Worker // instructions. 112*795d594fSAndroid Build Coastguard Worker bool RemoveUnneededTries(); 113*795d594fSAndroid Build Coastguard Worker 114*795d594fSAndroid Build Coastguard Worker // Adds a phi in `block`, if `block` and its dominator have the same (or opposite) condition. 115*795d594fSAndroid Build Coastguard Worker // For example it turns: 116*795d594fSAndroid Build Coastguard Worker // if(cond) 117*795d594fSAndroid Build Coastguard Worker // / \ 118*795d594fSAndroid Build Coastguard Worker // B1 B2 119*795d594fSAndroid Build Coastguard Worker // \ / 120*795d594fSAndroid Build Coastguard Worker // if(cond) 121*795d594fSAndroid Build Coastguard Worker // / \ 122*795d594fSAndroid Build Coastguard Worker // B3 B4 123*795d594fSAndroid Build Coastguard Worker // 124*795d594fSAndroid Build Coastguard Worker // into: 125*795d594fSAndroid Build Coastguard Worker // if(cond) 126*795d594fSAndroid Build Coastguard Worker // / \ 127*795d594fSAndroid Build Coastguard Worker // B1 B2 128*795d594fSAndroid Build Coastguard Worker // \ / 129*795d594fSAndroid Build Coastguard Worker // if(Phi(1, 0)) 130*795d594fSAndroid Build Coastguard Worker // / \ 131*795d594fSAndroid Build Coastguard Worker // B3 B4 132*795d594fSAndroid Build Coastguard Worker // 133*795d594fSAndroid Build Coastguard Worker // Following this, SimplifyIfs is able to connect B1->B3 and B2->B4 effectively skipping an if. 134*795d594fSAndroid Build Coastguard Worker void MaybeAddPhi(HBasicBlock* block); 135*795d594fSAndroid Build Coastguard Worker 136*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(HDeadCodeElimination); 137*795d594fSAndroid Build Coastguard Worker }; 138*795d594fSAndroid Build Coastguard Worker 139*795d594fSAndroid Build Coastguard Worker } // namespace art 140*795d594fSAndroid Build Coastguard Worker 141*795d594fSAndroid Build Coastguard Worker #endif // ART_COMPILER_OPTIMIZING_DEAD_CODE_ELIMINATION_H_ 142