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