blob: 348bedcc752b96d0721b43c689f0139116cda00a [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
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_COMPILER_DEX_LOCAL_VALUE_NUMBERING_H_
18#define ART_COMPILER_DEX_LOCAL_VALUE_NUMBERING_H_
buzbee2502e002012-12-31 16:05:53 -080019
20#include "compiler_internals.h"
21
22#define NO_VALUE 0xffff
23#define ARRAY_REF 0xfffe
24
25namespace art {
26
Vladimir Markof59f18b2014-02-17 15:53:57 +000027class DexFile;
buzbee2502e002012-12-31 16:05:53 -080028
buzbee311ca162013-02-28 15:56:43 -080029class LocalValueNumbering {
Vladimir Markof59f18b2014-02-17 15:53:57 +000030 private:
31 // Field types correspond to the ordering of GET/PUT instructions; this order is the same
32 // for IGET, IPUT, SGET, SPUT, AGET and APUT:
33 // op 0
34 // op_WIDE 1
35 // op_OBJECT 2
36 // op_BOOLEAN 3
37 // op_BYTE 4
38 // op_CHAR 5
39 // op_SHORT 6
40 static constexpr size_t kFieldTypeCount = 7;
41
42 // FieldReference represents either a unique resolved field or all unresolved fields together.
43 struct FieldReference {
44 const DexFile* dex_file;
45 uint16_t field_idx;
46 };
47
48 struct FieldReferenceComparator {
49 bool operator()(const FieldReference& lhs, const FieldReference& rhs) const {
50 if (lhs.field_idx != rhs.field_idx) {
51 return lhs.field_idx < rhs.field_idx;
52 }
53 return lhs.dex_file < rhs.dex_file;
54 }
55 };
56
57 struct MemoryVersionKey {
58 uint16_t base;
59 uint16_t field_id;
60 uint16_t type;
61 };
62
63 struct MemoryVersionKeyComparator {
64 bool operator()(const MemoryVersionKey& lhs, const MemoryVersionKey& rhs) const {
65 if (lhs.base != rhs.base) {
66 return lhs.base < rhs.base;
67 }
68 if (lhs.field_id != rhs.field_id) {
69 return lhs.field_id < rhs.field_id;
70 }
71 return lhs.type < rhs.type;
72 }
73 };
74
75 // Key is s_reg, value is value name.
76 typedef SafeMap<uint16_t, uint16_t> SregValueMap;
77 // Key is concatenation of opcode, operand1, operand2 and modifier, value is value name.
78 typedef SafeMap<uint64_t, uint16_t> ValueMap;
79 // Key represents a memory address, value is generation.
80 typedef SafeMap<MemoryVersionKey, uint16_t, MemoryVersionKeyComparator> MemoryVersionMap;
81 // Maps field key to field id for resolved fields.
82 typedef SafeMap<FieldReference, uint32_t, FieldReferenceComparator> FieldIndexMap;
83
buzbee2502e002012-12-31 16:05:53 -080084 public:
Vladimir Markof59f18b2014-02-17 15:53:57 +000085 explicit LocalValueNumbering(CompilationUnit* cu)
86 : cu_(cu),
87 sreg_value_map_(),
88 sreg_wide_value_map_(),
89 value_map_(),
90 next_memory_version_(1u),
91 global_memory_version_(0u),
92 memory_version_map_(),
93 field_index_map_(),
94 non_aliasing_refs_(),
95 null_checked_() {
96 std::fill_n(unresolved_sfield_version_, kFieldTypeCount, 0u);
97 std::fill_n(unresolved_ifield_version_, kFieldTypeCount, 0u);
98 }
buzbee2502e002012-12-31 16:05:53 -080099
Ian Rogers71fe2672013-03-19 20:45:02 -0700100 static uint64_t BuildKey(uint16_t op, uint16_t operand1, uint16_t operand2, uint16_t modifier) {
buzbee2502e002012-12-31 16:05:53 -0800101 return (static_cast<uint64_t>(op) << 48 | static_cast<uint64_t>(operand1) << 32 |
102 static_cast<uint64_t>(operand2) << 16 | static_cast<uint64_t>(modifier));
103 };
104
Ian Rogers71fe2672013-03-19 20:45:02 -0700105 uint16_t LookupValue(uint16_t op, uint16_t operand1, uint16_t operand2, uint16_t modifier) {
buzbee2502e002012-12-31 16:05:53 -0800106 uint16_t res;
107 uint64_t key = BuildKey(op, operand1, operand2, modifier);
108 ValueMap::iterator it = value_map_.find(key);
109 if (it != value_map_.end()) {
110 res = it->second;
111 } else {
112 res = value_map_.size() + 1;
113 value_map_.Put(key, res);
114 }
115 return res;
116 };
117
Ian Rogers71fe2672013-03-19 20:45:02 -0700118 bool ValueExists(uint16_t op, uint16_t operand1, uint16_t operand2, uint16_t modifier) const {
buzbee2502e002012-12-31 16:05:53 -0800119 uint64_t key = BuildKey(op, operand1, operand2, modifier);
Ian Rogers71fe2672013-03-19 20:45:02 -0700120 ValueMap::const_iterator it = value_map_.find(key);
buzbee2502e002012-12-31 16:05:53 -0800121 return (it != value_map_.end());
122 };
123
Ian Rogers71fe2672013-03-19 20:45:02 -0700124 void SetOperandValue(uint16_t s_reg, uint16_t value) {
buzbee2502e002012-12-31 16:05:53 -0800125 SregValueMap::iterator it = sreg_value_map_.find(s_reg);
126 if (it != sreg_value_map_.end()) {
127 DCHECK_EQ(it->second, value);
128 } else {
129 sreg_value_map_.Put(s_reg, value);
130 }
131 };
132
Ian Rogers71fe2672013-03-19 20:45:02 -0700133 uint16_t GetOperandValue(int s_reg) {
buzbee2502e002012-12-31 16:05:53 -0800134 uint16_t res = NO_VALUE;
135 SregValueMap::iterator it = sreg_value_map_.find(s_reg);
136 if (it != sreg_value_map_.end()) {
137 res = it->second;
138 } else {
139 // First use
140 res = LookupValue(NO_VALUE, s_reg, NO_VALUE, NO_VALUE);
141 sreg_value_map_.Put(s_reg, res);
142 }
143 return res;
144 };
145
Ian Rogers71fe2672013-03-19 20:45:02 -0700146 void SetOperandValueWide(uint16_t s_reg, uint16_t value) {
buzbee2502e002012-12-31 16:05:53 -0800147 SregValueMap::iterator it = sreg_wide_value_map_.find(s_reg);
148 if (it != sreg_wide_value_map_.end()) {
149 DCHECK_EQ(it->second, value);
150 } else {
151 sreg_wide_value_map_.Put(s_reg, value);
152 }
153 };
154
Ian Rogers71fe2672013-03-19 20:45:02 -0700155 uint16_t GetOperandValueWide(int s_reg) {
buzbee2502e002012-12-31 16:05:53 -0800156 uint16_t res = NO_VALUE;
157 SregValueMap::iterator it = sreg_wide_value_map_.find(s_reg);
158 if (it != sreg_wide_value_map_.end()) {
159 res = it->second;
160 } else {
161 // First use
162 res = LookupValue(NO_VALUE, s_reg, NO_VALUE, NO_VALUE);
163 sreg_wide_value_map_.Put(s_reg, res);
164 }
165 return res;
166 };
167
168 uint16_t GetValueNumber(MIR* mir);
169
170 private:
Vladimir Markof59f18b2014-02-17 15:53:57 +0000171 uint16_t GetFieldId(const DexFile* dex_file, uint16_t field_idx);
172 void AdvanceGlobalMemory();
173 uint16_t GetMemoryVersion(uint16_t base, uint16_t field, uint16_t type);
174 uint16_t AdvanceMemoryVersion(uint16_t base, uint16_t field, uint16_t type);
175 uint16_t MarkNonAliasingNonNull(MIR* mir);
176 void MakeArgsAliasing(MIR* mir);
177 void HandleNullCheck(MIR* mir, uint16_t reg);
178 void HandleRangeCheck(MIR* mir, uint16_t array, uint16_t index);
179 void HandlePutObject(MIR* mir);
180
Ian Rogers71fe2672013-03-19 20:45:02 -0700181 CompilationUnit* const cu_;
buzbee2502e002012-12-31 16:05:53 -0800182 SregValueMap sreg_value_map_;
183 SregValueMap sreg_wide_value_map_;
184 ValueMap value_map_;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000185 uint16_t next_memory_version_;
186 uint16_t global_memory_version_;
187 uint16_t unresolved_sfield_version_[kFieldTypeCount];
188 uint16_t unresolved_ifield_version_[kFieldTypeCount];
buzbee2502e002012-12-31 16:05:53 -0800189 MemoryVersionMap memory_version_map_;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000190 FieldIndexMap field_index_map_;
191 // Value names of references to objects that cannot be reached through a different value name.
192 std::set<uint16_t> non_aliasing_refs_;
buzbee2502e002012-12-31 16:05:53 -0800193 std::set<uint16_t> null_checked_;
buzbee2502e002012-12-31 16:05:53 -0800194};
195
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700196} // namespace art
buzbee2502e002012-12-31 16:05:53 -0800197
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700198#endif // ART_COMPILER_DEX_LOCAL_VALUE_NUMBERING_H_