blob: 8dbc2bb9c3c674eade84a5528449c2c7d0040097 [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 Markof59f18b2014-02-17 15:53:57 +000024uint16_t LocalValueNumbering::GetFieldId(const DexFile* dex_file, uint16_t field_idx) {
25 FieldReference key = { dex_file, field_idx };
26 auto it = field_index_map_.find(key);
27 if (it != field_index_map_.end()) {
28 return it->second;
29 }
30 uint16_t id = field_index_map_.size();
31 field_index_map_.Put(key, id);
32 return id;
33}
34
35void LocalValueNumbering::AdvanceGlobalMemory() {
36 // See AdvanceMemoryVersion() for explanation.
37 global_memory_version_ = next_memory_version_;
38 ++next_memory_version_;
39}
40
41uint16_t LocalValueNumbering::GetMemoryVersion(uint16_t base, uint16_t field, uint16_t type) {
42 // See AdvanceMemoryVersion() for explanation.
43 MemoryVersionKey key = { base, field, type };
44 MemoryVersionMap::iterator it = memory_version_map_.find(key);
45 uint16_t memory_version = (it != memory_version_map_.end()) ? it->second : 0u;
46 if (base != NO_VALUE && non_aliasing_refs_.find(base) == non_aliasing_refs_.end()) {
47 // Check modifications by potentially aliased access.
48 MemoryVersionKey aliased_access_key = { NO_VALUE, field, type };
49 auto aa_it = memory_version_map_.find(aliased_access_key);
50 if (aa_it != memory_version_map_.end() && aa_it->second > memory_version) {
51 memory_version = aa_it->second;
52 }
53 memory_version = std::max(memory_version, global_memory_version_);
54 } else if (base != NO_VALUE) {
55 // Ignore global_memory_version_ for access via unique references.
56 } else {
57 memory_version = std::max(memory_version, global_memory_version_);
58 }
59 return memory_version;
60};
61
62uint16_t LocalValueNumbering::AdvanceMemoryVersion(uint16_t base, uint16_t field, uint16_t type) {
63 // When we read the same value from memory, we want to assign the same value name to it.
64 // However, we need to be careful not to assign the same value name if the memory location
65 // may have been written to between the reads. To avoid that we do "memory versioning".
66 //
67 // For each write to a memory location (instance field, static field, array element) we assign
68 // a new memory version number to the location identified by the value name of the base register,
69 // the field id and type, or "{ base, field, type }". For static fields the "base" is NO_VALUE
70 // since they are not accessed via a reference. For arrays the "field" is NO_VALUE since they
71 // don't have a field id.
72 //
73 // To account for the possibility of aliased access to the same memory location via different
74 // "base", we also store the memory version number with the key "{ NO_VALUE, field, type }"
75 // if "base" is an aliasing reference and check it in GetMemoryVersion() on reads via
76 // aliasing references. A global memory version is set for method calls as a method can
77 // potentially write to any memory location accessed via an aliasing reference.
78
79 uint16_t result = next_memory_version_;
80 ++next_memory_version_;
81 MemoryVersionKey key = { base, field, type };
82 memory_version_map_.Overwrite(key, result);
83 if (base != NO_VALUE && non_aliasing_refs_.find(base) == non_aliasing_refs_.end()) {
84 // Advance memory version for aliased access.
85 MemoryVersionKey aliased_access_key = { NO_VALUE, field, type };
86 memory_version_map_.Overwrite(aliased_access_key, result);
87 }
88 return result;
89};
90
91uint16_t LocalValueNumbering::MarkNonAliasingNonNull(MIR* mir) {
92 uint16_t res = GetOperandValue(mir->ssa_rep->defs[0]);
93 SetOperandValue(mir->ssa_rep->defs[0], res);
94 DCHECK(null_checked_.find(res) == null_checked_.end());
95 null_checked_.insert(res);
96 non_aliasing_refs_.insert(res);
97 return res;
98}
99
100void LocalValueNumbering::MakeArgsAliasing(MIR* mir) {
101 for (size_t i = 0u, count = mir->ssa_rep->num_uses; i != count; ++i) {
102 uint16_t reg = GetOperandValue(mir->ssa_rep->uses[i]);
103 non_aliasing_refs_.erase(reg);
104 }
105}
106
107void LocalValueNumbering::HandleNullCheck(MIR* mir, uint16_t reg) {
108 if (null_checked_.find(reg) != null_checked_.end()) {
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;
113 } else {
114 null_checked_.insert(reg);
115 }
116}
117
118void LocalValueNumbering::HandleRangeCheck(MIR* mir, uint16_t array, uint16_t index) {
119 if (ValueExists(ARRAY_REF, array, index, NO_VALUE)) {
120 if (cu_->verbose) {
121 LOG(INFO) << "Removing range check for 0x" << std::hex << mir->offset;
122 }
123 mir->optimization_flags |= MIR_IGNORE_RANGE_CHECK;
124 }
125 // Use side effect to note range check completed.
126 (void)LookupValue(ARRAY_REF, array, index, NO_VALUE);
127}
128
129void LocalValueNumbering::HandlePutObject(MIR* mir) {
130 // If we're storing a non-aliasing reference, stop tracking it as non-aliasing now.
131 uint16_t base = GetOperandValue(mir->ssa_rep->uses[0]);
132 non_aliasing_refs_.erase(base);
133}
buzbee2502e002012-12-31 16:05:53 -0800134
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700135uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) {
buzbee2502e002012-12-31 16:05:53 -0800136 uint16_t res = NO_VALUE;
137 uint16_t opcode = mir->dalvikInsn.opcode;
138 switch (opcode) {
139 case Instruction::NOP:
140 case Instruction::RETURN_VOID:
141 case Instruction::RETURN:
142 case Instruction::RETURN_OBJECT:
143 case Instruction::RETURN_WIDE:
144 case Instruction::MONITOR_ENTER:
145 case Instruction::MONITOR_EXIT:
146 case Instruction::GOTO:
147 case Instruction::GOTO_16:
148 case Instruction::GOTO_32:
149 case Instruction::CHECK_CAST:
150 case Instruction::THROW:
151 case Instruction::FILL_ARRAY_DATA:
buzbee2502e002012-12-31 16:05:53 -0800152 case Instruction::PACKED_SWITCH:
153 case Instruction::SPARSE_SWITCH:
154 case Instruction::IF_EQ:
155 case Instruction::IF_NE:
156 case Instruction::IF_LT:
157 case Instruction::IF_GE:
158 case Instruction::IF_GT:
159 case Instruction::IF_LE:
160 case Instruction::IF_EQZ:
161 case Instruction::IF_NEZ:
162 case Instruction::IF_LTZ:
163 case Instruction::IF_GEZ:
164 case Instruction::IF_GTZ:
165 case Instruction::IF_LEZ:
buzbee2502e002012-12-31 16:05:53 -0800166 case kMirOpFusedCmplFloat:
167 case kMirOpFusedCmpgFloat:
168 case kMirOpFusedCmplDouble:
169 case kMirOpFusedCmpgDouble:
170 case kMirOpFusedCmpLong:
171 // Nothing defined - take no action.
172 break;
173
Vladimir Markof59f18b2014-02-17 15:53:57 +0000174 case Instruction::FILLED_NEW_ARRAY:
175 case Instruction::FILLED_NEW_ARRAY_RANGE:
176 // Nothing defined but the result will be unique and non-null.
177 if (mir->next != nullptr && mir->next->dalvikInsn.opcode == Instruction::MOVE_RESULT_OBJECT) {
178 MarkNonAliasingNonNull(mir->next);
179 // The MOVE_RESULT_OBJECT will be processed next and we'll return the value name then.
180 }
181 MakeArgsAliasing(mir);
182 break;
183
184 case Instruction::INVOKE_DIRECT:
185 case Instruction::INVOKE_DIRECT_RANGE:
186 case Instruction::INVOKE_VIRTUAL:
187 case Instruction::INVOKE_VIRTUAL_RANGE:
188 case Instruction::INVOKE_SUPER:
189 case Instruction::INVOKE_SUPER_RANGE:
190 case Instruction::INVOKE_INTERFACE:
191 case Instruction::INVOKE_INTERFACE_RANGE: {
192 // Nothing defined but handle the null check.
193 uint16_t reg = GetOperandValue(mir->ssa_rep->uses[0]);
194 HandleNullCheck(mir, reg);
195 }
196 // Intentional fall-through.
197 case Instruction::INVOKE_STATIC:
198 case Instruction::INVOKE_STATIC_RANGE:
Vladimir Marko9820b7c2014-01-02 16:40:37 +0000199 if ((mir->optimization_flags & MIR_INLINED) == 0) {
200 AdvanceGlobalMemory();
201 MakeArgsAliasing(mir);
202 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000203 break;
204
buzbee2502e002012-12-31 16:05:53 -0800205 case Instruction::MOVE_RESULT:
206 case Instruction::MOVE_RESULT_OBJECT:
207 case Instruction::INSTANCE_OF:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000208 // 1 result, treat as unique each time, use result s_reg - will be unique.
209 res = GetOperandValue(mir->ssa_rep->defs[0]);
210 SetOperandValue(mir->ssa_rep->defs[0], res);
211 break;
212 case Instruction::MOVE_EXCEPTION:
buzbee2502e002012-12-31 16:05:53 -0800213 case Instruction::NEW_INSTANCE:
214 case Instruction::CONST_STRING:
215 case Instruction::CONST_STRING_JUMBO:
216 case Instruction::CONST_CLASS:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000217 case Instruction::NEW_ARRAY:
Vladimir Marko9820b7c2014-01-02 16:40:37 +0000218 if ((mir->optimization_flags & MIR_INLINED) == 0) {
219 // 1 result, treat as unique each time, use result s_reg - will be unique.
220 res = MarkNonAliasingNonNull(mir);
221 }
buzbee2502e002012-12-31 16:05:53 -0800222 break;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000223 case Instruction::MOVE_RESULT_WIDE:
Vladimir Marko9820b7c2014-01-02 16:40:37 +0000224 if ((mir->optimization_flags & MIR_INLINED) == 0) {
225 // 1 wide result, treat as unique each time, use result s_reg - will be unique.
226 res = GetOperandValueWide(mir->ssa_rep->defs[0]);
227 SetOperandValueWide(mir->ssa_rep->defs[0], res);
228 }
buzbee2502e002012-12-31 16:05:53 -0800229 break;
230
231 case kMirOpPhi:
232 /*
233 * Because we'll only see phi nodes at the beginning of an extended basic block,
234 * we can ignore them. Revisit if we shift to global value numbering.
235 */
236 break;
237
238 case Instruction::MOVE:
239 case Instruction::MOVE_OBJECT:
240 case Instruction::MOVE_16:
241 case Instruction::MOVE_OBJECT_16:
242 case Instruction::MOVE_FROM16:
243 case Instruction::MOVE_OBJECT_FROM16:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000244 case kMirOpCopy:
245 // Just copy value number of source to value number of result.
246 res = GetOperandValue(mir->ssa_rep->uses[0]);
247 SetOperandValue(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -0800248 break;
249
250 case Instruction::MOVE_WIDE:
251 case Instruction::MOVE_WIDE_16:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000252 case Instruction::MOVE_WIDE_FROM16:
253 // Just copy value number of source to value number of result.
254 res = GetOperandValueWide(mir->ssa_rep->uses[0]);
255 SetOperandValueWide(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -0800256 break;
257
258 case Instruction::CONST:
259 case Instruction::CONST_4:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000260 case Instruction::CONST_16:
261 res = LookupValue(Instruction::CONST, Low16Bits(mir->dalvikInsn.vB),
262 High16Bits(mir->dalvikInsn.vB >> 16), 0);
263 SetOperandValue(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -0800264 break;
265
Vladimir Markof59f18b2014-02-17 15:53:57 +0000266 case Instruction::CONST_HIGH16:
267 res = LookupValue(Instruction::CONST, 0, mir->dalvikInsn.vB, 0);
268 SetOperandValue(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -0800269 break;
270
271 case Instruction::CONST_WIDE_16:
272 case Instruction::CONST_WIDE_32: {
273 uint16_t low_res = LookupValue(Instruction::CONST, Low16Bits(mir->dalvikInsn.vB),
274 High16Bits(mir->dalvikInsn.vB >> 16), 1);
275 uint16_t high_res;
276 if (mir->dalvikInsn.vB & 0x80000000) {
277 high_res = LookupValue(Instruction::CONST, 0xffff, 0xffff, 2);
278 } else {
279 high_res = LookupValue(Instruction::CONST, 0, 0, 2);
280 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000281 res = LookupValue(Instruction::CONST, low_res, high_res, 3);
282 SetOperandValueWide(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -0800283 }
284 break;
285
286 case Instruction::CONST_WIDE: {
287 uint32_t low_word = Low32Bits(mir->dalvikInsn.vB_wide);
288 uint32_t high_word = High32Bits(mir->dalvikInsn.vB_wide);
289 uint16_t low_res = LookupValue(Instruction::CONST, Low16Bits(low_word),
290 High16Bits(low_word), 1);
291 uint16_t high_res = LookupValue(Instruction::CONST, Low16Bits(high_word),
292 High16Bits(high_word), 2);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000293 res = LookupValue(Instruction::CONST, low_res, high_res, 3);
buzbee2502e002012-12-31 16:05:53 -0800294 SetOperandValueWide(mir->ssa_rep->defs[0], res);
295 }
296 break;
297
298 case Instruction::CONST_WIDE_HIGH16: {
299 uint16_t low_res = LookupValue(Instruction::CONST, 0, 0, 1);
300 uint16_t high_res = LookupValue(Instruction::CONST, 0, Low16Bits(mir->dalvikInsn.vB), 2);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000301 res = LookupValue(Instruction::CONST, low_res, high_res, 3);
buzbee2502e002012-12-31 16:05:53 -0800302 SetOperandValueWide(mir->ssa_rep->defs[0], res);
303 }
304 break;
305
306 case Instruction::ARRAY_LENGTH:
307 case Instruction::NEG_INT:
308 case Instruction::NOT_INT:
309 case Instruction::NEG_FLOAT:
310 case Instruction::INT_TO_BYTE:
311 case Instruction::INT_TO_SHORT:
312 case Instruction::INT_TO_CHAR:
313 case Instruction::INT_TO_FLOAT:
314 case Instruction::FLOAT_TO_INT: {
315 // res = op + 1 operand
316 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000317 res = LookupValue(opcode, operand1, NO_VALUE, NO_VALUE);
buzbee2502e002012-12-31 16:05:53 -0800318 SetOperandValue(mir->ssa_rep->defs[0], res);
319 }
320 break;
321
322 case Instruction::LONG_TO_FLOAT:
323 case Instruction::LONG_TO_INT:
324 case Instruction::DOUBLE_TO_FLOAT:
325 case Instruction::DOUBLE_TO_INT: {
326 // res = op + 1 wide operand
327 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000328 res = LookupValue(opcode, operand1, NO_VALUE, NO_VALUE);
buzbee2502e002012-12-31 16:05:53 -0800329 SetOperandValue(mir->ssa_rep->defs[0], res);
330 }
331 break;
332
333
334 case Instruction::DOUBLE_TO_LONG:
335 case Instruction::LONG_TO_DOUBLE:
336 case Instruction::NEG_LONG:
337 case Instruction::NOT_LONG:
338 case Instruction::NEG_DOUBLE: {
339 // wide res = op + 1 wide operand
340 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000341 res = LookupValue(opcode, operand1, NO_VALUE, NO_VALUE);
buzbee2502e002012-12-31 16:05:53 -0800342 SetOperandValueWide(mir->ssa_rep->defs[0], res);
343 }
344 break;
345
346 case Instruction::FLOAT_TO_DOUBLE:
347 case Instruction::FLOAT_TO_LONG:
348 case Instruction::INT_TO_DOUBLE:
349 case Instruction::INT_TO_LONG: {
350 // wide res = op + 1 operand
351 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000352 res = LookupValue(opcode, operand1, NO_VALUE, NO_VALUE);
buzbee2502e002012-12-31 16:05:53 -0800353 SetOperandValueWide(mir->ssa_rep->defs[0], res);
354 }
355 break;
356
357 case Instruction::CMPL_DOUBLE:
358 case Instruction::CMPG_DOUBLE:
359 case Instruction::CMP_LONG: {
360 // res = op + 2 wide operands
361 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
362 uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000363 res = LookupValue(opcode, operand1, operand2, NO_VALUE);
buzbee2502e002012-12-31 16:05:53 -0800364 SetOperandValue(mir->ssa_rep->defs[0], res);
365 }
366 break;
367
368 case Instruction::CMPG_FLOAT:
369 case Instruction::CMPL_FLOAT:
370 case Instruction::ADD_INT:
371 case Instruction::ADD_INT_2ADDR:
372 case Instruction::MUL_INT:
373 case Instruction::MUL_INT_2ADDR:
374 case Instruction::AND_INT:
375 case Instruction::AND_INT_2ADDR:
376 case Instruction::OR_INT:
377 case Instruction::OR_INT_2ADDR:
378 case Instruction::XOR_INT:
379 case Instruction::XOR_INT_2ADDR:
380 case Instruction::SUB_INT:
381 case Instruction::SUB_INT_2ADDR:
382 case Instruction::DIV_INT:
383 case Instruction::DIV_INT_2ADDR:
384 case Instruction::REM_INT:
385 case Instruction::REM_INT_2ADDR:
386 case Instruction::SHL_INT:
387 case Instruction::SHL_INT_2ADDR:
388 case Instruction::SHR_INT:
389 case Instruction::SHR_INT_2ADDR:
390 case Instruction::USHR_INT:
391 case Instruction::USHR_INT_2ADDR: {
392 // res = op + 2 operands
393 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
394 uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[1]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000395 res = LookupValue(opcode, operand1, operand2, NO_VALUE);
buzbee2502e002012-12-31 16:05:53 -0800396 SetOperandValue(mir->ssa_rep->defs[0], res);
397 }
398 break;
399
400 case Instruction::ADD_LONG:
401 case Instruction::SUB_LONG:
402 case Instruction::MUL_LONG:
403 case Instruction::DIV_LONG:
404 case Instruction::REM_LONG:
405 case Instruction::AND_LONG:
406 case Instruction::OR_LONG:
407 case Instruction::XOR_LONG:
408 case Instruction::ADD_LONG_2ADDR:
409 case Instruction::SUB_LONG_2ADDR:
410 case Instruction::MUL_LONG_2ADDR:
411 case Instruction::DIV_LONG_2ADDR:
412 case Instruction::REM_LONG_2ADDR:
413 case Instruction::AND_LONG_2ADDR:
414 case Instruction::OR_LONG_2ADDR:
415 case Instruction::XOR_LONG_2ADDR:
416 case Instruction::ADD_DOUBLE:
417 case Instruction::SUB_DOUBLE:
418 case Instruction::MUL_DOUBLE:
419 case Instruction::DIV_DOUBLE:
420 case Instruction::REM_DOUBLE:
421 case Instruction::ADD_DOUBLE_2ADDR:
422 case Instruction::SUB_DOUBLE_2ADDR:
423 case Instruction::MUL_DOUBLE_2ADDR:
424 case Instruction::DIV_DOUBLE_2ADDR:
425 case Instruction::REM_DOUBLE_2ADDR: {
426 // wide res = op + 2 wide operands
427 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
428 uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000429 res = LookupValue(opcode, operand1, operand2, NO_VALUE);
buzbee2502e002012-12-31 16:05:53 -0800430 SetOperandValueWide(mir->ssa_rep->defs[0], res);
431 }
432 break;
433
434 case Instruction::SHL_LONG:
435 case Instruction::SHR_LONG:
436 case Instruction::USHR_LONG:
437 case Instruction::SHL_LONG_2ADDR:
438 case Instruction::SHR_LONG_2ADDR:
439 case Instruction::USHR_LONG_2ADDR: {
440 // wide res = op + 1 wide operand + 1 operand
441 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
442 uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000443 res = LookupValue(opcode, operand1, operand2, NO_VALUE);
buzbee2502e002012-12-31 16:05:53 -0800444 SetOperandValueWide(mir->ssa_rep->defs[0], res);
445 }
446 break;
447
448 case Instruction::ADD_FLOAT:
449 case Instruction::SUB_FLOAT:
450 case Instruction::MUL_FLOAT:
451 case Instruction::DIV_FLOAT:
452 case Instruction::REM_FLOAT:
453 case Instruction::ADD_FLOAT_2ADDR:
454 case Instruction::SUB_FLOAT_2ADDR:
455 case Instruction::MUL_FLOAT_2ADDR:
456 case Instruction::DIV_FLOAT_2ADDR:
457 case Instruction::REM_FLOAT_2ADDR: {
458 // res = op + 2 operands
459 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
460 uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[1]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000461 res = LookupValue(opcode, operand1, operand2, NO_VALUE);
buzbee2502e002012-12-31 16:05:53 -0800462 SetOperandValue(mir->ssa_rep->defs[0], res);
463 }
464 break;
465
466 case Instruction::RSUB_INT:
467 case Instruction::ADD_INT_LIT16:
468 case Instruction::MUL_INT_LIT16:
469 case Instruction::DIV_INT_LIT16:
470 case Instruction::REM_INT_LIT16:
471 case Instruction::AND_INT_LIT16:
472 case Instruction::OR_INT_LIT16:
473 case Instruction::XOR_INT_LIT16:
474 case Instruction::ADD_INT_LIT8:
475 case Instruction::RSUB_INT_LIT8:
476 case Instruction::MUL_INT_LIT8:
477 case Instruction::DIV_INT_LIT8:
478 case Instruction::REM_INT_LIT8:
479 case Instruction::AND_INT_LIT8:
480 case Instruction::OR_INT_LIT8:
481 case Instruction::XOR_INT_LIT8:
482 case Instruction::SHL_INT_LIT8:
483 case Instruction::SHR_INT_LIT8:
484 case Instruction::USHR_INT_LIT8: {
nikolay serdjukee40aa42014-03-25 12:21:29 +0700485 // Same as res = op + 2 operands, except use vC as operand 2
buzbee2502e002012-12-31 16:05:53 -0800486 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
nikolay serdjukee40aa42014-03-25 12:21:29 +0700487 uint16_t operand2 = LookupValue(Instruction::CONST, mir->dalvikInsn.vC, 0, 0);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000488 res = LookupValue(opcode, operand1, operand2, NO_VALUE);
buzbee2502e002012-12-31 16:05:53 -0800489 SetOperandValue(mir->ssa_rep->defs[0], res);
490 }
491 break;
492
buzbee2502e002012-12-31 16:05:53 -0800493 case Instruction::AGET_OBJECT:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000494 case Instruction::AGET:
495 case Instruction::AGET_WIDE:
buzbee2502e002012-12-31 16:05:53 -0800496 case Instruction::AGET_BOOLEAN:
497 case Instruction::AGET_BYTE:
498 case Instruction::AGET_CHAR:
499 case Instruction::AGET_SHORT: {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000500 uint16_t type = opcode - Instruction::AGET;
buzbee2502e002012-12-31 16:05:53 -0800501 uint16_t array = GetOperandValue(mir->ssa_rep->uses[0]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000502 HandleNullCheck(mir, array);
buzbee2502e002012-12-31 16:05:53 -0800503 uint16_t index = GetOperandValue(mir->ssa_rep->uses[1]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000504 HandleRangeCheck(mir, array, index);
buzbee2502e002012-12-31 16:05:53 -0800505 // Establish value number for loaded register. Note use of memory version.
Vladimir Markof59f18b2014-02-17 15:53:57 +0000506 uint16_t memory_version = GetMemoryVersion(array, NO_VALUE, type);
buzbee2502e002012-12-31 16:05:53 -0800507 uint16_t res = LookupValue(ARRAY_REF, array, index, memory_version);
508 if (opcode == Instruction::AGET_WIDE) {
509 SetOperandValueWide(mir->ssa_rep->defs[0], res);
510 } else {
511 SetOperandValue(mir->ssa_rep->defs[0], res);
512 }
513 }
514 break;
515
buzbee2502e002012-12-31 16:05:53 -0800516 case Instruction::APUT_OBJECT:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000517 HandlePutObject(mir);
518 // Intentional fall-through.
519 case Instruction::APUT:
520 case Instruction::APUT_WIDE:
buzbee2502e002012-12-31 16:05:53 -0800521 case Instruction::APUT_BYTE:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000522 case Instruction::APUT_BOOLEAN:
523 case Instruction::APUT_SHORT:
524 case Instruction::APUT_CHAR: {
525 uint16_t type = opcode - Instruction::APUT;
buzbee2502e002012-12-31 16:05:53 -0800526 int array_idx = (opcode == Instruction::APUT_WIDE) ? 2 : 1;
527 int index_idx = array_idx + 1;
528 uint16_t array = GetOperandValue(mir->ssa_rep->uses[array_idx]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000529 HandleNullCheck(mir, array);
buzbee2502e002012-12-31 16:05:53 -0800530 uint16_t index = GetOperandValue(mir->ssa_rep->uses[index_idx]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000531 HandleRangeCheck(mir, array, index);
buzbee2502e002012-12-31 16:05:53 -0800532 // Rev the memory version
Vladimir Markof59f18b2014-02-17 15:53:57 +0000533 AdvanceMemoryVersion(array, NO_VALUE, type);
buzbee2502e002012-12-31 16:05:53 -0800534 }
535 break;
536
537 case Instruction::IGET_OBJECT:
buzbee2502e002012-12-31 16:05:53 -0800538 case Instruction::IGET:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000539 case Instruction::IGET_WIDE:
buzbee2502e002012-12-31 16:05:53 -0800540 case Instruction::IGET_BOOLEAN:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000541 case Instruction::IGET_BYTE:
542 case Instruction::IGET_CHAR:
543 case Instruction::IGET_SHORT: {
Vladimir Markobe0e5462014-02-26 11:24:15 +0000544 uint16_t type = opcode - Instruction::IGET;
buzbee2502e002012-12-31 16:05:53 -0800545 uint16_t base = GetOperandValue(mir->ssa_rep->uses[0]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000546 HandleNullCheck(mir, base);
Vladimir Markobe0e5462014-02-26 11:24:15 +0000547 const MirFieldInfo& field_info = cu_->mir_graph->GetIFieldLoweringInfo(mir);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000548 uint16_t memory_version;
549 uint16_t field_id;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000550 if (!field_info.IsResolved() || field_info.IsVolatile()) {
551 // Volatile fields always get a new memory version; field id is irrelevant.
552 // Unresolved fields may be volatile, so handle them as such to be safe.
553 field_id = 0u;
554 memory_version = next_memory_version_;
555 ++next_memory_version_;
556 } else {
557 DCHECK(field_info.IsResolved());
558 field_id = GetFieldId(field_info.DeclaringDexFile(), field_info.DeclaringFieldIndex());
559 memory_version = std::max(unresolved_ifield_version_[type],
560 GetMemoryVersion(base, field_id, type));
561 }
buzbee2502e002012-12-31 16:05:53 -0800562 if (opcode == Instruction::IGET_WIDE) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000563 res = LookupValue(Instruction::IGET_WIDE, base, field_id, memory_version);
buzbee2502e002012-12-31 16:05:53 -0800564 SetOperandValueWide(mir->ssa_rep->defs[0], res);
565 } else {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000566 res = LookupValue(Instruction::IGET, base, field_id, memory_version);
buzbee2502e002012-12-31 16:05:53 -0800567 SetOperandValue(mir->ssa_rep->defs[0], res);
568 }
569 }
570 break;
571
buzbee2502e002012-12-31 16:05:53 -0800572 case Instruction::IPUT_OBJECT:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000573 HandlePutObject(mir);
574 // Intentional fall-through.
buzbee2502e002012-12-31 16:05:53 -0800575 case Instruction::IPUT:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000576 case Instruction::IPUT_WIDE:
buzbee2502e002012-12-31 16:05:53 -0800577 case Instruction::IPUT_BOOLEAN:
578 case Instruction::IPUT_BYTE:
579 case Instruction::IPUT_CHAR:
580 case Instruction::IPUT_SHORT: {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000581 uint16_t type = opcode - Instruction::IPUT;
buzbee2502e002012-12-31 16:05:53 -0800582 int base_reg = (opcode == Instruction::IPUT_WIDE) ? 2 : 1;
583 uint16_t base = GetOperandValue(mir->ssa_rep->uses[base_reg]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000584 HandleNullCheck(mir, base);
Vladimir Markobe0e5462014-02-26 11:24:15 +0000585 const MirFieldInfo& field_info = cu_->mir_graph->GetIFieldLoweringInfo(mir);
586 if (!field_info.IsResolved()) {
587 // Unresolved fields always alias with everything of the same type.
588 unresolved_ifield_version_[type] = next_memory_version_;
589 ++next_memory_version_;
590 } else if (field_info.IsVolatile()) {
591 // Nothing to do, resolved volatile fields always get a new memory version anyway and
592 // can't alias with resolved non-volatile fields.
593 } else {
594 AdvanceMemoryVersion(base, GetFieldId(field_info.DeclaringDexFile(),
595 field_info.DeclaringFieldIndex()), type);
596 }
buzbee2502e002012-12-31 16:05:53 -0800597 }
598 break;
599
600 case Instruction::SGET_OBJECT:
601 case Instruction::SGET:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000602 case Instruction::SGET_WIDE:
buzbee2502e002012-12-31 16:05:53 -0800603 case Instruction::SGET_BOOLEAN:
604 case Instruction::SGET_BYTE:
605 case Instruction::SGET_CHAR:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000606 case Instruction::SGET_SHORT: {
Vladimir Markobe0e5462014-02-26 11:24:15 +0000607 uint16_t type = opcode - Instruction::SGET;
608 const MirFieldInfo& field_info = cu_->mir_graph->GetSFieldLoweringInfo(mir);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000609 uint16_t memory_version;
610 uint16_t field_id;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000611 if (!field_info.IsResolved() || field_info.IsVolatile()) {
612 // Volatile fields always get a new memory version; field id is irrelevant.
613 // Unresolved fields may be volatile, so handle them as such to be safe.
614 field_id = 0u;
615 memory_version = next_memory_version_;
616 ++next_memory_version_;
617 } else {
618 DCHECK(field_info.IsResolved());
619 field_id = GetFieldId(field_info.DeclaringDexFile(), field_info.DeclaringFieldIndex());
620 memory_version = std::max(unresolved_sfield_version_[type],
621 GetMemoryVersion(NO_VALUE, field_id, type));
622 }
buzbee2502e002012-12-31 16:05:53 -0800623 if (opcode == Instruction::SGET_WIDE) {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000624 res = LookupValue(Instruction::SGET_WIDE, NO_VALUE, field_id, memory_version);
buzbee2502e002012-12-31 16:05:53 -0800625 SetOperandValueWide(mir->ssa_rep->defs[0], res);
626 } else {
Vladimir Markof59f18b2014-02-17 15:53:57 +0000627 res = LookupValue(Instruction::SGET, NO_VALUE, field_id, memory_version);
buzbee2502e002012-12-31 16:05:53 -0800628 SetOperandValue(mir->ssa_rep->defs[0], res);
629 }
630 }
631 break;
632
633 case Instruction::SPUT_OBJECT:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000634 HandlePutObject(mir);
635 // Intentional fall-through.
buzbee2502e002012-12-31 16:05:53 -0800636 case Instruction::SPUT:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000637 case Instruction::SPUT_WIDE:
buzbee2502e002012-12-31 16:05:53 -0800638 case Instruction::SPUT_BOOLEAN:
639 case Instruction::SPUT_BYTE:
640 case Instruction::SPUT_CHAR:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000641 case Instruction::SPUT_SHORT: {
642 uint16_t type = opcode - Instruction::SPUT;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000643 const MirFieldInfo& field_info = cu_->mir_graph->GetSFieldLoweringInfo(mir);
644 if (!field_info.IsResolved()) {
645 // Unresolved fields always alias with everything of the same type.
646 unresolved_sfield_version_[type] = next_memory_version_;
647 ++next_memory_version_;
648 } else if (field_info.IsVolatile()) {
649 // Nothing to do, resolved volatile fields always get a new memory version anyway and
650 // can't alias with resolved non-volatile fields.
651 } else {
652 AdvanceMemoryVersion(NO_VALUE, GetFieldId(field_info.DeclaringDexFile(),
653 field_info.DeclaringFieldIndex()), type);
654 }
buzbee2502e002012-12-31 16:05:53 -0800655 }
656 break;
buzbee2502e002012-12-31 16:05:53 -0800657 }
658 return res;
659}
660
661} // namespace art