blob: a3ea034902d3b5dcc947f2bbcbb6bc185dda77a9 [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 Markof59f18b2014-02-17 15:53:57 +000019#include "mir_graph.h"
20
buzbee2502e002012-12-31 16:05:53 -080021namespace art {
22
Vladimir Markof59f18b2014-02-17 15:53:57 +000023uint16_t LocalValueNumbering::GetFieldId(const DexFile* dex_file, uint16_t field_idx) {
24 FieldReference key = { dex_file, field_idx };
25 auto it = field_index_map_.find(key);
26 if (it != field_index_map_.end()) {
27 return it->second;
28 }
29 uint16_t id = field_index_map_.size();
30 field_index_map_.Put(key, id);
31 return id;
32}
33
34void LocalValueNumbering::AdvanceGlobalMemory() {
35 // See AdvanceMemoryVersion() for explanation.
36 global_memory_version_ = next_memory_version_;
37 ++next_memory_version_;
38}
39
40uint16_t LocalValueNumbering::GetMemoryVersion(uint16_t base, uint16_t field, uint16_t type) {
41 // See AdvanceMemoryVersion() for explanation.
42 MemoryVersionKey key = { base, field, type };
43 MemoryVersionMap::iterator it = memory_version_map_.find(key);
44 uint16_t memory_version = (it != memory_version_map_.end()) ? it->second : 0u;
45 if (base != NO_VALUE && non_aliasing_refs_.find(base) == non_aliasing_refs_.end()) {
46 // Check modifications by potentially aliased access.
47 MemoryVersionKey aliased_access_key = { NO_VALUE, field, type };
48 auto aa_it = memory_version_map_.find(aliased_access_key);
49 if (aa_it != memory_version_map_.end() && aa_it->second > memory_version) {
50 memory_version = aa_it->second;
51 }
52 memory_version = std::max(memory_version, global_memory_version_);
53 } else if (base != NO_VALUE) {
54 // Ignore global_memory_version_ for access via unique references.
55 } else {
56 memory_version = std::max(memory_version, global_memory_version_);
57 }
58 return memory_version;
59};
60
61uint16_t LocalValueNumbering::AdvanceMemoryVersion(uint16_t base, uint16_t field, uint16_t type) {
62 // When we read the same value from memory, we want to assign the same value name to it.
63 // However, we need to be careful not to assign the same value name if the memory location
64 // may have been written to between the reads. To avoid that we do "memory versioning".
65 //
66 // For each write to a memory location (instance field, static field, array element) we assign
67 // a new memory version number to the location identified by the value name of the base register,
68 // the field id and type, or "{ base, field, type }". For static fields the "base" is NO_VALUE
69 // since they are not accessed via a reference. For arrays the "field" is NO_VALUE since they
70 // don't have a field id.
71 //
72 // To account for the possibility of aliased access to the same memory location via different
73 // "base", we also store the memory version number with the key "{ NO_VALUE, field, type }"
74 // if "base" is an aliasing reference and check it in GetMemoryVersion() on reads via
75 // aliasing references. A global memory version is set for method calls as a method can
76 // potentially write to any memory location accessed via an aliasing reference.
77
78 uint16_t result = next_memory_version_;
79 ++next_memory_version_;
80 MemoryVersionKey key = { base, field, type };
81 memory_version_map_.Overwrite(key, result);
82 if (base != NO_VALUE && non_aliasing_refs_.find(base) == non_aliasing_refs_.end()) {
83 // Advance memory version for aliased access.
84 MemoryVersionKey aliased_access_key = { NO_VALUE, field, type };
85 memory_version_map_.Overwrite(aliased_access_key, result);
86 }
87 return result;
88};
89
90uint16_t LocalValueNumbering::MarkNonAliasingNonNull(MIR* mir) {
91 uint16_t res = GetOperandValue(mir->ssa_rep->defs[0]);
92 SetOperandValue(mir->ssa_rep->defs[0], res);
93 DCHECK(null_checked_.find(res) == null_checked_.end());
94 null_checked_.insert(res);
95 non_aliasing_refs_.insert(res);
96 return res;
97}
98
99void LocalValueNumbering::MakeArgsAliasing(MIR* mir) {
100 for (size_t i = 0u, count = mir->ssa_rep->num_uses; i != count; ++i) {
101 uint16_t reg = GetOperandValue(mir->ssa_rep->uses[i]);
102 non_aliasing_refs_.erase(reg);
103 }
104}
105
106void LocalValueNumbering::HandleNullCheck(MIR* mir, uint16_t reg) {
107 if (null_checked_.find(reg) != null_checked_.end()) {
108 if (cu_->verbose) {
109 LOG(INFO) << "Removing null check for 0x" << std::hex << mir->offset;
110 }
111 mir->optimization_flags |= MIR_IGNORE_NULL_CHECK;
112 } else {
113 null_checked_.insert(reg);
114 }
115}
116
117void LocalValueNumbering::HandleRangeCheck(MIR* mir, uint16_t array, uint16_t index) {
118 if (ValueExists(ARRAY_REF, array, index, NO_VALUE)) {
119 if (cu_->verbose) {
120 LOG(INFO) << "Removing range check for 0x" << std::hex << mir->offset;
121 }
122 mir->optimization_flags |= MIR_IGNORE_RANGE_CHECK;
123 }
124 // Use side effect to note range check completed.
125 (void)LookupValue(ARRAY_REF, array, index, NO_VALUE);
126}
127
128void LocalValueNumbering::HandlePutObject(MIR* mir) {
129 // If we're storing a non-aliasing reference, stop tracking it as non-aliasing now.
130 uint16_t base = GetOperandValue(mir->ssa_rep->uses[0]);
131 non_aliasing_refs_.erase(base);
132}
buzbee2502e002012-12-31 16:05:53 -0800133
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700134uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) {
buzbee2502e002012-12-31 16:05:53 -0800135 uint16_t res = NO_VALUE;
136 uint16_t opcode = mir->dalvikInsn.opcode;
137 switch (opcode) {
138 case Instruction::NOP:
139 case Instruction::RETURN_VOID:
140 case Instruction::RETURN:
141 case Instruction::RETURN_OBJECT:
142 case Instruction::RETURN_WIDE:
143 case Instruction::MONITOR_ENTER:
144 case Instruction::MONITOR_EXIT:
145 case Instruction::GOTO:
146 case Instruction::GOTO_16:
147 case Instruction::GOTO_32:
148 case Instruction::CHECK_CAST:
149 case Instruction::THROW:
150 case Instruction::FILL_ARRAY_DATA:
buzbee2502e002012-12-31 16:05:53 -0800151 case Instruction::PACKED_SWITCH:
152 case Instruction::SPARSE_SWITCH:
153 case Instruction::IF_EQ:
154 case Instruction::IF_NE:
155 case Instruction::IF_LT:
156 case Instruction::IF_GE:
157 case Instruction::IF_GT:
158 case Instruction::IF_LE:
159 case Instruction::IF_EQZ:
160 case Instruction::IF_NEZ:
161 case Instruction::IF_LTZ:
162 case Instruction::IF_GEZ:
163 case Instruction::IF_GTZ:
164 case Instruction::IF_LEZ:
buzbee2502e002012-12-31 16:05:53 -0800165 case kMirOpFusedCmplFloat:
166 case kMirOpFusedCmpgFloat:
167 case kMirOpFusedCmplDouble:
168 case kMirOpFusedCmpgDouble:
169 case kMirOpFusedCmpLong:
170 // Nothing defined - take no action.
171 break;
172
Vladimir Markof59f18b2014-02-17 15:53:57 +0000173 case Instruction::FILLED_NEW_ARRAY:
174 case Instruction::FILLED_NEW_ARRAY_RANGE:
175 // Nothing defined but the result will be unique and non-null.
176 if (mir->next != nullptr && mir->next->dalvikInsn.opcode == Instruction::MOVE_RESULT_OBJECT) {
177 MarkNonAliasingNonNull(mir->next);
178 // The MOVE_RESULT_OBJECT will be processed next and we'll return the value name then.
179 }
180 MakeArgsAliasing(mir);
181 break;
182
183 case Instruction::INVOKE_DIRECT:
184 case Instruction::INVOKE_DIRECT_RANGE:
185 case Instruction::INVOKE_VIRTUAL:
186 case Instruction::INVOKE_VIRTUAL_RANGE:
187 case Instruction::INVOKE_SUPER:
188 case Instruction::INVOKE_SUPER_RANGE:
189 case Instruction::INVOKE_INTERFACE:
190 case Instruction::INVOKE_INTERFACE_RANGE: {
191 // Nothing defined but handle the null check.
192 uint16_t reg = GetOperandValue(mir->ssa_rep->uses[0]);
193 HandleNullCheck(mir, reg);
194 }
195 // Intentional fall-through.
196 case Instruction::INVOKE_STATIC:
197 case Instruction::INVOKE_STATIC_RANGE:
198 AdvanceGlobalMemory();
199 MakeArgsAliasing(mir);
200 break;
201
buzbee2502e002012-12-31 16:05:53 -0800202 case Instruction::MOVE_RESULT:
203 case Instruction::MOVE_RESULT_OBJECT:
204 case Instruction::INSTANCE_OF:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000205 // 1 result, treat as unique each time, use result s_reg - will be unique.
206 res = GetOperandValue(mir->ssa_rep->defs[0]);
207 SetOperandValue(mir->ssa_rep->defs[0], res);
208 break;
209 case Instruction::MOVE_EXCEPTION:
buzbee2502e002012-12-31 16:05:53 -0800210 case Instruction::NEW_INSTANCE:
211 case Instruction::CONST_STRING:
212 case Instruction::CONST_STRING_JUMBO:
213 case Instruction::CONST_CLASS:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000214 case Instruction::NEW_ARRAY:
215 // 1 result, treat as unique each time, use result s_reg - will be unique.
216 res = MarkNonAliasingNonNull(mir);
buzbee2502e002012-12-31 16:05:53 -0800217 break;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000218 case Instruction::MOVE_RESULT_WIDE:
219 // 1 wide result, treat as unique each time, use result s_reg - will be unique.
220 res = GetOperandValueWide(mir->ssa_rep->defs[0]);
221 SetOperandValueWide(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -0800222 break;
223
224 case kMirOpPhi:
225 /*
226 * Because we'll only see phi nodes at the beginning of an extended basic block,
227 * we can ignore them. Revisit if we shift to global value numbering.
228 */
229 break;
230
231 case Instruction::MOVE:
232 case Instruction::MOVE_OBJECT:
233 case Instruction::MOVE_16:
234 case Instruction::MOVE_OBJECT_16:
235 case Instruction::MOVE_FROM16:
236 case Instruction::MOVE_OBJECT_FROM16:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000237 case kMirOpCopy:
238 // Just copy value number of source to value number of result.
239 res = GetOperandValue(mir->ssa_rep->uses[0]);
240 SetOperandValue(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -0800241 break;
242
243 case Instruction::MOVE_WIDE:
244 case Instruction::MOVE_WIDE_16:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000245 case Instruction::MOVE_WIDE_FROM16:
246 // Just copy value number of source to value number of result.
247 res = GetOperandValueWide(mir->ssa_rep->uses[0]);
248 SetOperandValueWide(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -0800249 break;
250
251 case Instruction::CONST:
252 case Instruction::CONST_4:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000253 case Instruction::CONST_16:
254 res = LookupValue(Instruction::CONST, Low16Bits(mir->dalvikInsn.vB),
255 High16Bits(mir->dalvikInsn.vB >> 16), 0);
256 SetOperandValue(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -0800257 break;
258
Vladimir Markof59f18b2014-02-17 15:53:57 +0000259 case Instruction::CONST_HIGH16:
260 res = LookupValue(Instruction::CONST, 0, mir->dalvikInsn.vB, 0);
261 SetOperandValue(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -0800262 break;
263
264 case Instruction::CONST_WIDE_16:
265 case Instruction::CONST_WIDE_32: {
266 uint16_t low_res = LookupValue(Instruction::CONST, Low16Bits(mir->dalvikInsn.vB),
267 High16Bits(mir->dalvikInsn.vB >> 16), 1);
268 uint16_t high_res;
269 if (mir->dalvikInsn.vB & 0x80000000) {
270 high_res = LookupValue(Instruction::CONST, 0xffff, 0xffff, 2);
271 } else {
272 high_res = LookupValue(Instruction::CONST, 0, 0, 2);
273 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000274 res = LookupValue(Instruction::CONST, low_res, high_res, 3);
275 SetOperandValueWide(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -0800276 }
277 break;
278
279 case Instruction::CONST_WIDE: {
280 uint32_t low_word = Low32Bits(mir->dalvikInsn.vB_wide);
281 uint32_t high_word = High32Bits(mir->dalvikInsn.vB_wide);
282 uint16_t low_res = LookupValue(Instruction::CONST, Low16Bits(low_word),
283 High16Bits(low_word), 1);
284 uint16_t high_res = LookupValue(Instruction::CONST, Low16Bits(high_word),
285 High16Bits(high_word), 2);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000286 res = LookupValue(Instruction::CONST, low_res, high_res, 3);
buzbee2502e002012-12-31 16:05:53 -0800287 SetOperandValueWide(mir->ssa_rep->defs[0], res);
288 }
289 break;
290
291 case Instruction::CONST_WIDE_HIGH16: {
292 uint16_t low_res = LookupValue(Instruction::CONST, 0, 0, 1);
293 uint16_t high_res = LookupValue(Instruction::CONST, 0, Low16Bits(mir->dalvikInsn.vB), 2);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000294 res = LookupValue(Instruction::CONST, low_res, high_res, 3);
buzbee2502e002012-12-31 16:05:53 -0800295 SetOperandValueWide(mir->ssa_rep->defs[0], res);
296 }
297 break;
298
299 case Instruction::ARRAY_LENGTH:
300 case Instruction::NEG_INT:
301 case Instruction::NOT_INT:
302 case Instruction::NEG_FLOAT:
303 case Instruction::INT_TO_BYTE:
304 case Instruction::INT_TO_SHORT:
305 case Instruction::INT_TO_CHAR:
306 case Instruction::INT_TO_FLOAT:
307 case Instruction::FLOAT_TO_INT: {
308 // res = op + 1 operand
309 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000310 res = LookupValue(opcode, operand1, NO_VALUE, NO_VALUE);
buzbee2502e002012-12-31 16:05:53 -0800311 SetOperandValue(mir->ssa_rep->defs[0], res);
312 }
313 break;
314
315 case Instruction::LONG_TO_FLOAT:
316 case Instruction::LONG_TO_INT:
317 case Instruction::DOUBLE_TO_FLOAT:
318 case Instruction::DOUBLE_TO_INT: {
319 // res = op + 1 wide operand
320 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000321 res = LookupValue(opcode, operand1, NO_VALUE, NO_VALUE);
buzbee2502e002012-12-31 16:05:53 -0800322 SetOperandValue(mir->ssa_rep->defs[0], res);
323 }
324 break;
325
326
327 case Instruction::DOUBLE_TO_LONG:
328 case Instruction::LONG_TO_DOUBLE:
329 case Instruction::NEG_LONG:
330 case Instruction::NOT_LONG:
331 case Instruction::NEG_DOUBLE: {
332 // wide res = op + 1 wide operand
333 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000334 res = LookupValue(opcode, operand1, NO_VALUE, NO_VALUE);
buzbee2502e002012-12-31 16:05:53 -0800335 SetOperandValueWide(mir->ssa_rep->defs[0], res);
336 }
337 break;
338
339 case Instruction::FLOAT_TO_DOUBLE:
340 case Instruction::FLOAT_TO_LONG:
341 case Instruction::INT_TO_DOUBLE:
342 case Instruction::INT_TO_LONG: {
343 // wide res = op + 1 operand
344 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000345 res = LookupValue(opcode, operand1, NO_VALUE, NO_VALUE);
buzbee2502e002012-12-31 16:05:53 -0800346 SetOperandValueWide(mir->ssa_rep->defs[0], res);
347 }
348 break;
349
350 case Instruction::CMPL_DOUBLE:
351 case Instruction::CMPG_DOUBLE:
352 case Instruction::CMP_LONG: {
353 // res = op + 2 wide operands
354 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
355 uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000356 res = LookupValue(opcode, operand1, operand2, NO_VALUE);
buzbee2502e002012-12-31 16:05:53 -0800357 SetOperandValue(mir->ssa_rep->defs[0], res);
358 }
359 break;
360
361 case Instruction::CMPG_FLOAT:
362 case Instruction::CMPL_FLOAT:
363 case Instruction::ADD_INT:
364 case Instruction::ADD_INT_2ADDR:
365 case Instruction::MUL_INT:
366 case Instruction::MUL_INT_2ADDR:
367 case Instruction::AND_INT:
368 case Instruction::AND_INT_2ADDR:
369 case Instruction::OR_INT:
370 case Instruction::OR_INT_2ADDR:
371 case Instruction::XOR_INT:
372 case Instruction::XOR_INT_2ADDR:
373 case Instruction::SUB_INT:
374 case Instruction::SUB_INT_2ADDR:
375 case Instruction::DIV_INT:
376 case Instruction::DIV_INT_2ADDR:
377 case Instruction::REM_INT:
378 case Instruction::REM_INT_2ADDR:
379 case Instruction::SHL_INT:
380 case Instruction::SHL_INT_2ADDR:
381 case Instruction::SHR_INT:
382 case Instruction::SHR_INT_2ADDR:
383 case Instruction::USHR_INT:
384 case Instruction::USHR_INT_2ADDR: {
385 // res = op + 2 operands
386 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
387 uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[1]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000388 res = LookupValue(opcode, operand1, operand2, NO_VALUE);
buzbee2502e002012-12-31 16:05:53 -0800389 SetOperandValue(mir->ssa_rep->defs[0], res);
390 }
391 break;
392
393 case Instruction::ADD_LONG:
394 case Instruction::SUB_LONG:
395 case Instruction::MUL_LONG:
396 case Instruction::DIV_LONG:
397 case Instruction::REM_LONG:
398 case Instruction::AND_LONG:
399 case Instruction::OR_LONG:
400 case Instruction::XOR_LONG:
401 case Instruction::ADD_LONG_2ADDR:
402 case Instruction::SUB_LONG_2ADDR:
403 case Instruction::MUL_LONG_2ADDR:
404 case Instruction::DIV_LONG_2ADDR:
405 case Instruction::REM_LONG_2ADDR:
406 case Instruction::AND_LONG_2ADDR:
407 case Instruction::OR_LONG_2ADDR:
408 case Instruction::XOR_LONG_2ADDR:
409 case Instruction::ADD_DOUBLE:
410 case Instruction::SUB_DOUBLE:
411 case Instruction::MUL_DOUBLE:
412 case Instruction::DIV_DOUBLE:
413 case Instruction::REM_DOUBLE:
414 case Instruction::ADD_DOUBLE_2ADDR:
415 case Instruction::SUB_DOUBLE_2ADDR:
416 case Instruction::MUL_DOUBLE_2ADDR:
417 case Instruction::DIV_DOUBLE_2ADDR:
418 case Instruction::REM_DOUBLE_2ADDR: {
419 // wide res = op + 2 wide operands
420 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
421 uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000422 res = LookupValue(opcode, operand1, operand2, NO_VALUE);
buzbee2502e002012-12-31 16:05:53 -0800423 SetOperandValueWide(mir->ssa_rep->defs[0], res);
424 }
425 break;
426
427 case Instruction::SHL_LONG:
428 case Instruction::SHR_LONG:
429 case Instruction::USHR_LONG:
430 case Instruction::SHL_LONG_2ADDR:
431 case Instruction::SHR_LONG_2ADDR:
432 case Instruction::USHR_LONG_2ADDR: {
433 // wide res = op + 1 wide operand + 1 operand
434 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
435 uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000436 res = LookupValue(opcode, operand1, operand2, NO_VALUE);
buzbee2502e002012-12-31 16:05:53 -0800437 SetOperandValueWide(mir->ssa_rep->defs[0], res);
438 }
439 break;
440
441 case Instruction::ADD_FLOAT:
442 case Instruction::SUB_FLOAT:
443 case Instruction::MUL_FLOAT:
444 case Instruction::DIV_FLOAT:
445 case Instruction::REM_FLOAT:
446 case Instruction::ADD_FLOAT_2ADDR:
447 case Instruction::SUB_FLOAT_2ADDR:
448 case Instruction::MUL_FLOAT_2ADDR:
449 case Instruction::DIV_FLOAT_2ADDR:
450 case Instruction::REM_FLOAT_2ADDR: {
451 // res = op + 2 operands
452 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
453 uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[1]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000454 res = LookupValue(opcode, operand1, operand2, NO_VALUE);
buzbee2502e002012-12-31 16:05:53 -0800455 SetOperandValue(mir->ssa_rep->defs[0], res);
456 }
457 break;
458
459 case Instruction::RSUB_INT:
460 case Instruction::ADD_INT_LIT16:
461 case Instruction::MUL_INT_LIT16:
462 case Instruction::DIV_INT_LIT16:
463 case Instruction::REM_INT_LIT16:
464 case Instruction::AND_INT_LIT16:
465 case Instruction::OR_INT_LIT16:
466 case Instruction::XOR_INT_LIT16:
467 case Instruction::ADD_INT_LIT8:
468 case Instruction::RSUB_INT_LIT8:
469 case Instruction::MUL_INT_LIT8:
470 case Instruction::DIV_INT_LIT8:
471 case Instruction::REM_INT_LIT8:
472 case Instruction::AND_INT_LIT8:
473 case Instruction::OR_INT_LIT8:
474 case Instruction::XOR_INT_LIT8:
475 case Instruction::SHL_INT_LIT8:
476 case Instruction::SHR_INT_LIT8:
477 case Instruction::USHR_INT_LIT8: {
478 // Same as res = op + 2 operands, except use vB as operand 2
479 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
480 uint16_t operand2 = LookupValue(Instruction::CONST, mir->dalvikInsn.vB, 0, 0);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000481 res = LookupValue(opcode, operand1, operand2, NO_VALUE);
buzbee2502e002012-12-31 16:05:53 -0800482 SetOperandValue(mir->ssa_rep->defs[0], res);
483 }
484 break;
485
buzbee2502e002012-12-31 16:05:53 -0800486 case Instruction::AGET_OBJECT:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000487 case Instruction::AGET:
488 case Instruction::AGET_WIDE:
buzbee2502e002012-12-31 16:05:53 -0800489 case Instruction::AGET_BOOLEAN:
490 case Instruction::AGET_BYTE:
491 case Instruction::AGET_CHAR:
492 case Instruction::AGET_SHORT: {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000493 uint16_t type = opcode - Instruction::AGET;
buzbee2502e002012-12-31 16:05:53 -0800494 uint16_t array = GetOperandValue(mir->ssa_rep->uses[0]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000495 HandleNullCheck(mir, array);
buzbee2502e002012-12-31 16:05:53 -0800496 uint16_t index = GetOperandValue(mir->ssa_rep->uses[1]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000497 HandleRangeCheck(mir, array, index);
buzbee2502e002012-12-31 16:05:53 -0800498 // Establish value number for loaded register. Note use of memory version.
Vladimir Markof59f18b2014-02-17 15:53:57 +0000499 uint16_t memory_version = GetMemoryVersion(array, NO_VALUE, type);
buzbee2502e002012-12-31 16:05:53 -0800500 uint16_t res = LookupValue(ARRAY_REF, array, index, memory_version);
501 if (opcode == Instruction::AGET_WIDE) {
502 SetOperandValueWide(mir->ssa_rep->defs[0], res);
503 } else {
504 SetOperandValue(mir->ssa_rep->defs[0], res);
505 }
506 }
507 break;
508
buzbee2502e002012-12-31 16:05:53 -0800509 case Instruction::APUT_OBJECT:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000510 HandlePutObject(mir);
511 // Intentional fall-through.
512 case Instruction::APUT:
513 case Instruction::APUT_WIDE:
buzbee2502e002012-12-31 16:05:53 -0800514 case Instruction::APUT_BYTE:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000515 case Instruction::APUT_BOOLEAN:
516 case Instruction::APUT_SHORT:
517 case Instruction::APUT_CHAR: {
518 uint16_t type = opcode - Instruction::APUT;
buzbee2502e002012-12-31 16:05:53 -0800519 int array_idx = (opcode == Instruction::APUT_WIDE) ? 2 : 1;
520 int index_idx = array_idx + 1;
521 uint16_t array = GetOperandValue(mir->ssa_rep->uses[array_idx]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000522 HandleNullCheck(mir, array);
buzbee2502e002012-12-31 16:05:53 -0800523 uint16_t index = GetOperandValue(mir->ssa_rep->uses[index_idx]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000524 HandleRangeCheck(mir, array, index);
buzbee2502e002012-12-31 16:05:53 -0800525 // Rev the memory version
Vladimir Markof59f18b2014-02-17 15:53:57 +0000526 AdvanceMemoryVersion(array, NO_VALUE, type);
buzbee2502e002012-12-31 16:05:53 -0800527 }
528 break;
529
530 case Instruction::IGET_OBJECT:
buzbee2502e002012-12-31 16:05:53 -0800531 case Instruction::IGET:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000532 case Instruction::IGET_WIDE:
buzbee2502e002012-12-31 16:05:53 -0800533 case Instruction::IGET_BOOLEAN:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000534 case Instruction::IGET_BYTE:
535 case Instruction::IGET_CHAR:
536 case Instruction::IGET_SHORT: {
buzbee2502e002012-12-31 16:05:53 -0800537 uint16_t base = GetOperandValue(mir->ssa_rep->uses[0]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000538 HandleNullCheck(mir, base);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000539 uint16_t memory_version;
540 uint16_t field_id;
Ian Rogers9c86a022014-02-21 16:40:21 +0000541 // TODO: all gets treated as volatile.
542 // Volatile fields always get a new memory version; field id is irrelevant.
543 // Unresolved fields are always marked as volatile and handled the same way here.
544 field_id = 0u;
545 memory_version = next_memory_version_;
546 ++next_memory_version_;
buzbee2502e002012-12-31 16:05:53 -0800547 if (opcode == Instruction::IGET_WIDE) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000548 res = LookupValue(Instruction::IGET_WIDE, base, field_id, memory_version);
buzbee2502e002012-12-31 16:05:53 -0800549 SetOperandValueWide(mir->ssa_rep->defs[0], res);
550 } else {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000551 res = LookupValue(Instruction::IGET, base, field_id, memory_version);
buzbee2502e002012-12-31 16:05:53 -0800552 SetOperandValue(mir->ssa_rep->defs[0], res);
553 }
554 }
555 break;
556
buzbee2502e002012-12-31 16:05:53 -0800557 case Instruction::IPUT_OBJECT:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000558 HandlePutObject(mir);
559 // Intentional fall-through.
buzbee2502e002012-12-31 16:05:53 -0800560 case Instruction::IPUT:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000561 case Instruction::IPUT_WIDE:
buzbee2502e002012-12-31 16:05:53 -0800562 case Instruction::IPUT_BOOLEAN:
563 case Instruction::IPUT_BYTE:
564 case Instruction::IPUT_CHAR:
565 case Instruction::IPUT_SHORT: {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000566 uint16_t type = opcode - Instruction::IPUT;
buzbee2502e002012-12-31 16:05:53 -0800567 int base_reg = (opcode == Instruction::IPUT_WIDE) ? 2 : 1;
568 uint16_t base = GetOperandValue(mir->ssa_rep->uses[base_reg]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000569 HandleNullCheck(mir, base);
Ian Rogers9c86a022014-02-21 16:40:21 +0000570 // TODO: all puts treated as unresolved.
571 // Unresolved fields always alias with everything of the same type.
572 unresolved_ifield_version_[type] = next_memory_version_;
573 ++next_memory_version_;
buzbee2502e002012-12-31 16:05:53 -0800574 }
575 break;
576
577 case Instruction::SGET_OBJECT:
578 case Instruction::SGET:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000579 case Instruction::SGET_WIDE:
buzbee2502e002012-12-31 16:05:53 -0800580 case Instruction::SGET_BOOLEAN:
581 case Instruction::SGET_BYTE:
582 case Instruction::SGET_CHAR:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000583 case Instruction::SGET_SHORT: {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000584 uint16_t memory_version;
585 uint16_t field_id;
Ian Rogers9c86a022014-02-21 16:40:21 +0000586 // TODO: all gets treated as volatile.
587 // Volatile fields always get a new memory version; field id is irrelevant.
588 // Unresolved fields are always marked as volatile and handled the same way here.
589 field_id = 0u;
590 memory_version = next_memory_version_;
591 ++next_memory_version_;
buzbee2502e002012-12-31 16:05:53 -0800592 if (opcode == Instruction::SGET_WIDE) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000593 res = LookupValue(Instruction::SGET_WIDE, NO_VALUE, field_id, memory_version);
buzbee2502e002012-12-31 16:05:53 -0800594 SetOperandValueWide(mir->ssa_rep->defs[0], res);
595 } else {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000596 res = LookupValue(Instruction::SGET, NO_VALUE, field_id, memory_version);
buzbee2502e002012-12-31 16:05:53 -0800597 SetOperandValue(mir->ssa_rep->defs[0], res);
598 }
599 }
600 break;
601
602 case Instruction::SPUT_OBJECT:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000603 HandlePutObject(mir);
604 // Intentional fall-through.
buzbee2502e002012-12-31 16:05:53 -0800605 case Instruction::SPUT:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000606 case Instruction::SPUT_WIDE:
buzbee2502e002012-12-31 16:05:53 -0800607 case Instruction::SPUT_BOOLEAN:
608 case Instruction::SPUT_BYTE:
609 case Instruction::SPUT_CHAR:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000610 case Instruction::SPUT_SHORT: {
611 uint16_t type = opcode - Instruction::SPUT;
Ian Rogers9c86a022014-02-21 16:40:21 +0000612 // TODO: all puts treated as unresolved.
613 // Unresolved fields always alias with everything of the same type.
614 unresolved_sfield_version_[type] = next_memory_version_;
615 ++next_memory_version_;
buzbee2502e002012-12-31 16:05:53 -0800616 }
617 break;
buzbee2502e002012-12-31 16:05:53 -0800618 }
619 return res;
620}
621
622} // namespace art