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