• 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