blob: a4a7602c4b7bb21db1da9e6f6d5bb862c5b9b71b [file] [log] [blame]
Vladimir Marko95a05972014-05-30 10:01:32 +01001/*
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_DEX_GLOBAL_VALUE_NUMBERING_H_
18#define ART_COMPILER_DEX_GLOBAL_VALUE_NUMBERING_H_
19
20#include "base/macros.h"
21#include "compiler_internals.h"
22#include "utils/scoped_arena_containers.h"
23
24namespace art {
25
26class LocalValueNumbering;
27class MirFieldInfo;
28
29class GlobalValueNumbering {
30 public:
Vladimir Marko415ac882014-09-30 18:09:14 +010031 enum Mode {
32 kModeGvn,
33 kModeGvnPostProcessing,
34 kModeLvn
35 };
36
37 static bool Skip(CompilationUnit* cu) {
38 return (cu->disable_opt & (1u << kGlobalValueNumbering)) != 0u ||
39 cu->mir_graph->GetMaxNestedLoops() > kMaxAllowedNestedLoops;
40 }
41
42 GlobalValueNumbering(CompilationUnit* cu, ScopedArenaAllocator* allocator, Mode mode);
Vladimir Marko95a05972014-05-30 10:01:32 +010043 ~GlobalValueNumbering();
44
Vladimir Marko55fff042014-07-10 12:42:52 +010045 // Prepare LVN for the basic block.
Vladimir Markob19955d2014-07-29 12:04:10 +010046 LocalValueNumbering* PrepareBasicBlock(BasicBlock* bb,
47 ScopedArenaAllocator* allocator = nullptr);
Vladimir Marko55fff042014-07-10 12:42:52 +010048
49 // Finish processing the basic block.
Vladimir Marko95a05972014-05-30 10:01:32 +010050 bool FinishBasicBlock(BasicBlock* bb);
51
52 // Checks that the value names didn't overflow.
53 bool Good() const {
54 return last_value_ < kNoValue;
55 }
56
57 // Allow modifications.
Vladimir Marko415ac882014-09-30 18:09:14 +010058 void StartPostProcessing() {
Vladimir Marko95a05972014-05-30 10:01:32 +010059 DCHECK(Good());
Vladimir Marko415ac882014-09-30 18:09:14 +010060 DCHECK_EQ(mode_, kModeGvn);
61 mode_ = kModeGvnPostProcessing;
Vladimir Marko95a05972014-05-30 10:01:32 +010062 }
63
64 bool CanModify() const {
Vladimir Marko95a05972014-05-30 10:01:32 +010065 return modifications_allowed_ && Good();
66 }
67
68 // GlobalValueNumbering should be allocated on the ArenaStack (or the native stack).
69 static void* operator new(size_t size, ScopedArenaAllocator* allocator) {
Vladimir Markob19955d2014-07-29 12:04:10 +010070 return allocator->Alloc(sizeof(GlobalValueNumbering), kArenaAllocMisc);
Vladimir Marko95a05972014-05-30 10:01:32 +010071 }
72
73 // Allow delete-expression to destroy a GlobalValueNumbering object without deallocation.
74 static void operator delete(void* ptr) { UNUSED(ptr); }
75
76 private:
77 static constexpr uint16_t kNoValue = 0xffffu;
78
79 // Allocate a new value name.
80 uint16_t NewValueName() {
Vladimir Marko415ac882014-09-30 18:09:14 +010081 DCHECK_NE(mode_, kModeGvnPostProcessing);
Vladimir Marko95a05972014-05-30 10:01:32 +010082 ++last_value_;
83 return last_value_;
84 }
85
86 // Key is concatenation of opcode, operand1, operand2 and modifier, value is value name.
87 typedef ScopedArenaSafeMap<uint64_t, uint16_t> ValueMap;
88
89 static uint64_t BuildKey(uint16_t op, uint16_t operand1, uint16_t operand2, uint16_t modifier) {
90 return (static_cast<uint64_t>(op) << 48 | static_cast<uint64_t>(operand1) << 32 |
91 static_cast<uint64_t>(operand2) << 16 | static_cast<uint64_t>(modifier));
Andreas Gampec8ccf682014-09-29 20:07:43 -070092 }
Vladimir Marko95a05972014-05-30 10:01:32 +010093
94 // Look up a value in the global value map, adding a new entry if there was none before.
95 uint16_t LookupValue(uint16_t op, uint16_t operand1, uint16_t operand2, uint16_t modifier) {
96 uint16_t res;
97 uint64_t key = BuildKey(op, operand1, operand2, modifier);
98 ValueMap::iterator lb = global_value_map_.lower_bound(key);
99 if (lb != global_value_map_.end() && lb->first == key) {
100 res = lb->second;
101 } else {
102 res = NewValueName();
103 global_value_map_.PutBefore(lb, key, res);
104 }
105 return res;
Andreas Gampec8ccf682014-09-29 20:07:43 -0700106 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100107
Vladimir Markoa4426cf2014-10-22 17:15:53 +0100108 // Look up a value in the global value map, don't add a new entry if there was none before.
109 uint16_t FindValue(uint16_t op, uint16_t operand1, uint16_t operand2, uint16_t modifier) {
110 uint16_t res;
111 uint64_t key = BuildKey(op, operand1, operand2, modifier);
112 ValueMap::iterator lb = global_value_map_.lower_bound(key);
113 if (lb != global_value_map_.end() && lb->first == key) {
114 res = lb->second;
115 } else {
116 res = kNoValue;
117 }
118 return res;
119 }
120
Vladimir Marko95a05972014-05-30 10:01:32 +0100121 // Check if the exact value is stored in the global value map.
122 bool HasValue(uint16_t op, uint16_t operand1, uint16_t operand2, uint16_t modifier,
123 uint16_t value) const {
124 DCHECK(value != 0u || !Good());
125 DCHECK_LE(value, last_value_);
126 // This is equivalent to value == LookupValue(op, operand1, operand2, modifier)
127 // except that it doesn't add an entry to the global value map if it's not there.
128 uint64_t key = BuildKey(op, operand1, operand2, modifier);
129 ValueMap::const_iterator it = global_value_map_.find(key);
130 return (it != global_value_map_.end() && it->second == value);
Andreas Gampec8ccf682014-09-29 20:07:43 -0700131 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100132
133 // FieldReference represents a unique resolved field.
134 struct FieldReference {
135 const DexFile* dex_file;
136 uint16_t field_idx;
137 uint16_t type; // See comments for LocalValueNumbering::kFieldTypeCount.
138 };
139
140 struct FieldReferenceComparator {
141 bool operator()(const FieldReference& lhs, const FieldReference& rhs) const {
142 if (lhs.field_idx != rhs.field_idx) {
143 return lhs.field_idx < rhs.field_idx;
144 }
145 // If the field_idx and dex_file match, the type must also match.
146 DCHECK(lhs.dex_file != rhs.dex_file || lhs.type == rhs.type);
147 return lhs.dex_file < rhs.dex_file;
148 }
149 };
150
151 // Maps field key to field id for resolved fields.
152 typedef ScopedArenaSafeMap<FieldReference, uint32_t, FieldReferenceComparator> FieldIndexMap;
153
154 // Get a field id.
155 uint16_t GetFieldId(const MirFieldInfo& field_info, uint16_t type);
156
157 // Get a field type based on field id.
158 uint16_t GetFieldType(uint16_t field_id) {
159 DCHECK_LT(field_id, field_index_reverse_map_.size());
160 return field_index_reverse_map_[field_id]->first.type;
161 }
162
163 struct ArrayLocation {
164 uint16_t base;
165 uint16_t index;
166 };
167
168 struct ArrayLocationComparator {
169 bool operator()(const ArrayLocation& lhs, const ArrayLocation& rhs) const {
170 if (lhs.base != rhs.base) {
171 return lhs.base < rhs.base;
172 }
173 return lhs.index < rhs.index;
174 }
175 };
176
177 typedef ScopedArenaSafeMap<ArrayLocation, uint16_t, ArrayLocationComparator> ArrayLocationMap;
178
179 // Get an array location.
180 uint16_t GetArrayLocation(uint16_t base, uint16_t index);
181
182 // Get the array base from an array location.
183 uint16_t GetArrayLocationBase(uint16_t location) const {
184 return array_location_reverse_map_[location]->first.base;
185 }
186
187 // Get the array index from an array location.
188 uint16_t GetArrayLocationIndex(uint16_t location) const {
189 return array_location_reverse_map_[location]->first.index;
190 }
191
192 // A set of value names.
193 typedef ScopedArenaSet<uint16_t> ValueNameSet;
194
195 // A map from a set of references to the set id.
196 typedef ScopedArenaSafeMap<ValueNameSet, uint16_t> RefSetIdMap;
197
198 uint16_t GetRefSetId(const ValueNameSet& ref_set) {
199 uint16_t res = kNoValue;
200 auto lb = ref_set_map_.lower_bound(ref_set);
201 if (lb != ref_set_map_.end() && !ref_set_map_.key_comp()(ref_set, lb->first)) {
202 res = lb->second;
203 } else {
204 res = NewValueName();
205 ref_set_map_.PutBefore(lb, ref_set, res);
206 }
207 return res;
208 }
209
210 const BasicBlock* GetBasicBlock(uint16_t bb_id) const {
Vladimir Marko55fff042014-07-10 12:42:52 +0100211 return mir_graph_->GetBasicBlock(bb_id);
Vladimir Marko95a05972014-05-30 10:01:32 +0100212 }
213
214 static bool HasNullCheckLastInsn(const BasicBlock* pred_bb, BasicBlockId succ_id);
215
216 bool NullCheckedInAllPredecessors(const ScopedArenaVector<uint16_t>& merge_names) const;
217
218 CompilationUnit* GetCompilationUnit() const {
219 return cu_;
220 }
221
222 MIRGraph* GetMirGraph() const {
Vladimir Marko55fff042014-07-10 12:42:52 +0100223 return mir_graph_;
Vladimir Marko95a05972014-05-30 10:01:32 +0100224 }
225
226 ScopedArenaAllocator* Allocator() const {
227 return allocator_;
228 }
229
230 CompilationUnit* const cu_;
Vladimir Marko55fff042014-07-10 12:42:52 +0100231 MIRGraph* mir_graph_;
Vladimir Marko95a05972014-05-30 10:01:32 +0100232 ScopedArenaAllocator* const allocator_;
233
Vladimir Marko415ac882014-09-30 18:09:14 +0100234 // The maximum number of nested loops that we accept for GVN.
235 static constexpr size_t kMaxAllowedNestedLoops = 6u;
236
Vladimir Marko55fff042014-07-10 12:42:52 +0100237 // The number of BBs that we need to process grows exponentially with the number
238 // of nested loops. Don't allow excessive processing for too many nested loops or
239 // otherwise expensive methods.
240 static constexpr uint32_t kMaxBbsToProcessMultiplyFactor = 20u;
Vladimir Marko95a05972014-05-30 10:01:32 +0100241
Vladimir Marko55fff042014-07-10 12:42:52 +0100242 uint32_t bbs_processed_;
Vladimir Marko2d2365c2014-08-19 18:08:39 +0100243 uint32_t max_bbs_to_process_; // Doesn't apply after the main GVN has converged.
Vladimir Marko95a05972014-05-30 10:01:32 +0100244
245 // We have 32-bit last_value_ so that we can detect when we run out of value names, see Good().
246 // We usually don't check Good() until the end of LVN unless we're about to modify code.
247 uint32_t last_value_;
248
249 // Marks whether code modifications are allowed. The initial GVN is done without code
250 // modifications to settle the value names. Afterwards, we allow modifications and rerun
251 // LVN once for each BasicBlock.
252 bool modifications_allowed_;
253
Vladimir Marko415ac882014-09-30 18:09:14 +0100254 // Specifies the mode of operation.
255 Mode mode_;
256
Vladimir Marko95a05972014-05-30 10:01:32 +0100257 ValueMap global_value_map_;
258 FieldIndexMap field_index_map_;
259 ScopedArenaVector<const FieldIndexMap::value_type*> field_index_reverse_map_;
260 ArrayLocationMap array_location_map_;
261 ScopedArenaVector<const ArrayLocationMap::value_type*> array_location_reverse_map_;
262 RefSetIdMap ref_set_map_;
263
264 ScopedArenaVector<const LocalValueNumbering*> lvns_; // Owning.
265 std::unique_ptr<LocalValueNumbering> work_lvn_;
266 ScopedArenaVector<const LocalValueNumbering*> merge_lvns_; // Not owning.
267
268 friend class LocalValueNumbering;
Vladimir Markoa4426cf2014-10-22 17:15:53 +0100269 friend class GlobalValueNumberingTest;
Vladimir Marko95a05972014-05-30 10:01:32 +0100270
271 DISALLOW_COPY_AND_ASSIGN(GlobalValueNumbering);
272};
273
274} // namespace art
275
276#endif // ART_COMPILER_DEX_GLOBAL_VALUE_NUMBERING_H_