xref: /aosp_15_r20/art/compiler/optimizing/ssa_builder.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_SSA_BUILDER_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_OPTIMIZING_SSA_BUILDER_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
21*795d594fSAndroid Build Coastguard Worker #include "base/scoped_arena_allocator.h"
22*795d594fSAndroid Build Coastguard Worker #include "base/scoped_arena_containers.h"
23*795d594fSAndroid Build Coastguard Worker #include "nodes.h"
24*795d594fSAndroid Build Coastguard Worker #include "optimization.h"
25*795d594fSAndroid Build Coastguard Worker 
26*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
27*795d594fSAndroid Build Coastguard Worker 
28*795d594fSAndroid Build Coastguard Worker /**
29*795d594fSAndroid Build Coastguard Worker  * Transforms a graph into SSA form. The liveness guarantees of
30*795d594fSAndroid Build Coastguard Worker  * this transformation are listed below. A DEX register
31*795d594fSAndroid Build Coastguard Worker  * being killed means its value at a given position in the code
32*795d594fSAndroid Build Coastguard Worker  * will not be available to its environment uses. A merge in the
33*795d594fSAndroid Build Coastguard Worker  * following text is materialized as a `HPhi`.
34*795d594fSAndroid Build Coastguard Worker  *
35*795d594fSAndroid Build Coastguard Worker  * (a) Dex registers that do not require merging (that is, they do not
36*795d594fSAndroid Build Coastguard Worker  *     have different values at a join block) are available to all their
37*795d594fSAndroid Build Coastguard Worker  *     environment uses. Note that it does not imply the instruction will
38*795d594fSAndroid Build Coastguard Worker  *     have a physical location after register allocation. See the
39*795d594fSAndroid Build Coastguard Worker  *     SsaLivenessAnalysis phase.
40*795d594fSAndroid Build Coastguard Worker  *
41*795d594fSAndroid Build Coastguard Worker  * (b) Dex registers that require merging, and the merging gives
42*795d594fSAndroid Build Coastguard Worker  *     incompatible types, will be killed for environment uses of that merge.
43*795d594fSAndroid Build Coastguard Worker  *
44*795d594fSAndroid Build Coastguard Worker  * (c) When the `debuggable` flag is passed to the compiler, Dex registers
45*795d594fSAndroid Build Coastguard Worker  *     that require merging and have a proper type after the merge, are
46*795d594fSAndroid Build Coastguard Worker  *     available to all their environment uses. If the `debuggable` flag
47*795d594fSAndroid Build Coastguard Worker  *     is not set, values of Dex registers only used by environments
48*795d594fSAndroid Build Coastguard Worker  *     are killed.
49*795d594fSAndroid Build Coastguard Worker  */
50*795d594fSAndroid Build Coastguard Worker class SsaBuilder : public ValueObject {
51*795d594fSAndroid Build Coastguard Worker  public:
SsaBuilder(HGraph * graph,Handle<mirror::ClassLoader> class_loader,Handle<mirror::DexCache> dex_cache,ScopedArenaAllocator * local_allocator)52*795d594fSAndroid Build Coastguard Worker   SsaBuilder(HGraph* graph,
53*795d594fSAndroid Build Coastguard Worker              Handle<mirror::ClassLoader> class_loader,
54*795d594fSAndroid Build Coastguard Worker              Handle<mirror::DexCache> dex_cache,
55*795d594fSAndroid Build Coastguard Worker              ScopedArenaAllocator* local_allocator)
56*795d594fSAndroid Build Coastguard Worker       : graph_(graph),
57*795d594fSAndroid Build Coastguard Worker         class_loader_(class_loader),
58*795d594fSAndroid Build Coastguard Worker         dex_cache_(dex_cache),
59*795d594fSAndroid Build Coastguard Worker         agets_fixed_(false),
60*795d594fSAndroid Build Coastguard Worker         local_allocator_(local_allocator),
61*795d594fSAndroid Build Coastguard Worker         ambiguous_agets_(local_allocator->Adapter(kArenaAllocGraphBuilder)),
62*795d594fSAndroid Build Coastguard Worker         ambiguous_asets_(local_allocator->Adapter(kArenaAllocGraphBuilder)),
63*795d594fSAndroid Build Coastguard Worker         uninitialized_strings_(local_allocator->Adapter(kArenaAllocGraphBuilder)),
64*795d594fSAndroid Build Coastguard Worker         uninitialized_string_phis_(local_allocator->Adapter(kArenaAllocGraphBuilder)) {
65*795d594fSAndroid Build Coastguard Worker   }
66*795d594fSAndroid Build Coastguard Worker 
67*795d594fSAndroid Build Coastguard Worker   GraphAnalysisResult BuildSsa();
68*795d594fSAndroid Build Coastguard Worker 
69*795d594fSAndroid Build Coastguard Worker   HInstruction* GetFloatOrDoubleEquivalent(HInstruction* instruction, DataType::Type type);
70*795d594fSAndroid Build Coastguard Worker   HInstruction* GetReferenceTypeEquivalent(HInstruction* instruction);
71*795d594fSAndroid Build Coastguard Worker 
MaybeAddAmbiguousArrayGet(HArrayGet * aget)72*795d594fSAndroid Build Coastguard Worker   void MaybeAddAmbiguousArrayGet(HArrayGet* aget) {
73*795d594fSAndroid Build Coastguard Worker     DataType::Type type = aget->GetType();
74*795d594fSAndroid Build Coastguard Worker     DCHECK(!DataType::IsFloatingPointType(type));
75*795d594fSAndroid Build Coastguard Worker     if (DataType::IsIntOrLongType(type)) {
76*795d594fSAndroid Build Coastguard Worker       ambiguous_agets_.push_back(aget);
77*795d594fSAndroid Build Coastguard Worker     }
78*795d594fSAndroid Build Coastguard Worker   }
79*795d594fSAndroid Build Coastguard Worker 
MaybeAddAmbiguousArraySet(HArraySet * aset)80*795d594fSAndroid Build Coastguard Worker   void MaybeAddAmbiguousArraySet(HArraySet* aset) {
81*795d594fSAndroid Build Coastguard Worker     DataType::Type type = aset->GetValue()->GetType();
82*795d594fSAndroid Build Coastguard Worker     if (DataType::IsIntOrLongType(type)) {
83*795d594fSAndroid Build Coastguard Worker       ambiguous_asets_.push_back(aset);
84*795d594fSAndroid Build Coastguard Worker     }
85*795d594fSAndroid Build Coastguard Worker   }
86*795d594fSAndroid Build Coastguard Worker 
AddUninitializedString(HNewInstance * string)87*795d594fSAndroid Build Coastguard Worker   void AddUninitializedString(HNewInstance* string) {
88*795d594fSAndroid Build Coastguard Worker     // In some rare cases (b/27847265), the same NewInstance may be seen
89*795d594fSAndroid Build Coastguard Worker     // multiple times. We should only consider it once for removal, so we
90*795d594fSAndroid Build Coastguard Worker     // ensure it is not added more than once.
91*795d594fSAndroid Build Coastguard Worker     // Note that we cannot check whether this really is a NewInstance of String
92*795d594fSAndroid Build Coastguard Worker     // before RTP. We DCHECK that in RemoveRedundantUninitializedStrings.
93*795d594fSAndroid Build Coastguard Worker     if (!ContainsElement(uninitialized_strings_, string)) {
94*795d594fSAndroid Build Coastguard Worker       uninitialized_strings_.push_back(string);
95*795d594fSAndroid Build Coastguard Worker     }
96*795d594fSAndroid Build Coastguard Worker   }
97*795d594fSAndroid Build Coastguard Worker 
AddUninitializedStringPhi(HInvoke * invoke)98*795d594fSAndroid Build Coastguard Worker   void AddUninitializedStringPhi(HInvoke* invoke) {
99*795d594fSAndroid Build Coastguard Worker     uninitialized_string_phis_.push_back(invoke);
100*795d594fSAndroid Build Coastguard Worker   }
101*795d594fSAndroid Build Coastguard Worker 
102*795d594fSAndroid Build Coastguard Worker  private:
103*795d594fSAndroid Build Coastguard Worker   void SetLoopHeaderPhiInputs();
104*795d594fSAndroid Build Coastguard Worker   void FixEnvironmentPhis();
105*795d594fSAndroid Build Coastguard Worker   void FixNullConstantType();
106*795d594fSAndroid Build Coastguard Worker   void EquivalentPhisCleanup();
107*795d594fSAndroid Build Coastguard Worker   void RunPrimitiveTypePropagation();
108*795d594fSAndroid Build Coastguard Worker 
109*795d594fSAndroid Build Coastguard Worker   // Attempts to resolve types of aget(-wide) instructions and type values passed
110*795d594fSAndroid Build Coastguard Worker   // to aput(-wide) instructions from reference type information on the array
111*795d594fSAndroid Build Coastguard Worker   // input. Returns false if the type of an array is unknown.
112*795d594fSAndroid Build Coastguard Worker   bool FixAmbiguousArrayOps();
113*795d594fSAndroid Build Coastguard Worker 
114*795d594fSAndroid Build Coastguard Worker   bool TypeInputsOfPhi(HPhi* phi, ScopedArenaVector<HPhi*>* worklist);
115*795d594fSAndroid Build Coastguard Worker   bool UpdatePrimitiveType(HPhi* phi, ScopedArenaVector<HPhi*>* worklist);
116*795d594fSAndroid Build Coastguard Worker   void ProcessPrimitiveTypePropagationWorklist(ScopedArenaVector<HPhi*>* worklist);
117*795d594fSAndroid Build Coastguard Worker 
118*795d594fSAndroid Build Coastguard Worker   HFloatConstant* GetFloatEquivalent(HIntConstant* constant);
119*795d594fSAndroid Build Coastguard Worker   HDoubleConstant* GetDoubleEquivalent(HLongConstant* constant);
120*795d594fSAndroid Build Coastguard Worker   HPhi* GetFloatDoubleOrReferenceEquivalentOfPhi(HPhi* phi, DataType::Type type);
121*795d594fSAndroid Build Coastguard Worker   HArrayGet* GetFloatOrDoubleEquivalentOfArrayGet(HArrayGet* aget);
122*795d594fSAndroid Build Coastguard Worker 
123*795d594fSAndroid Build Coastguard Worker   void RemoveRedundantUninitializedStrings();
124*795d594fSAndroid Build Coastguard Worker   bool ReplaceUninitializedStringPhis();
125*795d594fSAndroid Build Coastguard Worker   bool HasAliasInEnvironments(HInstruction* instruction);
126*795d594fSAndroid Build Coastguard Worker 
127*795d594fSAndroid Build Coastguard Worker   HGraph* const graph_;
128*795d594fSAndroid Build Coastguard Worker   Handle<mirror::ClassLoader> class_loader_;
129*795d594fSAndroid Build Coastguard Worker   Handle<mirror::DexCache> dex_cache_;
130*795d594fSAndroid Build Coastguard Worker 
131*795d594fSAndroid Build Coastguard Worker   // True if types of ambiguous ArrayGets have been resolved.
132*795d594fSAndroid Build Coastguard Worker   bool agets_fixed_;
133*795d594fSAndroid Build Coastguard Worker 
134*795d594fSAndroid Build Coastguard Worker   ScopedArenaAllocator* const local_allocator_;
135*795d594fSAndroid Build Coastguard Worker   ScopedArenaVector<HArrayGet*> ambiguous_agets_;
136*795d594fSAndroid Build Coastguard Worker   ScopedArenaVector<HArraySet*> ambiguous_asets_;
137*795d594fSAndroid Build Coastguard Worker   ScopedArenaVector<HNewInstance*> uninitialized_strings_;
138*795d594fSAndroid Build Coastguard Worker   ScopedArenaVector<HInvoke*> uninitialized_string_phis_;
139*795d594fSAndroid Build Coastguard Worker 
140*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(SsaBuilder);
141*795d594fSAndroid Build Coastguard Worker };
142*795d594fSAndroid Build Coastguard Worker 
143*795d594fSAndroid Build Coastguard Worker }  // namespace art
144*795d594fSAndroid Build Coastguard Worker 
145*795d594fSAndroid Build Coastguard Worker #endif  // ART_COMPILER_OPTIMIZING_SSA_BUILDER_H_
146