xref: /aosp_15_r20/art/compiler/optimizing/dead_code_elimination.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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