xref: /aosp_15_r20/art/compiler/optimizing/select_generator.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2016 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 /*
18*795d594fSAndroid Build Coastguard Worker  * This optimization recognizes the common diamond selection pattern and
19*795d594fSAndroid Build Coastguard Worker  * replaces it with an instance of the HSelect instruction.
20*795d594fSAndroid Build Coastguard Worker  *
21*795d594fSAndroid Build Coastguard Worker  * Recognized patterns:
22*795d594fSAndroid Build Coastguard Worker  *
23*795d594fSAndroid Build Coastguard Worker  *          If [ Condition ]
24*795d594fSAndroid Build Coastguard Worker  *            /          \
25*795d594fSAndroid Build Coastguard Worker  *      false branch  true branch
26*795d594fSAndroid Build Coastguard Worker  *            \          /
27*795d594fSAndroid Build Coastguard Worker  *     Phi [FalseValue, TrueValue]
28*795d594fSAndroid Build Coastguard Worker  *
29*795d594fSAndroid Build Coastguard Worker  * and
30*795d594fSAndroid Build Coastguard Worker  *
31*795d594fSAndroid Build Coastguard Worker  *             If [ Condition ]
32*795d594fSAndroid Build Coastguard Worker  *               /          \
33*795d594fSAndroid Build Coastguard Worker  *     false branch        true branch
34*795d594fSAndroid Build Coastguard Worker  *     return FalseValue   return TrueValue
35*795d594fSAndroid Build Coastguard Worker  *
36*795d594fSAndroid Build Coastguard Worker  * The pattern will be simplified if `true_branch` and `false_branch` each
37*795d594fSAndroid Build Coastguard Worker  * contain at most one instruction without any side effects.
38*795d594fSAndroid Build Coastguard Worker  *
39*795d594fSAndroid Build Coastguard Worker  * Blocks are merged into one and Select replaces the If and the Phi.
40*795d594fSAndroid Build Coastguard Worker  *
41*795d594fSAndroid Build Coastguard Worker  * For the first pattern it simplifies to:
42*795d594fSAndroid Build Coastguard Worker  *
43*795d594fSAndroid Build Coastguard Worker  *              true branch
44*795d594fSAndroid Build Coastguard Worker  *              false branch
45*795d594fSAndroid Build Coastguard Worker  *              Select [FalseValue, TrueValue, Condition]
46*795d594fSAndroid Build Coastguard Worker  *
47*795d594fSAndroid Build Coastguard Worker  * For the second pattern it simplifies to:
48*795d594fSAndroid Build Coastguard Worker  *
49*795d594fSAndroid Build Coastguard Worker  *              true branch
50*795d594fSAndroid Build Coastguard Worker  *              false branch
51*795d594fSAndroid Build Coastguard Worker  *              return Select [FalseValue, TrueValue, Condition]
52*795d594fSAndroid Build Coastguard Worker  *
53*795d594fSAndroid Build Coastguard Worker  * Note: In order to recognize no side-effect blocks, this optimization must be
54*795d594fSAndroid Build Coastguard Worker  * run after the instruction simplifier has removed redundant suspend checks.
55*795d594fSAndroid Build Coastguard Worker  */
56*795d594fSAndroid Build Coastguard Worker 
57*795d594fSAndroid Build Coastguard Worker #ifndef ART_COMPILER_OPTIMIZING_SELECT_GENERATOR_H_
58*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_OPTIMIZING_SELECT_GENERATOR_H_
59*795d594fSAndroid Build Coastguard Worker 
60*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
61*795d594fSAndroid Build Coastguard Worker #include "base/scoped_arena_containers.h"
62*795d594fSAndroid Build Coastguard Worker #include "optimization.h"
63*795d594fSAndroid Build Coastguard Worker #include "optimizing/nodes.h"
64*795d594fSAndroid Build Coastguard Worker 
65*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
66*795d594fSAndroid Build Coastguard Worker 
67*795d594fSAndroid Build Coastguard Worker class HSelectGenerator : public HOptimization {
68*795d594fSAndroid Build Coastguard Worker  public:
69*795d594fSAndroid Build Coastguard Worker   HSelectGenerator(HGraph* graph,
70*795d594fSAndroid Build Coastguard Worker                    OptimizingCompilerStats* stats,
71*795d594fSAndroid Build Coastguard Worker                    const char* name = kSelectGeneratorPassName);
72*795d594fSAndroid Build Coastguard Worker 
73*795d594fSAndroid Build Coastguard Worker   bool Run() override;
74*795d594fSAndroid Build Coastguard Worker 
75*795d594fSAndroid Build Coastguard Worker   static constexpr const char* kSelectGeneratorPassName = "select_generator";
76*795d594fSAndroid Build Coastguard Worker 
77*795d594fSAndroid Build Coastguard Worker  private:
78*795d594fSAndroid Build Coastguard Worker   bool TryGenerateSelectSimpleDiamondPattern(HBasicBlock* block,
79*795d594fSAndroid Build Coastguard Worker                                              ScopedArenaSafeMap<HInstruction*, HSelect*>* cache);
80*795d594fSAndroid Build Coastguard Worker 
81*795d594fSAndroid Build Coastguard Worker   // When generating code for nested ternary operators (e.g. `return (x > 100) ? 100 : ((x < -100) ?
82*795d594fSAndroid Build Coastguard Worker   // -100 : x);`), a dexer can generate a double diamond pattern but it is not a clear cut one due
83*795d594fSAndroid Build Coastguard Worker   // to the merging of the blocks. `TryFixupDoubleDiamondPattern` recognizes that pattern and fixes
84*795d594fSAndroid Build Coastguard Worker   // up the graph to have a clean double diamond that `TryGenerateSelectSimpleDiamondPattern` can
85*795d594fSAndroid Build Coastguard Worker   // use to generate selects.
86*795d594fSAndroid Build Coastguard Worker   //
87*795d594fSAndroid Build Coastguard Worker   // In ASCII, it turns:
88*795d594fSAndroid Build Coastguard Worker   //
89*795d594fSAndroid Build Coastguard Worker   //      1 (outer if)
90*795d594fSAndroid Build Coastguard Worker   //     / \
91*795d594fSAndroid Build Coastguard Worker   //    2   3 (inner if)
92*795d594fSAndroid Build Coastguard Worker   //    |  / \
93*795d594fSAndroid Build Coastguard Worker   //    | 4  5
94*795d594fSAndroid Build Coastguard Worker   //     \/  |
95*795d594fSAndroid Build Coastguard Worker   //      6  |
96*795d594fSAndroid Build Coastguard Worker   //       \ |
97*795d594fSAndroid Build Coastguard Worker   //         7
98*795d594fSAndroid Build Coastguard Worker   //         |
99*795d594fSAndroid Build Coastguard Worker   //         8
100*795d594fSAndroid Build Coastguard Worker   // into:
101*795d594fSAndroid Build Coastguard Worker   //      1 (outer if)
102*795d594fSAndroid Build Coastguard Worker   //     / \
103*795d594fSAndroid Build Coastguard Worker   //    2   3 (inner if)
104*795d594fSAndroid Build Coastguard Worker   //    |  / \
105*795d594fSAndroid Build Coastguard Worker   //    | 4  5
106*795d594fSAndroid Build Coastguard Worker   //     \/ /
107*795d594fSAndroid Build Coastguard Worker   //      6
108*795d594fSAndroid Build Coastguard Worker   //      |
109*795d594fSAndroid Build Coastguard Worker   //      8
110*795d594fSAndroid Build Coastguard Worker   //
111*795d594fSAndroid Build Coastguard Worker   // In short, block 7 disappears and we merge 6 and 7. Now we have a diamond with {3,4,5,6}, and
112*795d594fSAndroid Build Coastguard Worker   // when that gets resolved we get another one with the outer if.
113*795d594fSAndroid Build Coastguard Worker   HBasicBlock* TryFixupDoubleDiamondPattern(HBasicBlock* block);
114*795d594fSAndroid Build Coastguard Worker 
115*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(HSelectGenerator);
116*795d594fSAndroid Build Coastguard Worker };
117*795d594fSAndroid Build Coastguard Worker 
118*795d594fSAndroid Build Coastguard Worker }  // namespace art
119*795d594fSAndroid Build Coastguard Worker 
120*795d594fSAndroid Build Coastguard Worker #endif  // ART_COMPILER_OPTIMIZING_SELECT_GENERATOR_H_
121