blob: 69a94a54c4a9f3bd25ec57d9317b3c8d8bf855c0 [file] [log] [blame]
buzbee2502e002012-12-31 16:05:53 -08001/*
2 * Copyright (C) 2012 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
buzbee311ca162013-02-28 15:56:43 -080017#include "local_value_numbering.h"
buzbee2502e002012-12-31 16:05:53 -080018
Vladimir Markobe0e5462014-02-26 11:24:15 +000019#include "mir_field_info.h"
Vladimir Markof59f18b2014-02-17 15:53:57 +000020#include "mir_graph.h"
21
buzbee2502e002012-12-31 16:05:53 -080022namespace art {
23
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010024namespace { // anonymous namespace
25
26// Operations used for value map keys instead of actual opcode.
27static constexpr uint16_t kInvokeMemoryVersionBumpOp = Instruction::INVOKE_DIRECT;
28static constexpr uint16_t kUnresolvedSFieldOp = Instruction::SPUT;
29static constexpr uint16_t kResolvedSFieldOp = Instruction::SGET;
30static constexpr uint16_t kUnresolvedIFieldOp = Instruction::IPUT;
31static constexpr uint16_t kNonAliasingIFieldOp = Instruction::IGET;
32static constexpr uint16_t kAliasingIFieldOp = Instruction::IGET_WIDE;
33static constexpr uint16_t kAliasingIFieldStartVersionOp = Instruction::IGET_WIDE;
34static constexpr uint16_t kAliasingIFieldBumpVersionOp = Instruction::IGET_OBJECT;
35static constexpr uint16_t kArrayAccessLocOp = Instruction::APUT;
36static constexpr uint16_t kNonAliasingArrayOp = Instruction::AGET;
37static constexpr uint16_t kNonAliasingArrayStartVersionOp = Instruction::AGET_WIDE;
38static constexpr uint16_t kAliasingArrayOp = Instruction::AGET_OBJECT;
39static constexpr uint16_t kAliasingArrayMemoryVersionOp = Instruction::AGET_BOOLEAN;
40static constexpr uint16_t kAliasingArrayBumpVersionOp = Instruction::AGET_BYTE;
41
42} // anonymous namespace
43
44LocalValueNumbering::LocalValueNumbering(CompilationUnit* cu, ScopedArenaAllocator* allocator)
45 : cu_(cu),
46 last_value_(0u),
47 sreg_value_map_(std::less<uint16_t>(), allocator->Adapter()),
48 sreg_wide_value_map_(std::less<uint16_t>(), allocator->Adapter()),
49 value_map_(std::less<uint64_t>(), allocator->Adapter()),
50 global_memory_version_(0u),
51 aliasing_ifield_version_map_(std::less<uint16_t>(), allocator->Adapter()),
52 non_aliasing_array_version_map_(std::less<uint16_t>(), allocator->Adapter()),
53 field_index_map_(FieldReferenceComparator(), allocator->Adapter()),
54 non_aliasing_refs_(std::less<uint16_t>(), allocator->Adapter()),
55 non_aliasing_ifields_(NonAliasingIFieldKeyComparator(), allocator->Adapter()),
56 escaped_array_refs_(EscapedArrayKeyComparator(), allocator->Adapter()),
57 range_checked_(RangeCheckKeyComparator() , allocator->Adapter()),
58 null_checked_(std::less<uint16_t>(), allocator->Adapter()) {
59 std::fill_n(unresolved_sfield_version_, kFieldTypeCount, 0u);
60 std::fill_n(unresolved_ifield_version_, kFieldTypeCount, 0u);
61 std::fill_n(aliasing_array_version_, kFieldTypeCount, 0u);
62}
63
64uint16_t LocalValueNumbering::GetFieldId(const MirFieldInfo& field_info) {
65 FieldReference key = { field_info.DeclaringDexFile(), field_info.DeclaringFieldIndex() };
Vladimir Markof59f18b2014-02-17 15:53:57 +000066 auto it = field_index_map_.find(key);
67 if (it != field_index_map_.end()) {
68 return it->second;
69 }
70 uint16_t id = field_index_map_.size();
71 field_index_map_.Put(key, id);
72 return id;
73}
74
Vladimir Markof59f18b2014-02-17 15:53:57 +000075uint16_t LocalValueNumbering::MarkNonAliasingNonNull(MIR* mir) {
76 uint16_t res = GetOperandValue(mir->ssa_rep->defs[0]);
77 SetOperandValue(mir->ssa_rep->defs[0], res);
78 DCHECK(null_checked_.find(res) == null_checked_.end());
79 null_checked_.insert(res);
80 non_aliasing_refs_.insert(res);
81 return res;
82}
83
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010084bool LocalValueNumbering::IsNonAliasing(uint16_t reg) {
85 return non_aliasing_refs_.find(reg) != non_aliasing_refs_.end();
Vladimir Markof59f18b2014-02-17 15:53:57 +000086}
87
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010088bool LocalValueNumbering::IsNonAliasingIField(uint16_t reg, uint16_t field_id, uint16_t type) {
89 if (IsNonAliasing(reg)) {
90 return true;
91 }
92 NonAliasingIFieldKey key = { reg, field_id, type };
93 return non_aliasing_ifields_.count(key) != 0u;
94}
95
96bool LocalValueNumbering::IsNonAliasingArray(uint16_t reg, uint16_t type) {
97 if (IsNonAliasing(reg)) {
98 return true;
99 }
100 EscapedArrayKey key = { reg, type };
101 return escaped_array_refs_.count(key) != 0u;
102}
103
104
Vladimir Markof59f18b2014-02-17 15:53:57 +0000105void LocalValueNumbering::HandleNullCheck(MIR* mir, uint16_t reg) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100106 auto lb = null_checked_.lower_bound(reg);
107 if (lb != null_checked_.end() && *lb == reg) {
108 if (LIKELY(Good())) {
109 if (cu_->verbose) {
110 LOG(INFO) << "Removing null check for 0x" << std::hex << mir->offset;
111 }
112 mir->optimization_flags |= MIR_IGNORE_NULL_CHECK;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000113 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000114 } else {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100115 null_checked_.insert(lb, reg);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000116 }
117}
118
119void LocalValueNumbering::HandleRangeCheck(MIR* mir, uint16_t array, uint16_t index) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100120 RangeCheckKey key = { array, index };
121 auto lb = range_checked_.lower_bound(key);
122 if (lb != range_checked_.end() && !RangeCheckKeyComparator()(key, *lb)) {
123 if (LIKELY(Good())) {
124 if (cu_->verbose) {
125 LOG(INFO) << "Removing range check for 0x" << std::hex << mir->offset;
126 }
127 mir->optimization_flags |= MIR_IGNORE_RANGE_CHECK;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000128 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100129 } else {
130 // Mark range check completed.
131 range_checked_.insert(lb, key);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000132 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000133}
134
135void LocalValueNumbering::HandlePutObject(MIR* mir) {
136 // If we're storing a non-aliasing reference, stop tracking it as non-aliasing now.
137 uint16_t base = GetOperandValue(mir->ssa_rep->uses[0]);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100138 HandleEscapingRef(base);
139}
140
141void LocalValueNumbering::HandleEscapingRef(uint16_t base) {
142 auto it = non_aliasing_refs_.find(base);
143 if (it != non_aliasing_refs_.end()) {
144 uint64_t iget_key = BuildKey(Instruction::IGET, base, 0u, 0u);
145 for (auto iget_it = value_map_.lower_bound(iget_key), iget_end = value_map_.end();
146 iget_it != iget_end && EqualOpAndOperand1(iget_it->first, iget_key); ++iget_it) {
147 uint16_t field_id = ExtractOperand2(iget_it->first);
148 uint16_t type = ExtractModifier(iget_it->first);
149 NonAliasingIFieldKey key = { base, field_id, type };
150 non_aliasing_ifields_.insert(key);
151 }
152 uint64_t aget_key = BuildKey(kNonAliasingArrayStartVersionOp, base, 0u, 0u);
153 auto aget_it = value_map_.lower_bound(aget_key);
154 if (aget_it != value_map_.end() && EqualOpAndOperand1(aget_key, aget_it->first)) {
155 DCHECK_EQ(ExtractOperand2(aget_it->first), kNoValue);
156 uint16_t type = ExtractModifier(aget_it->first);
157 EscapedArrayKey key = { base, type };
158 escaped_array_refs_.insert(key);
159 }
160 non_aliasing_refs_.erase(it);
161 }
162}
163
164uint16_t LocalValueNumbering::HandleAGet(MIR* mir, uint16_t opcode) {
165 // uint16_t type = opcode - Instruction::AGET;
166 uint16_t array = GetOperandValue(mir->ssa_rep->uses[0]);
167 HandleNullCheck(mir, array);
168 uint16_t index = GetOperandValue(mir->ssa_rep->uses[1]);
169 HandleRangeCheck(mir, array, index);
170 uint16_t type = opcode - Instruction::AGET;
171 // Establish value number for loaded register.
172 uint16_t res;
173 if (IsNonAliasingArray(array, type)) {
174 // Get the start version that accounts for aliasing within the array (different index names).
175 uint16_t start_version = LookupValue(kNonAliasingArrayStartVersionOp, array, kNoValue, type);
176 // Find the current version from the non_aliasing_array_version_map_.
177 uint16_t memory_version = start_version;
178 auto it = non_aliasing_array_version_map_.find(start_version);
179 if (it != non_aliasing_array_version_map_.end()) {
180 memory_version = it->second;
181 } else {
182 // Just use the start_version.
183 }
184 res = LookupValue(kNonAliasingArrayOp, array, index, memory_version);
185 } else {
186 // Get the memory version of aliased array accesses of this type.
187 uint16_t memory_version = LookupValue(kAliasingArrayMemoryVersionOp, global_memory_version_,
188 aliasing_array_version_[type], kNoValue);
189 res = LookupValue(kAliasingArrayOp, array, index, memory_version);
190 }
191 if (opcode == Instruction::AGET_WIDE) {
192 SetOperandValueWide(mir->ssa_rep->defs[0], res);
193 } else {
194 SetOperandValue(mir->ssa_rep->defs[0], res);
195 }
196 return res;
197}
198
199void LocalValueNumbering::HandleAPut(MIR* mir, uint16_t opcode) {
200 int array_idx = (opcode == Instruction::APUT_WIDE) ? 2 : 1;
201 int index_idx = array_idx + 1;
202 uint16_t array = GetOperandValue(mir->ssa_rep->uses[array_idx]);
203 HandleNullCheck(mir, array);
204 uint16_t index = GetOperandValue(mir->ssa_rep->uses[index_idx]);
205 HandleRangeCheck(mir, array, index);
206
207 uint16_t type = opcode - Instruction::APUT;
208 uint16_t value = (opcode == Instruction::APUT_WIDE)
209 ? GetOperandValueWide(mir->ssa_rep->uses[0])
210 : GetOperandValue(mir->ssa_rep->uses[0]);
211 if (IsNonAliasing(array)) {
212 // Get the start version that accounts for aliasing within the array (different index values).
213 uint16_t start_version = LookupValue(kNonAliasingArrayStartVersionOp, array, kNoValue, type);
214 auto it = non_aliasing_array_version_map_.find(start_version);
215 uint16_t memory_version = start_version;
216 if (it != non_aliasing_array_version_map_.end()) {
217 memory_version = it->second;
218 }
219 // We need to take 4 values (array, index, memory_version, value) into account for bumping
220 // the memory version but the key can take only 3. Merge array and index into a location.
221 uint16_t array_access_location = LookupValue(kArrayAccessLocOp, array, index, kNoValue);
222 // Bump the version, adding to the chain.
223 memory_version = LookupValue(kAliasingArrayBumpVersionOp, memory_version,
224 array_access_location, value);
225 non_aliasing_array_version_map_.Overwrite(start_version, memory_version);
226 StoreValue(kNonAliasingArrayOp, array, index, memory_version, value);
227 } else {
228 // Get the memory version based on global_memory_version_ and aliasing_array_version_[type].
229 uint16_t memory_version = LookupValue(kAliasingArrayMemoryVersionOp, global_memory_version_,
230 aliasing_array_version_[type], kNoValue);
231 if (HasValue(kAliasingArrayOp, array, index, memory_version, value)) {
232 // This APUT can be eliminated, it stores the same value that's already in the field.
233 // TODO: Eliminate the APUT.
234 return;
235 }
236 // We need to take 4 values (array, index, memory_version, value) into account for bumping
237 // the memory version but the key can take only 3. Merge array and index into a location.
238 uint16_t array_access_location = LookupValue(kArrayAccessLocOp, array, index, kNoValue);
239 // Bump the version, adding to the chain.
240 uint16_t bumped_version = LookupValue(kAliasingArrayBumpVersionOp, memory_version,
241 array_access_location, value);
242 aliasing_array_version_[type] = bumped_version;
243 memory_version = LookupValue(kAliasingArrayMemoryVersionOp, global_memory_version_,
244 bumped_version, kNoValue);
245 StoreValue(kAliasingArrayOp, array, index, memory_version, value);
246
247 // Clear escaped array refs for this type.
248 EscapedArrayKey array_key = { type, 0u };
249 auto it = escaped_array_refs_.lower_bound(array_key), end = escaped_array_refs_.end();
250 while (it != end && it->type == type) {
251 it = escaped_array_refs_.erase(it);
252 }
253 }
254}
255
256uint16_t LocalValueNumbering::HandleIGet(MIR* mir, uint16_t opcode) {
257 uint16_t base = GetOperandValue(mir->ssa_rep->uses[0]);
258 HandleNullCheck(mir, base);
259 const MirFieldInfo& field_info = cu_->mir_graph->GetIFieldLoweringInfo(mir);
260 uint16_t res;
261 if (!field_info.IsResolved() || field_info.IsVolatile()) {
262 // Volatile fields always get a new memory version; field id is irrelevant.
263 // Unresolved fields may be volatile, so handle them as such to be safe.
264 // Use result s_reg - will be unique.
265 res = LookupValue(kNoValue, mir->ssa_rep->defs[0], kNoValue, kNoValue);
266 } else {
267 uint16_t type = opcode - Instruction::IGET;
268 uint16_t field_id = GetFieldId(field_info);
269 if (IsNonAliasingIField(base, field_id, type)) {
270 res = LookupValue(kNonAliasingIFieldOp, base, field_id, type);
271 } else {
272 // Get the start version that accounts for aliasing with unresolved fields of the same type
273 // and make it unique for the field by including the field_id.
274 uint16_t start_version = LookupValue(kAliasingIFieldStartVersionOp, global_memory_version_,
275 unresolved_ifield_version_[type], field_id);
276 // Find the current version from the aliasing_ifield_version_map_.
277 uint16_t memory_version = start_version;
278 auto version_it = aliasing_ifield_version_map_.find(start_version);
279 if (version_it != aliasing_ifield_version_map_.end()) {
280 memory_version = version_it->second;
281 } else {
282 // Just use the start_version.
283 }
284 res = LookupValue(kAliasingIFieldOp, base, field_id, memory_version);
285 }
286 }
287 if (opcode == Instruction::IGET_WIDE) {
288 SetOperandValueWide(mir->ssa_rep->defs[0], res);
289 } else {
290 SetOperandValue(mir->ssa_rep->defs[0], res);
291 }
292 return res;
293}
294
295void LocalValueNumbering::HandleIPut(MIR* mir, uint16_t opcode) {
296 uint16_t type = opcode - Instruction::IPUT;
297 int base_reg = (opcode == Instruction::IPUT_WIDE) ? 2 : 1;
298 uint16_t base = GetOperandValue(mir->ssa_rep->uses[base_reg]);
299 HandleNullCheck(mir, base);
300 const MirFieldInfo& field_info = cu_->mir_graph->GetIFieldLoweringInfo(mir);
301 if (!field_info.IsResolved()) {
302 // Unresolved fields always alias with everything of the same type.
303 // Use mir->offset as modifier; without elaborate inlining, it will be unique.
304 unresolved_ifield_version_[type] =
305 LookupValue(kUnresolvedIFieldOp, kNoValue, kNoValue, mir->offset);
306
307 // Treat fields of escaped references of the same type as potentially modified.
308 NonAliasingIFieldKey key = { type, 0u, 0u }; // lowest possible key of this type.
309 auto it = non_aliasing_ifields_.lower_bound(key), end = non_aliasing_ifields_.end();
310 while (it != end && it->type == type) {
311 it = non_aliasing_ifields_.erase(it);
312 }
313 } else if (field_info.IsVolatile()) {
314 // Nothing to do, resolved volatile fields always get a new memory version anyway and
315 // can't alias with resolved non-volatile fields.
316 } else {
317 uint16_t field_id = GetFieldId(field_info);
318 uint16_t value = (opcode == Instruction::IPUT_WIDE)
319 ? GetOperandValueWide(mir->ssa_rep->uses[0])
320 : GetOperandValue(mir->ssa_rep->uses[0]);
321 if (IsNonAliasing(base)) {
322 StoreValue(kNonAliasingIFieldOp, base, field_id, type, value);
323 } else {
324 // Get the start version that accounts for aliasing with unresolved fields of the same type
325 // and make it unique for the field by including the field_id.
326 uint16_t start_version = LookupValue(kAliasingIFieldStartVersionOp, global_memory_version_,
327 unresolved_ifield_version_[type], field_id);
328 // Find the old version from the aliasing_ifield_version_map_.
329 uint16_t old_version = start_version;
330 auto version_it = aliasing_ifield_version_map_.find(start_version);
331 if (version_it != aliasing_ifield_version_map_.end()) {
332 old_version = version_it->second;
333 }
334 // Check if the field currently contains the value, making this a NOP.
335 if (HasValue(kAliasingIFieldOp, base, field_id, old_version, value)) {
336 // This IPUT can be eliminated, it stores the same value that's already in the field.
337 // TODO: Eliminate the IPUT.
338 return;
339 }
340 // Bump the version, adding to the chain started by start_version.
341 uint16_t memory_version = LookupValue(kAliasingIFieldBumpVersionOp, old_version, base, value);
342 // Update the aliasing_ifield_version_map_ so that HandleIGet() can get the memory_version
343 // without knowing the values used to build the chain.
344 aliasing_ifield_version_map_.Overwrite(start_version, memory_version);
345 StoreValue(kAliasingIFieldOp, base, field_id, memory_version, value);
346
347 // Clear non-aliasing fields for this field_id.
348 NonAliasingIFieldKey field_key = { type, field_id, 0u };
349 auto it = non_aliasing_ifields_.lower_bound(field_key), end = non_aliasing_ifields_.end();
350 while (it != end && it->field_id == field_id) {
351 DCHECK_EQ(type, it->type);
352 it = non_aliasing_ifields_.erase(it);
353 }
354 }
355 }
356}
357
358uint16_t LocalValueNumbering::HandleSGet(MIR* mir, uint16_t opcode) {
Vladimir Markof418f322014-07-09 14:45:36 +0100359 const MirSFieldLoweringInfo& field_info = cu_->mir_graph->GetSFieldLoweringInfo(mir);
360 if (!field_info.IsInitialized() && (mir->optimization_flags & MIR_IGNORE_CLINIT_CHECK) == 0) {
361 // Class initialization can call arbitrary functions, we need to wipe aliasing values.
362 HandleInvokeOrClInit(mir);
363 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100364 uint16_t res;
365 if (!field_info.IsResolved() || field_info.IsVolatile()) {
366 // Volatile fields always get a new memory version; field id is irrelevant.
367 // Unresolved fields may be volatile, so handle them as such to be safe.
368 // Use result s_reg - will be unique.
369 res = LookupValue(kNoValue, mir->ssa_rep->defs[0], kNoValue, kNoValue);
370 } else {
371 uint16_t field_id = GetFieldId(field_info);
372 // Resolved non-volatile static fields can alias with non-resolved fields of the same type,
373 // so we need to use unresolved_sfield_version_[type] in addition to global_memory_version_
374 // to determine the version of the field.
375 uint16_t type = opcode - Instruction::SGET;
376 res = LookupValue(kResolvedSFieldOp, field_id,
377 unresolved_sfield_version_[type], global_memory_version_);
378 }
379 if (opcode == Instruction::SGET_WIDE) {
380 SetOperandValueWide(mir->ssa_rep->defs[0], res);
381 } else {
382 SetOperandValue(mir->ssa_rep->defs[0], res);
383 }
384 return res;
385}
386
387void LocalValueNumbering::HandleSPut(MIR* mir, uint16_t opcode) {
Vladimir Markof418f322014-07-09 14:45:36 +0100388 const MirSFieldLoweringInfo& field_info = cu_->mir_graph->GetSFieldLoweringInfo(mir);
389 if (!field_info.IsInitialized() && (mir->optimization_flags & MIR_IGNORE_CLINIT_CHECK) == 0) {
390 // Class initialization can call arbitrary functions, we need to wipe aliasing values.
391 HandleInvokeOrClInit(mir);
392 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100393 uint16_t type = opcode - Instruction::SPUT;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100394 if (!field_info.IsResolved()) {
395 // Unresolved fields always alias with everything of the same type.
396 // Use mir->offset as modifier; without elaborate inlining, it will be unique.
397 unresolved_sfield_version_[type] =
398 LookupValue(kUnresolvedSFieldOp, kNoValue, kNoValue, mir->offset);
399 } else if (field_info.IsVolatile()) {
400 // Nothing to do, resolved volatile fields always get a new memory version anyway and
401 // can't alias with resolved non-volatile fields.
402 } else {
403 uint16_t field_id = GetFieldId(field_info);
404 uint16_t value = (opcode == Instruction::SPUT_WIDE)
405 ? GetOperandValueWide(mir->ssa_rep->uses[0])
406 : GetOperandValue(mir->ssa_rep->uses[0]);
407 // Resolved non-volatile static fields can alias with non-resolved fields of the same type,
408 // so we need to use unresolved_sfield_version_[type] in addition to global_memory_version_
409 // to determine the version of the field.
410 uint16_t type = opcode - Instruction::SGET;
411 StoreValue(kResolvedSFieldOp, field_id,
412 unresolved_sfield_version_[type], global_memory_version_, value);
413 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000414}
buzbee2502e002012-12-31 16:05:53 -0800415
Vladimir Markof418f322014-07-09 14:45:36 +0100416void LocalValueNumbering::HandleInvokeOrClInit(MIR* mir) {
417 // Use mir->offset as modifier; without elaborate inlining, it will be unique.
418 global_memory_version_ = LookupValue(kInvokeMemoryVersionBumpOp, 0u, 0u, mir->offset);
419 // All fields of escaped references need to be treated as potentially modified.
420 non_aliasing_ifields_.clear();
421 // Array elements may also have been modified via escaped array refs.
422 escaped_array_refs_.clear();
423}
424
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700425uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100426 uint16_t res = kNoValue;
buzbee2502e002012-12-31 16:05:53 -0800427 uint16_t opcode = mir->dalvikInsn.opcode;
428 switch (opcode) {
429 case Instruction::NOP:
430 case Instruction::RETURN_VOID:
431 case Instruction::RETURN:
432 case Instruction::RETURN_OBJECT:
433 case Instruction::RETURN_WIDE:
434 case Instruction::MONITOR_ENTER:
435 case Instruction::MONITOR_EXIT:
436 case Instruction::GOTO:
437 case Instruction::GOTO_16:
438 case Instruction::GOTO_32:
439 case Instruction::CHECK_CAST:
440 case Instruction::THROW:
441 case Instruction::FILL_ARRAY_DATA:
buzbee2502e002012-12-31 16:05:53 -0800442 case Instruction::PACKED_SWITCH:
443 case Instruction::SPARSE_SWITCH:
444 case Instruction::IF_EQ:
445 case Instruction::IF_NE:
446 case Instruction::IF_LT:
447 case Instruction::IF_GE:
448 case Instruction::IF_GT:
449 case Instruction::IF_LE:
450 case Instruction::IF_EQZ:
451 case Instruction::IF_NEZ:
452 case Instruction::IF_LTZ:
453 case Instruction::IF_GEZ:
454 case Instruction::IF_GTZ:
455 case Instruction::IF_LEZ:
buzbee2502e002012-12-31 16:05:53 -0800456 case kMirOpFusedCmplFloat:
457 case kMirOpFusedCmpgFloat:
458 case kMirOpFusedCmplDouble:
459 case kMirOpFusedCmpgDouble:
460 case kMirOpFusedCmpLong:
461 // Nothing defined - take no action.
462 break;
463
Vladimir Markof59f18b2014-02-17 15:53:57 +0000464 case Instruction::FILLED_NEW_ARRAY:
465 case Instruction::FILLED_NEW_ARRAY_RANGE:
466 // Nothing defined but the result will be unique and non-null.
467 if (mir->next != nullptr && mir->next->dalvikInsn.opcode == Instruction::MOVE_RESULT_OBJECT) {
468 MarkNonAliasingNonNull(mir->next);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100469 // TUNING: We could track value names stored in the array.
Vladimir Markof59f18b2014-02-17 15:53:57 +0000470 // The MOVE_RESULT_OBJECT will be processed next and we'll return the value name then.
471 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100472 // All args escaped (if references).
473 for (size_t i = 0u, count = mir->ssa_rep->num_uses; i != count; ++i) {
474 uint16_t reg = GetOperandValue(mir->ssa_rep->uses[i]);
475 HandleEscapingRef(reg);
476 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000477 break;
478
479 case Instruction::INVOKE_DIRECT:
480 case Instruction::INVOKE_DIRECT_RANGE:
481 case Instruction::INVOKE_VIRTUAL:
482 case Instruction::INVOKE_VIRTUAL_RANGE:
483 case Instruction::INVOKE_SUPER:
484 case Instruction::INVOKE_SUPER_RANGE:
485 case Instruction::INVOKE_INTERFACE:
486 case Instruction::INVOKE_INTERFACE_RANGE: {
487 // Nothing defined but handle the null check.
488 uint16_t reg = GetOperandValue(mir->ssa_rep->uses[0]);
489 HandleNullCheck(mir, reg);
490 }
491 // Intentional fall-through.
492 case Instruction::INVOKE_STATIC:
493 case Instruction::INVOKE_STATIC_RANGE:
Vladimir Marko9820b7c2014-01-02 16:40:37 +0000494 if ((mir->optimization_flags & MIR_INLINED) == 0) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100495 // Make ref args aliasing.
496 for (size_t i = 0u, count = mir->ssa_rep->num_uses; i != count; ++i) {
497 uint16_t reg = GetOperandValue(mir->ssa_rep->uses[i]);
498 non_aliasing_refs_.erase(reg);
499 }
Vladimir Markof418f322014-07-09 14:45:36 +0100500 HandleInvokeOrClInit(mir);
Vladimir Marko9820b7c2014-01-02 16:40:37 +0000501 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000502 break;
503
buzbee2502e002012-12-31 16:05:53 -0800504 case Instruction::MOVE_RESULT:
505 case Instruction::MOVE_RESULT_OBJECT:
506 case Instruction::INSTANCE_OF:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000507 // 1 result, treat as unique each time, use result s_reg - will be unique.
508 res = GetOperandValue(mir->ssa_rep->defs[0]);
509 SetOperandValue(mir->ssa_rep->defs[0], res);
510 break;
511 case Instruction::MOVE_EXCEPTION:
buzbee2502e002012-12-31 16:05:53 -0800512 case Instruction::NEW_INSTANCE:
buzbee2502e002012-12-31 16:05:53 -0800513 case Instruction::CONST_CLASS:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000514 case Instruction::NEW_ARRAY:
Vladimir Markob3e527b2014-04-04 12:37:07 +0100515 // 1 result, treat as unique each time, use result s_reg - will be unique.
516 res = MarkNonAliasingNonNull(mir);
buzbee2502e002012-12-31 16:05:53 -0800517 break;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100518 case Instruction::CONST_STRING:
519 case Instruction::CONST_STRING_JUMBO:
520 // These strings are internalized, so assign value based on the string pool index.
521 res = LookupValue(Instruction::CONST_STRING, Low16Bits(mir->dalvikInsn.vB),
522 High16Bits(mir->dalvikInsn.vB), 0);
523 SetOperandValue(mir->ssa_rep->defs[0], res);
524 null_checked_.insert(res); // May already be there.
525 // NOTE: Hacking the contents of an internalized string via reflection is possible
526 // but the behavior is undefined. Therefore, we consider the string constant and
527 // the reference non-aliasing.
528 // TUNING: We could keep this property even if the reference "escapes".
529 non_aliasing_refs_.insert(res); // May already be there.
530 break;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000531 case Instruction::MOVE_RESULT_WIDE:
Vladimir Markob3e527b2014-04-04 12:37:07 +0100532 // 1 wide result, treat as unique each time, use result s_reg - will be unique.
533 res = GetOperandValueWide(mir->ssa_rep->defs[0]);
534 SetOperandValueWide(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -0800535 break;
536
537 case kMirOpPhi:
538 /*
539 * Because we'll only see phi nodes at the beginning of an extended basic block,
540 * we can ignore them. Revisit if we shift to global value numbering.
541 */
542 break;
543
544 case Instruction::MOVE:
545 case Instruction::MOVE_OBJECT:
546 case Instruction::MOVE_16:
547 case Instruction::MOVE_OBJECT_16:
548 case Instruction::MOVE_FROM16:
549 case Instruction::MOVE_OBJECT_FROM16:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000550 case kMirOpCopy:
551 // Just copy value number of source to value number of result.
552 res = GetOperandValue(mir->ssa_rep->uses[0]);
553 SetOperandValue(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -0800554 break;
555
556 case Instruction::MOVE_WIDE:
557 case Instruction::MOVE_WIDE_16:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000558 case Instruction::MOVE_WIDE_FROM16:
559 // Just copy value number of source to value number of result.
560 res = GetOperandValueWide(mir->ssa_rep->uses[0]);
561 SetOperandValueWide(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -0800562 break;
563
564 case Instruction::CONST:
565 case Instruction::CONST_4:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000566 case Instruction::CONST_16:
567 res = LookupValue(Instruction::CONST, Low16Bits(mir->dalvikInsn.vB),
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100568 High16Bits(mir->dalvikInsn.vB), 0);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000569 SetOperandValue(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -0800570 break;
571
Vladimir Markof59f18b2014-02-17 15:53:57 +0000572 case Instruction::CONST_HIGH16:
573 res = LookupValue(Instruction::CONST, 0, mir->dalvikInsn.vB, 0);
574 SetOperandValue(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -0800575 break;
576
577 case Instruction::CONST_WIDE_16:
578 case Instruction::CONST_WIDE_32: {
579 uint16_t low_res = LookupValue(Instruction::CONST, Low16Bits(mir->dalvikInsn.vB),
580 High16Bits(mir->dalvikInsn.vB >> 16), 1);
581 uint16_t high_res;
582 if (mir->dalvikInsn.vB & 0x80000000) {
583 high_res = LookupValue(Instruction::CONST, 0xffff, 0xffff, 2);
584 } else {
585 high_res = LookupValue(Instruction::CONST, 0, 0, 2);
586 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000587 res = LookupValue(Instruction::CONST, low_res, high_res, 3);
588 SetOperandValueWide(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -0800589 }
590 break;
591
592 case Instruction::CONST_WIDE: {
593 uint32_t low_word = Low32Bits(mir->dalvikInsn.vB_wide);
594 uint32_t high_word = High32Bits(mir->dalvikInsn.vB_wide);
595 uint16_t low_res = LookupValue(Instruction::CONST, Low16Bits(low_word),
596 High16Bits(low_word), 1);
597 uint16_t high_res = LookupValue(Instruction::CONST, Low16Bits(high_word),
598 High16Bits(high_word), 2);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000599 res = LookupValue(Instruction::CONST, low_res, high_res, 3);
buzbee2502e002012-12-31 16:05:53 -0800600 SetOperandValueWide(mir->ssa_rep->defs[0], res);
601 }
602 break;
603
604 case Instruction::CONST_WIDE_HIGH16: {
605 uint16_t low_res = LookupValue(Instruction::CONST, 0, 0, 1);
606 uint16_t high_res = LookupValue(Instruction::CONST, 0, Low16Bits(mir->dalvikInsn.vB), 2);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000607 res = LookupValue(Instruction::CONST, low_res, high_res, 3);
buzbee2502e002012-12-31 16:05:53 -0800608 SetOperandValueWide(mir->ssa_rep->defs[0], res);
609 }
610 break;
611
612 case Instruction::ARRAY_LENGTH:
613 case Instruction::NEG_INT:
614 case Instruction::NOT_INT:
615 case Instruction::NEG_FLOAT:
616 case Instruction::INT_TO_BYTE:
617 case Instruction::INT_TO_SHORT:
618 case Instruction::INT_TO_CHAR:
619 case Instruction::INT_TO_FLOAT:
620 case Instruction::FLOAT_TO_INT: {
621 // res = op + 1 operand
622 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100623 res = LookupValue(opcode, operand1, kNoValue, kNoValue);
buzbee2502e002012-12-31 16:05:53 -0800624 SetOperandValue(mir->ssa_rep->defs[0], res);
625 }
626 break;
627
628 case Instruction::LONG_TO_FLOAT:
629 case Instruction::LONG_TO_INT:
630 case Instruction::DOUBLE_TO_FLOAT:
631 case Instruction::DOUBLE_TO_INT: {
632 // res = op + 1 wide operand
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100633 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
634 res = LookupValue(opcode, operand1, kNoValue, kNoValue);
buzbee2502e002012-12-31 16:05:53 -0800635 SetOperandValue(mir->ssa_rep->defs[0], res);
636 }
637 break;
638
639
640 case Instruction::DOUBLE_TO_LONG:
641 case Instruction::LONG_TO_DOUBLE:
642 case Instruction::NEG_LONG:
643 case Instruction::NOT_LONG:
644 case Instruction::NEG_DOUBLE: {
645 // wide res = op + 1 wide operand
646 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100647 res = LookupValue(opcode, operand1, kNoValue, kNoValue);
buzbee2502e002012-12-31 16:05:53 -0800648 SetOperandValueWide(mir->ssa_rep->defs[0], res);
649 }
650 break;
651
652 case Instruction::FLOAT_TO_DOUBLE:
653 case Instruction::FLOAT_TO_LONG:
654 case Instruction::INT_TO_DOUBLE:
655 case Instruction::INT_TO_LONG: {
656 // wide res = op + 1 operand
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100657 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
658 res = LookupValue(opcode, operand1, kNoValue, kNoValue);
buzbee2502e002012-12-31 16:05:53 -0800659 SetOperandValueWide(mir->ssa_rep->defs[0], res);
660 }
661 break;
662
663 case Instruction::CMPL_DOUBLE:
664 case Instruction::CMPG_DOUBLE:
665 case Instruction::CMP_LONG: {
666 // res = op + 2 wide operands
667 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
668 uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100669 res = LookupValue(opcode, operand1, operand2, kNoValue);
buzbee2502e002012-12-31 16:05:53 -0800670 SetOperandValue(mir->ssa_rep->defs[0], res);
671 }
672 break;
673
674 case Instruction::CMPG_FLOAT:
675 case Instruction::CMPL_FLOAT:
676 case Instruction::ADD_INT:
677 case Instruction::ADD_INT_2ADDR:
678 case Instruction::MUL_INT:
679 case Instruction::MUL_INT_2ADDR:
680 case Instruction::AND_INT:
681 case Instruction::AND_INT_2ADDR:
682 case Instruction::OR_INT:
683 case Instruction::OR_INT_2ADDR:
684 case Instruction::XOR_INT:
685 case Instruction::XOR_INT_2ADDR:
686 case Instruction::SUB_INT:
687 case Instruction::SUB_INT_2ADDR:
688 case Instruction::DIV_INT:
689 case Instruction::DIV_INT_2ADDR:
690 case Instruction::REM_INT:
691 case Instruction::REM_INT_2ADDR:
692 case Instruction::SHL_INT:
693 case Instruction::SHL_INT_2ADDR:
694 case Instruction::SHR_INT:
695 case Instruction::SHR_INT_2ADDR:
696 case Instruction::USHR_INT:
697 case Instruction::USHR_INT_2ADDR: {
698 // res = op + 2 operands
699 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
700 uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[1]);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100701 res = LookupValue(opcode, operand1, operand2, kNoValue);
buzbee2502e002012-12-31 16:05:53 -0800702 SetOperandValue(mir->ssa_rep->defs[0], res);
703 }
704 break;
705
706 case Instruction::ADD_LONG:
707 case Instruction::SUB_LONG:
708 case Instruction::MUL_LONG:
709 case Instruction::DIV_LONG:
710 case Instruction::REM_LONG:
711 case Instruction::AND_LONG:
712 case Instruction::OR_LONG:
713 case Instruction::XOR_LONG:
714 case Instruction::ADD_LONG_2ADDR:
715 case Instruction::SUB_LONG_2ADDR:
716 case Instruction::MUL_LONG_2ADDR:
717 case Instruction::DIV_LONG_2ADDR:
718 case Instruction::REM_LONG_2ADDR:
719 case Instruction::AND_LONG_2ADDR:
720 case Instruction::OR_LONG_2ADDR:
721 case Instruction::XOR_LONG_2ADDR:
722 case Instruction::ADD_DOUBLE:
723 case Instruction::SUB_DOUBLE:
724 case Instruction::MUL_DOUBLE:
725 case Instruction::DIV_DOUBLE:
726 case Instruction::REM_DOUBLE:
727 case Instruction::ADD_DOUBLE_2ADDR:
728 case Instruction::SUB_DOUBLE_2ADDR:
729 case Instruction::MUL_DOUBLE_2ADDR:
730 case Instruction::DIV_DOUBLE_2ADDR:
731 case Instruction::REM_DOUBLE_2ADDR: {
732 // wide res = op + 2 wide operands
733 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
734 uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100735 res = LookupValue(opcode, operand1, operand2, kNoValue);
buzbee2502e002012-12-31 16:05:53 -0800736 SetOperandValueWide(mir->ssa_rep->defs[0], res);
737 }
738 break;
739
740 case Instruction::SHL_LONG:
741 case Instruction::SHR_LONG:
742 case Instruction::USHR_LONG:
743 case Instruction::SHL_LONG_2ADDR:
744 case Instruction::SHR_LONG_2ADDR:
745 case Instruction::USHR_LONG_2ADDR: {
746 // wide res = op + 1 wide operand + 1 operand
747 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100748 uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[2]);
749 res = LookupValue(opcode, operand1, operand2, kNoValue);
buzbee2502e002012-12-31 16:05:53 -0800750 SetOperandValueWide(mir->ssa_rep->defs[0], res);
751 }
752 break;
753
754 case Instruction::ADD_FLOAT:
755 case Instruction::SUB_FLOAT:
756 case Instruction::MUL_FLOAT:
757 case Instruction::DIV_FLOAT:
758 case Instruction::REM_FLOAT:
759 case Instruction::ADD_FLOAT_2ADDR:
760 case Instruction::SUB_FLOAT_2ADDR:
761 case Instruction::MUL_FLOAT_2ADDR:
762 case Instruction::DIV_FLOAT_2ADDR:
763 case Instruction::REM_FLOAT_2ADDR: {
764 // res = op + 2 operands
765 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
766 uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[1]);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100767 res = LookupValue(opcode, operand1, operand2, kNoValue);
buzbee2502e002012-12-31 16:05:53 -0800768 SetOperandValue(mir->ssa_rep->defs[0], res);
769 }
770 break;
771
772 case Instruction::RSUB_INT:
773 case Instruction::ADD_INT_LIT16:
774 case Instruction::MUL_INT_LIT16:
775 case Instruction::DIV_INT_LIT16:
776 case Instruction::REM_INT_LIT16:
777 case Instruction::AND_INT_LIT16:
778 case Instruction::OR_INT_LIT16:
779 case Instruction::XOR_INT_LIT16:
780 case Instruction::ADD_INT_LIT8:
781 case Instruction::RSUB_INT_LIT8:
782 case Instruction::MUL_INT_LIT8:
783 case Instruction::DIV_INT_LIT8:
784 case Instruction::REM_INT_LIT8:
785 case Instruction::AND_INT_LIT8:
786 case Instruction::OR_INT_LIT8:
787 case Instruction::XOR_INT_LIT8:
788 case Instruction::SHL_INT_LIT8:
789 case Instruction::SHR_INT_LIT8:
790 case Instruction::USHR_INT_LIT8: {
nikolay serdjukee40aa42014-03-25 12:21:29 +0700791 // Same as res = op + 2 operands, except use vC as operand 2
buzbee2502e002012-12-31 16:05:53 -0800792 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
nikolay serdjukee40aa42014-03-25 12:21:29 +0700793 uint16_t operand2 = LookupValue(Instruction::CONST, mir->dalvikInsn.vC, 0, 0);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100794 res = LookupValue(opcode, operand1, operand2, kNoValue);
buzbee2502e002012-12-31 16:05:53 -0800795 SetOperandValue(mir->ssa_rep->defs[0], res);
796 }
797 break;
798
buzbee2502e002012-12-31 16:05:53 -0800799 case Instruction::AGET_OBJECT:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000800 case Instruction::AGET:
801 case Instruction::AGET_WIDE:
buzbee2502e002012-12-31 16:05:53 -0800802 case Instruction::AGET_BOOLEAN:
803 case Instruction::AGET_BYTE:
804 case Instruction::AGET_CHAR:
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100805 case Instruction::AGET_SHORT:
806 res = HandleAGet(mir, opcode);
buzbee2502e002012-12-31 16:05:53 -0800807 break;
808
buzbee2502e002012-12-31 16:05:53 -0800809 case Instruction::APUT_OBJECT:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000810 HandlePutObject(mir);
811 // Intentional fall-through.
812 case Instruction::APUT:
813 case Instruction::APUT_WIDE:
buzbee2502e002012-12-31 16:05:53 -0800814 case Instruction::APUT_BYTE:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000815 case Instruction::APUT_BOOLEAN:
816 case Instruction::APUT_SHORT:
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100817 case Instruction::APUT_CHAR:
818 HandleAPut(mir, opcode);
buzbee2502e002012-12-31 16:05:53 -0800819 break;
820
821 case Instruction::IGET_OBJECT:
buzbee2502e002012-12-31 16:05:53 -0800822 case Instruction::IGET:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000823 case Instruction::IGET_WIDE:
buzbee2502e002012-12-31 16:05:53 -0800824 case Instruction::IGET_BOOLEAN:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000825 case Instruction::IGET_BYTE:
826 case Instruction::IGET_CHAR:
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100827 case Instruction::IGET_SHORT:
828 res = HandleIGet(mir, opcode);
buzbee2502e002012-12-31 16:05:53 -0800829 break;
830
buzbee2502e002012-12-31 16:05:53 -0800831 case Instruction::IPUT_OBJECT:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000832 HandlePutObject(mir);
833 // Intentional fall-through.
buzbee2502e002012-12-31 16:05:53 -0800834 case Instruction::IPUT:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000835 case Instruction::IPUT_WIDE:
buzbee2502e002012-12-31 16:05:53 -0800836 case Instruction::IPUT_BOOLEAN:
837 case Instruction::IPUT_BYTE:
838 case Instruction::IPUT_CHAR:
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100839 case Instruction::IPUT_SHORT:
840 HandleIPut(mir, opcode);
buzbee2502e002012-12-31 16:05:53 -0800841 break;
842
843 case Instruction::SGET_OBJECT:
844 case Instruction::SGET:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000845 case Instruction::SGET_WIDE:
buzbee2502e002012-12-31 16:05:53 -0800846 case Instruction::SGET_BOOLEAN:
847 case Instruction::SGET_BYTE:
848 case Instruction::SGET_CHAR:
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100849 case Instruction::SGET_SHORT:
850 res = HandleSGet(mir, opcode);
buzbee2502e002012-12-31 16:05:53 -0800851 break;
852
853 case Instruction::SPUT_OBJECT:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000854 HandlePutObject(mir);
855 // Intentional fall-through.
buzbee2502e002012-12-31 16:05:53 -0800856 case Instruction::SPUT:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000857 case Instruction::SPUT_WIDE:
buzbee2502e002012-12-31 16:05:53 -0800858 case Instruction::SPUT_BOOLEAN:
859 case Instruction::SPUT_BYTE:
860 case Instruction::SPUT_CHAR:
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100861 case Instruction::SPUT_SHORT:
862 HandleSPut(mir, opcode);
buzbee2502e002012-12-31 16:05:53 -0800863 break;
buzbee2502e002012-12-31 16:05:53 -0800864 }
865 return res;
866}
867
868} // namespace art