OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/constant_propagator.h" | 5 #include "vm/constant_propagator.h" |
6 | 6 |
7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
8 #include "vm/flow_graph_builder.h" | 8 #include "vm/flow_graph_builder.h" |
9 #include "vm/flow_graph_compiler.h" | 9 #include "vm/flow_graph_compiler.h" |
10 #include "vm/flow_graph_range_analysis.h" | 10 #include "vm/flow_graph_range_analysis.h" |
11 #include "vm/il_printer.h" | 11 #include "vm/il_printer.h" |
12 #include "vm/intermediate_language.h" | 12 #include "vm/intermediate_language.h" |
13 #include "vm/parser.h" | 13 #include "vm/parser.h" |
14 #include "vm/symbols.h" | 14 #include "vm/symbols.h" |
15 | 15 |
16 namespace dart { | 16 namespace dart { |
17 | 17 |
18 DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis."); | 18 DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis."); |
19 DEFINE_FLAG(bool, | 19 DEFINE_FLAG(bool, |
20 trace_constant_propagation, | 20 trace_constant_propagation, |
21 false, | 21 false, |
22 "Print constant propagation and useless code elimination."); | 22 "Print constant propagation and useless code elimination."); |
23 | 23 |
24 // Quick access to the current zone and isolate. | 24 // Quick access to the current zone and isolate. |
25 #define I (isolate()) | 25 #define I (isolate()) |
26 #define Z (graph_->zone()) | 26 #define Z (graph_->zone()) |
27 | 27 |
28 | |
29 ConstantPropagator::ConstantPropagator( | 28 ConstantPropagator::ConstantPropagator( |
30 FlowGraph* graph, | 29 FlowGraph* graph, |
31 const GrowableArray<BlockEntryInstr*>& ignored) | 30 const GrowableArray<BlockEntryInstr*>& ignored) |
32 : FlowGraphVisitor(ignored), | 31 : FlowGraphVisitor(ignored), |
33 graph_(graph), | 32 graph_(graph), |
34 unknown_(Object::unknown_constant()), | 33 unknown_(Object::unknown_constant()), |
35 non_constant_(Object::non_constant()), | 34 non_constant_(Object::non_constant()), |
36 reachable_(new (Z) BitVector(Z, graph->preorder().length())), | 35 reachable_(new (Z) BitVector(Z, graph->preorder().length())), |
37 marked_phis_(new (Z) BitVector(Z, graph->max_virtual_register_number())), | 36 marked_phis_(new (Z) BitVector(Z, graph->max_virtual_register_number())), |
38 block_worklist_(), | 37 block_worklist_(), |
39 definition_worklist_(graph, 10) {} | 38 definition_worklist_(graph, 10) {} |
40 | 39 |
41 | |
42 void ConstantPropagator::Optimize(FlowGraph* graph) { | 40 void ConstantPropagator::Optimize(FlowGraph* graph) { |
43 GrowableArray<BlockEntryInstr*> ignored; | 41 GrowableArray<BlockEntryInstr*> ignored; |
44 ConstantPropagator cp(graph, ignored); | 42 ConstantPropagator cp(graph, ignored); |
45 cp.Analyze(); | 43 cp.Analyze(); |
46 cp.Transform(); | 44 cp.Transform(); |
47 } | 45 } |
48 | 46 |
49 | |
50 void ConstantPropagator::OptimizeBranches(FlowGraph* graph) { | 47 void ConstantPropagator::OptimizeBranches(FlowGraph* graph) { |
51 GrowableArray<BlockEntryInstr*> ignored; | 48 GrowableArray<BlockEntryInstr*> ignored; |
52 ConstantPropagator cp(graph, ignored); | 49 ConstantPropagator cp(graph, ignored); |
53 cp.Analyze(); | 50 cp.Analyze(); |
54 cp.Transform(); | 51 cp.Transform(); |
55 cp.EliminateRedundantBranches(); | 52 cp.EliminateRedundantBranches(); |
56 } | 53 } |
57 | 54 |
58 | |
59 void ConstantPropagator::SetReachable(BlockEntryInstr* block) { | 55 void ConstantPropagator::SetReachable(BlockEntryInstr* block) { |
60 if (!reachable_->Contains(block->preorder_number())) { | 56 if (!reachable_->Contains(block->preorder_number())) { |
61 reachable_->Add(block->preorder_number()); | 57 reachable_->Add(block->preorder_number()); |
62 block_worklist_.Add(block); | 58 block_worklist_.Add(block); |
63 } | 59 } |
64 } | 60 } |
65 | 61 |
66 | |
67 bool ConstantPropagator::SetValue(Definition* definition, const Object& value) { | 62 bool ConstantPropagator::SetValue(Definition* definition, const Object& value) { |
68 // We would like to assert we only go up (toward non-constant) in the lattice. | 63 // We would like to assert we only go up (toward non-constant) in the lattice. |
69 // | 64 // |
70 // ASSERT(IsUnknown(definition->constant_value()) || | 65 // ASSERT(IsUnknown(definition->constant_value()) || |
71 // IsNonConstant(value) || | 66 // IsNonConstant(value) || |
72 // (definition->constant_value().raw() == value.raw())); | 67 // (definition->constant_value().raw() == value.raw())); |
73 // | 68 // |
74 // But the final disjunct is not true (e.g., mint or double constants are | 69 // But the final disjunct is not true (e.g., mint or double constants are |
75 // heap-allocated and so not necessarily pointer-equal on each iteration). | 70 // heap-allocated and so not necessarily pointer-equal on each iteration). |
76 if (definition->constant_value().raw() != value.raw()) { | 71 if (definition->constant_value().raw() != value.raw()) { |
77 definition->constant_value() = value.raw(); | 72 definition->constant_value() = value.raw(); |
78 if (definition->input_use_list() != NULL) { | 73 if (definition->input_use_list() != NULL) { |
79 definition_worklist_.Add(definition); | 74 definition_worklist_.Add(definition); |
80 } | 75 } |
81 return true; | 76 return true; |
82 } | 77 } |
83 return false; | 78 return false; |
84 } | 79 } |
85 | 80 |
86 | |
87 // Compute the join of two values in the lattice, assign it to the first. | 81 // Compute the join of two values in the lattice, assign it to the first. |
88 void ConstantPropagator::Join(Object* left, const Object& right) { | 82 void ConstantPropagator::Join(Object* left, const Object& right) { |
89 // Join(non-constant, X) = non-constant | 83 // Join(non-constant, X) = non-constant |
90 // Join(X, unknown) = X | 84 // Join(X, unknown) = X |
91 if (IsNonConstant(*left) || IsUnknown(right)) return; | 85 if (IsNonConstant(*left) || IsUnknown(right)) return; |
92 | 86 |
93 // Join(unknown, X) = X | 87 // Join(unknown, X) = X |
94 // Join(X, non-constant) = non-constant | 88 // Join(X, non-constant) = non-constant |
95 if (IsUnknown(*left) || IsNonConstant(right)) { | 89 if (IsUnknown(*left) || IsNonConstant(right)) { |
96 *left = right.raw(); | 90 *left = right.raw(); |
97 return; | 91 return; |
98 } | 92 } |
99 | 93 |
100 // Join(X, X) = X | 94 // Join(X, X) = X |
101 // TODO(kmillikin): support equality for doubles, mints, etc. | 95 // TODO(kmillikin): support equality for doubles, mints, etc. |
102 if (left->raw() == right.raw()) return; | 96 if (left->raw() == right.raw()) return; |
103 | 97 |
104 // Join(X, Y) = non-constant | 98 // Join(X, Y) = non-constant |
105 *left = non_constant_.raw(); | 99 *left = non_constant_.raw(); |
106 } | 100 } |
107 | 101 |
108 | |
109 // -------------------------------------------------------------------------- | 102 // -------------------------------------------------------------------------- |
110 // Analysis of blocks. Called at most once per block. The block is already | 103 // Analysis of blocks. Called at most once per block. The block is already |
111 // marked as reachable. All instructions in the block are analyzed. | 104 // marked as reachable. All instructions in the block are analyzed. |
112 void ConstantPropagator::VisitGraphEntry(GraphEntryInstr* block) { | 105 void ConstantPropagator::VisitGraphEntry(GraphEntryInstr* block) { |
113 const GrowableArray<Definition*>& defs = *block->initial_definitions(); | 106 const GrowableArray<Definition*>& defs = *block->initial_definitions(); |
114 for (intptr_t i = 0; i < defs.length(); ++i) { | 107 for (intptr_t i = 0; i < defs.length(); ++i) { |
115 defs[i]->Accept(this); | 108 defs[i]->Accept(this); |
116 } | 109 } |
117 ASSERT(ForwardInstructionIterator(block).Done()); | 110 ASSERT(ForwardInstructionIterator(block).Done()); |
118 | 111 |
119 // TODO(fschneider): Improve this approximation. The catch entry is only | 112 // TODO(fschneider): Improve this approximation. The catch entry is only |
120 // reachable if a call in the try-block is reachable. | 113 // reachable if a call in the try-block is reachable. |
121 for (intptr_t i = 0; i < block->SuccessorCount(); ++i) { | 114 for (intptr_t i = 0; i < block->SuccessorCount(); ++i) { |
122 SetReachable(block->SuccessorAt(i)); | 115 SetReachable(block->SuccessorAt(i)); |
123 } | 116 } |
124 } | 117 } |
125 | 118 |
126 | |
127 void ConstantPropagator::VisitJoinEntry(JoinEntryInstr* block) { | 119 void ConstantPropagator::VisitJoinEntry(JoinEntryInstr* block) { |
128 // Phis are visited when visiting Goto at a predecessor. See VisitGoto. | 120 // Phis are visited when visiting Goto at a predecessor. See VisitGoto. |
129 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 121 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
130 it.Current()->Accept(this); | 122 it.Current()->Accept(this); |
131 } | 123 } |
132 } | 124 } |
133 | 125 |
134 | |
135 void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) { | 126 void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) { |
136 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 127 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
137 it.Current()->Accept(this); | 128 it.Current()->Accept(this); |
138 } | 129 } |
139 } | 130 } |
140 | 131 |
141 | |
142 void ConstantPropagator::VisitIndirectEntry(IndirectEntryInstr* block) { | 132 void ConstantPropagator::VisitIndirectEntry(IndirectEntryInstr* block) { |
143 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 133 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
144 it.Current()->Accept(this); | 134 it.Current()->Accept(this); |
145 } | 135 } |
146 } | 136 } |
147 | 137 |
148 | |
149 void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) { | 138 void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) { |
150 const GrowableArray<Definition*>& defs = *block->initial_definitions(); | 139 const GrowableArray<Definition*>& defs = *block->initial_definitions(); |
151 for (intptr_t i = 0; i < defs.length(); ++i) { | 140 for (intptr_t i = 0; i < defs.length(); ++i) { |
152 defs[i]->Accept(this); | 141 defs[i]->Accept(this); |
153 } | 142 } |
154 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 143 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
155 it.Current()->Accept(this); | 144 it.Current()->Accept(this); |
156 } | 145 } |
157 } | 146 } |
158 | 147 |
159 | |
160 void ConstantPropagator::VisitParallelMove(ParallelMoveInstr* instr) { | 148 void ConstantPropagator::VisitParallelMove(ParallelMoveInstr* instr) { |
161 // Parallel moves have not yet been inserted in the graph. | 149 // Parallel moves have not yet been inserted in the graph. |
162 UNREACHABLE(); | 150 UNREACHABLE(); |
163 } | 151 } |
164 | 152 |
165 | |
166 // -------------------------------------------------------------------------- | 153 // -------------------------------------------------------------------------- |
167 // Analysis of control instructions. Unconditional successors are | 154 // Analysis of control instructions. Unconditional successors are |
168 // reachable. Conditional successors are reachable depending on the | 155 // reachable. Conditional successors are reachable depending on the |
169 // constant value of the condition. | 156 // constant value of the condition. |
170 void ConstantPropagator::VisitReturn(ReturnInstr* instr) { | 157 void ConstantPropagator::VisitReturn(ReturnInstr* instr) { |
171 // Nothing to do. | 158 // Nothing to do. |
172 } | 159 } |
173 | 160 |
174 | |
175 void ConstantPropagator::VisitThrow(ThrowInstr* instr) { | 161 void ConstantPropagator::VisitThrow(ThrowInstr* instr) { |
176 // Nothing to do. | 162 // Nothing to do. |
177 } | 163 } |
178 | 164 |
179 | |
180 void ConstantPropagator::VisitReThrow(ReThrowInstr* instr) { | 165 void ConstantPropagator::VisitReThrow(ReThrowInstr* instr) { |
181 // Nothing to do. | 166 // Nothing to do. |
182 } | 167 } |
183 | 168 |
184 | |
185 void ConstantPropagator::VisitStop(StopInstr* instr) { | 169 void ConstantPropagator::VisitStop(StopInstr* instr) { |
186 // Nothing to do. | 170 // Nothing to do. |
187 } | 171 } |
188 | 172 |
189 | |
190 void ConstantPropagator::VisitGoto(GotoInstr* instr) { | 173 void ConstantPropagator::VisitGoto(GotoInstr* instr) { |
191 SetReachable(instr->successor()); | 174 SetReachable(instr->successor()); |
192 | 175 |
193 // Phi value depends on the reachability of a predecessor. We have | 176 // Phi value depends on the reachability of a predecessor. We have |
194 // to revisit phis every time a predecessor becomes reachable. | 177 // to revisit phis every time a predecessor becomes reachable. |
195 for (PhiIterator it(instr->successor()); !it.Done(); it.Advance()) { | 178 for (PhiIterator it(instr->successor()); !it.Done(); it.Advance()) { |
196 it.Current()->Accept(this); | 179 it.Current()->Accept(this); |
197 } | 180 } |
198 } | 181 } |
199 | 182 |
200 | |
201 void ConstantPropagator::VisitIndirectGoto(IndirectGotoInstr* instr) { | 183 void ConstantPropagator::VisitIndirectGoto(IndirectGotoInstr* instr) { |
202 for (intptr_t i = 0; i < instr->SuccessorCount(); i++) { | 184 for (intptr_t i = 0; i < instr->SuccessorCount(); i++) { |
203 SetReachable(instr->SuccessorAt(i)); | 185 SetReachable(instr->SuccessorAt(i)); |
204 } | 186 } |
205 } | 187 } |
206 | 188 |
207 | |
208 void ConstantPropagator::VisitBranch(BranchInstr* instr) { | 189 void ConstantPropagator::VisitBranch(BranchInstr* instr) { |
209 instr->comparison()->Accept(this); | 190 instr->comparison()->Accept(this); |
210 | 191 |
211 // The successors may be reachable, but only if this instruction is. (We | 192 // The successors may be reachable, but only if this instruction is. (We |
212 // might be analyzing it because the constant value of one of its inputs | 193 // might be analyzing it because the constant value of one of its inputs |
213 // has changed.) | 194 // has changed.) |
214 if (reachable_->Contains(instr->GetBlock()->preorder_number())) { | 195 if (reachable_->Contains(instr->GetBlock()->preorder_number())) { |
215 if (instr->constant_target() != NULL) { | 196 if (instr->constant_target() != NULL) { |
216 ASSERT((instr->constant_target() == instr->true_successor()) || | 197 ASSERT((instr->constant_target() == instr->true_successor()) || |
217 (instr->constant_target() == instr->false_successor())); | 198 (instr->constant_target() == instr->false_successor())); |
218 SetReachable(instr->constant_target()); | 199 SetReachable(instr->constant_target()); |
219 } else { | 200 } else { |
220 const Object& value = instr->comparison()->constant_value(); | 201 const Object& value = instr->comparison()->constant_value(); |
221 if (IsNonConstant(value)) { | 202 if (IsNonConstant(value)) { |
222 SetReachable(instr->true_successor()); | 203 SetReachable(instr->true_successor()); |
223 SetReachable(instr->false_successor()); | 204 SetReachable(instr->false_successor()); |
224 } else if (value.raw() == Bool::True().raw()) { | 205 } else if (value.raw() == Bool::True().raw()) { |
225 SetReachable(instr->true_successor()); | 206 SetReachable(instr->true_successor()); |
226 } else if (!IsUnknown(value)) { // Any other constant. | 207 } else if (!IsUnknown(value)) { // Any other constant. |
227 SetReachable(instr->false_successor()); | 208 SetReachable(instr->false_successor()); |
228 } | 209 } |
229 } | 210 } |
230 } | 211 } |
231 } | 212 } |
232 | 213 |
233 | |
234 // -------------------------------------------------------------------------- | 214 // -------------------------------------------------------------------------- |
235 // Analysis of non-definition instructions. They do not have values so they | 215 // Analysis of non-definition instructions. They do not have values so they |
236 // cannot have constant values. | 216 // cannot have constant values. |
237 void ConstantPropagator::VisitCheckStackOverflow( | 217 void ConstantPropagator::VisitCheckStackOverflow( |
238 CheckStackOverflowInstr* instr) {} | 218 CheckStackOverflowInstr* instr) {} |
239 | 219 |
240 | |
241 void ConstantPropagator::VisitCheckClass(CheckClassInstr* instr) {} | 220 void ConstantPropagator::VisitCheckClass(CheckClassInstr* instr) {} |
242 | 221 |
243 | |
244 void ConstantPropagator::VisitCheckClassId(CheckClassIdInstr* instr) {} | 222 void ConstantPropagator::VisitCheckClassId(CheckClassIdInstr* instr) {} |
245 | 223 |
246 | |
247 void ConstantPropagator::VisitGuardFieldClass(GuardFieldClassInstr* instr) {} | 224 void ConstantPropagator::VisitGuardFieldClass(GuardFieldClassInstr* instr) {} |
248 | 225 |
249 | |
250 void ConstantPropagator::VisitGuardFieldLength(GuardFieldLengthInstr* instr) {} | 226 void ConstantPropagator::VisitGuardFieldLength(GuardFieldLengthInstr* instr) {} |
251 | 227 |
252 | |
253 void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) {} | 228 void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) {} |
254 | 229 |
255 | |
256 void ConstantPropagator::VisitGenericCheckBound(GenericCheckBoundInstr* instr) { | 230 void ConstantPropagator::VisitGenericCheckBound(GenericCheckBoundInstr* instr) { |
257 } | 231 } |
258 | 232 |
259 | |
260 void ConstantPropagator::VisitCheckEitherNonSmi(CheckEitherNonSmiInstr* instr) { | 233 void ConstantPropagator::VisitCheckEitherNonSmi(CheckEitherNonSmiInstr* instr) { |
261 } | 234 } |
262 | 235 |
263 | |
264 void ConstantPropagator::VisitCheckArrayBound(CheckArrayBoundInstr* instr) {} | 236 void ConstantPropagator::VisitCheckArrayBound(CheckArrayBoundInstr* instr) {} |
265 | 237 |
266 | |
267 void ConstantPropagator::VisitDeoptimize(DeoptimizeInstr* instr) { | 238 void ConstantPropagator::VisitDeoptimize(DeoptimizeInstr* instr) { |
268 // TODO(vegorov) remove all code after DeoptimizeInstr as dead. | 239 // TODO(vegorov) remove all code after DeoptimizeInstr as dead. |
269 } | 240 } |
270 | 241 |
271 | |
272 Definition* ConstantPropagator::UnwrapPhi(Definition* defn) { | 242 Definition* ConstantPropagator::UnwrapPhi(Definition* defn) { |
273 if (defn->IsPhi()) { | 243 if (defn->IsPhi()) { |
274 JoinEntryInstr* block = defn->AsPhi()->block(); | 244 JoinEntryInstr* block = defn->AsPhi()->block(); |
275 | 245 |
276 Definition* input = NULL; | 246 Definition* input = NULL; |
277 for (intptr_t i = 0; i < defn->InputCount(); ++i) { | 247 for (intptr_t i = 0; i < defn->InputCount(); ++i) { |
278 if (reachable_->Contains(block->PredecessorAt(i)->preorder_number())) { | 248 if (reachable_->Contains(block->PredecessorAt(i)->preorder_number())) { |
279 if (input == NULL) { | 249 if (input == NULL) { |
280 input = defn->InputAt(i)->definition(); | 250 input = defn->InputAt(i)->definition(); |
281 } else { | 251 } else { |
282 return defn; | 252 return defn; |
283 } | 253 } |
284 } | 254 } |
285 } | 255 } |
286 | 256 |
287 return input; | 257 return input; |
288 } | 258 } |
289 | 259 |
290 return defn; | 260 return defn; |
291 } | 261 } |
292 | 262 |
293 | |
294 void ConstantPropagator::MarkPhi(Definition* phi) { | 263 void ConstantPropagator::MarkPhi(Definition* phi) { |
295 ASSERT(phi->IsPhi()); | 264 ASSERT(phi->IsPhi()); |
296 marked_phis_->Add(phi->ssa_temp_index()); | 265 marked_phis_->Add(phi->ssa_temp_index()); |
297 } | 266 } |
298 | 267 |
299 | |
300 // -------------------------------------------------------------------------- | 268 // -------------------------------------------------------------------------- |
301 // Analysis of definitions. Compute the constant value. If it has changed | 269 // Analysis of definitions. Compute the constant value. If it has changed |
302 // and the definition has input uses, add the definition to the definition | 270 // and the definition has input uses, add the definition to the definition |
303 // worklist so that the used can be processed. | 271 // worklist so that the used can be processed. |
304 void ConstantPropagator::VisitPhi(PhiInstr* instr) { | 272 void ConstantPropagator::VisitPhi(PhiInstr* instr) { |
305 // Compute the join over all the reachable predecessor values. | 273 // Compute the join over all the reachable predecessor values. |
306 JoinEntryInstr* block = instr->block(); | 274 JoinEntryInstr* block = instr->block(); |
307 Object& value = Object::ZoneHandle(Z, Unknown()); | 275 Object& value = Object::ZoneHandle(Z, Unknown()); |
308 for (intptr_t pred_idx = 0; pred_idx < instr->InputCount(); ++pred_idx) { | 276 for (intptr_t pred_idx = 0; pred_idx < instr->InputCount(); ++pred_idx) { |
309 if (reachable_->Contains( | 277 if (reachable_->Contains( |
310 block->PredecessorAt(pred_idx)->preorder_number())) { | 278 block->PredecessorAt(pred_idx)->preorder_number())) { |
311 Join(&value, instr->InputAt(pred_idx)->definition()->constant_value()); | 279 Join(&value, instr->InputAt(pred_idx)->definition()->constant_value()); |
312 } | 280 } |
313 } | 281 } |
314 if (!SetValue(instr, value) && | 282 if (!SetValue(instr, value) && |
315 marked_phis_->Contains(instr->ssa_temp_index())) { | 283 marked_phis_->Contains(instr->ssa_temp_index())) { |
316 marked_phis_->Remove(instr->ssa_temp_index()); | 284 marked_phis_->Remove(instr->ssa_temp_index()); |
317 definition_worklist_.Add(instr); | 285 definition_worklist_.Add(instr); |
318 } | 286 } |
319 } | 287 } |
320 | 288 |
321 | |
322 void ConstantPropagator::VisitRedefinition(RedefinitionInstr* instr) { | 289 void ConstantPropagator::VisitRedefinition(RedefinitionInstr* instr) { |
323 // Ensure that we never remove redefinition of a constant unless we are also | 290 // Ensure that we never remove redefinition of a constant unless we are also |
324 // are guaranteed to fold away code paths that correspond to non-matching | 291 // are guaranteed to fold away code paths that correspond to non-matching |
325 // class ids. Otherwise LICM might potentially hoist incorrect code. | 292 // class ids. Otherwise LICM might potentially hoist incorrect code. |
326 const Object& value = instr->value()->definition()->constant_value(); | 293 const Object& value = instr->value()->definition()->constant_value(); |
327 if (IsConstant(value) && !Field::IsExternalizableCid(value.GetClassId())) { | 294 if (IsConstant(value) && !Field::IsExternalizableCid(value.GetClassId())) { |
328 SetValue(instr, value); | 295 SetValue(instr, value); |
329 } else { | 296 } else { |
330 SetValue(instr, non_constant_); | 297 SetValue(instr, non_constant_); |
331 } | 298 } |
332 } | 299 } |
333 | 300 |
334 | |
335 void ConstantPropagator::VisitParameter(ParameterInstr* instr) { | 301 void ConstantPropagator::VisitParameter(ParameterInstr* instr) { |
336 SetValue(instr, non_constant_); | 302 SetValue(instr, non_constant_); |
337 } | 303 } |
338 | 304 |
339 | |
340 void ConstantPropagator::VisitPushArgument(PushArgumentInstr* instr) { | 305 void ConstantPropagator::VisitPushArgument(PushArgumentInstr* instr) { |
341 SetValue(instr, instr->value()->definition()->constant_value()); | 306 SetValue(instr, instr->value()->definition()->constant_value()); |
342 } | 307 } |
343 | 308 |
344 | |
345 void ConstantPropagator::VisitAssertAssignable(AssertAssignableInstr* instr) { | 309 void ConstantPropagator::VisitAssertAssignable(AssertAssignableInstr* instr) { |
346 const Object& value = instr->value()->definition()->constant_value(); | 310 const Object& value = instr->value()->definition()->constant_value(); |
347 if (IsNonConstant(value)) { | 311 if (IsNonConstant(value)) { |
348 SetValue(instr, non_constant_); | 312 SetValue(instr, non_constant_); |
349 } else if (IsConstant(value)) { | 313 } else if (IsConstant(value)) { |
350 // We are ignoring the instantiator and instantiator_type_arguments, but | 314 // We are ignoring the instantiator and instantiator_type_arguments, but |
351 // still monotonic and safe. | 315 // still monotonic and safe. |
352 if (instr->value()->Type()->IsAssignableTo(instr->dst_type())) { | 316 if (instr->value()->Type()->IsAssignableTo(instr->dst_type())) { |
353 SetValue(instr, value); | 317 SetValue(instr, value); |
354 } else { | 318 } else { |
355 SetValue(instr, non_constant_); | 319 SetValue(instr, non_constant_); |
356 } | 320 } |
357 } | 321 } |
358 } | 322 } |
359 | 323 |
360 | |
361 void ConstantPropagator::VisitAssertBoolean(AssertBooleanInstr* instr) { | 324 void ConstantPropagator::VisitAssertBoolean(AssertBooleanInstr* instr) { |
362 const Object& value = instr->value()->definition()->constant_value(); | 325 const Object& value = instr->value()->definition()->constant_value(); |
363 if (IsNonConstant(value)) { | 326 if (IsNonConstant(value)) { |
364 SetValue(instr, non_constant_); | 327 SetValue(instr, non_constant_); |
365 } else if (IsConstant(value)) { | 328 } else if (IsConstant(value)) { |
366 if (value.IsBool()) { | 329 if (value.IsBool()) { |
367 SetValue(instr, value); | 330 SetValue(instr, value); |
368 } else { | 331 } else { |
369 SetValue(instr, non_constant_); | 332 SetValue(instr, non_constant_); |
370 } | 333 } |
371 } | 334 } |
372 } | 335 } |
373 | 336 |
374 | |
375 void ConstantPropagator::VisitSpecialParameter(SpecialParameterInstr* instr) { | 337 void ConstantPropagator::VisitSpecialParameter(SpecialParameterInstr* instr) { |
376 SetValue(instr, non_constant_); | 338 SetValue(instr, non_constant_); |
377 } | 339 } |
378 | 340 |
379 | |
380 void ConstantPropagator::VisitClosureCall(ClosureCallInstr* instr) { | 341 void ConstantPropagator::VisitClosureCall(ClosureCallInstr* instr) { |
381 SetValue(instr, non_constant_); | 342 SetValue(instr, non_constant_); |
382 } | 343 } |
383 | 344 |
384 | |
385 void ConstantPropagator::VisitInstanceCall(InstanceCallInstr* instr) { | 345 void ConstantPropagator::VisitInstanceCall(InstanceCallInstr* instr) { |
386 SetValue(instr, non_constant_); | 346 SetValue(instr, non_constant_); |
387 } | 347 } |
388 | 348 |
389 | |
390 void ConstantPropagator::VisitPolymorphicInstanceCall( | 349 void ConstantPropagator::VisitPolymorphicInstanceCall( |
391 PolymorphicInstanceCallInstr* instr) { | 350 PolymorphicInstanceCallInstr* instr) { |
392 SetValue(instr, non_constant_); | 351 SetValue(instr, non_constant_); |
393 } | 352 } |
394 | 353 |
395 | |
396 void ConstantPropagator::VisitStaticCall(StaticCallInstr* instr) { | 354 void ConstantPropagator::VisitStaticCall(StaticCallInstr* instr) { |
397 SetValue(instr, non_constant_); | 355 SetValue(instr, non_constant_); |
398 } | 356 } |
399 | 357 |
400 | |
401 void ConstantPropagator::VisitLoadLocal(LoadLocalInstr* instr) { | 358 void ConstantPropagator::VisitLoadLocal(LoadLocalInstr* instr) { |
402 // Instruction is eliminated when translating to SSA. | 359 // Instruction is eliminated when translating to SSA. |
403 UNREACHABLE(); | 360 UNREACHABLE(); |
404 } | 361 } |
405 | 362 |
406 | |
407 void ConstantPropagator::VisitDropTemps(DropTempsInstr* instr) { | 363 void ConstantPropagator::VisitDropTemps(DropTempsInstr* instr) { |
408 // Instruction is eliminated when translating to SSA. | 364 // Instruction is eliminated when translating to SSA. |
409 UNREACHABLE(); | 365 UNREACHABLE(); |
410 } | 366 } |
411 | 367 |
412 | |
413 void ConstantPropagator::VisitStoreLocal(StoreLocalInstr* instr) { | 368 void ConstantPropagator::VisitStoreLocal(StoreLocalInstr* instr) { |
414 // Instruction is eliminated when translating to SSA. | 369 // Instruction is eliminated when translating to SSA. |
415 UNREACHABLE(); | 370 UNREACHABLE(); |
416 } | 371 } |
417 | 372 |
418 | |
419 void ConstantPropagator::VisitIfThenElse(IfThenElseInstr* instr) { | 373 void ConstantPropagator::VisitIfThenElse(IfThenElseInstr* instr) { |
420 instr->comparison()->Accept(this); | 374 instr->comparison()->Accept(this); |
421 const Object& value = instr->comparison()->constant_value(); | 375 const Object& value = instr->comparison()->constant_value(); |
422 if (IsNonConstant(value)) { | 376 if (IsNonConstant(value)) { |
423 SetValue(instr, non_constant_); | 377 SetValue(instr, non_constant_); |
424 } else if (IsConstant(value)) { | 378 } else if (IsConstant(value)) { |
425 ASSERT(!value.IsNull()); | 379 ASSERT(!value.IsNull()); |
426 ASSERT(value.IsBool()); | 380 ASSERT(value.IsBool()); |
427 bool result = Bool::Cast(value).value(); | 381 bool result = Bool::Cast(value).value(); |
428 SetValue(instr, Smi::Handle(Z, Smi::New(result ? instr->if_true() | 382 SetValue(instr, Smi::Handle(Z, Smi::New(result ? instr->if_true() |
429 : instr->if_false()))); | 383 : instr->if_false()))); |
430 } | 384 } |
431 } | 385 } |
432 | 386 |
433 | |
434 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { | 387 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { |
435 Definition* left_defn = instr->left()->definition(); | 388 Definition* left_defn = instr->left()->definition(); |
436 Definition* right_defn = instr->right()->definition(); | 389 Definition* right_defn = instr->right()->definition(); |
437 | 390 |
438 Definition* unwrapped_left_defn = UnwrapPhi(left_defn); | 391 Definition* unwrapped_left_defn = UnwrapPhi(left_defn); |
439 Definition* unwrapped_right_defn = UnwrapPhi(right_defn); | 392 Definition* unwrapped_right_defn = UnwrapPhi(right_defn); |
440 if (unwrapped_left_defn == unwrapped_right_defn) { | 393 if (unwrapped_left_defn == unwrapped_right_defn) { |
441 // Fold x === x, and x !== x to true/false. | 394 // Fold x === x, and x !== x to true/false. |
442 SetValue(instr, Bool::Get(instr->kind() == Token::kEQ_STRICT)); | 395 SetValue(instr, Bool::Get(instr->kind() == Token::kEQ_STRICT)); |
443 if (unwrapped_left_defn != left_defn) { | 396 if (unwrapped_left_defn != left_defn) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
476 } | 429 } |
477 } else if (IsConstant(left) && IsConstant(right)) { | 430 } else if (IsConstant(left) && IsConstant(right)) { |
478 bool result = (left.raw() == right.raw()); | 431 bool result = (left.raw() == right.raw()); |
479 if (instr->kind() == Token::kNE_STRICT) { | 432 if (instr->kind() == Token::kNE_STRICT) { |
480 result = !result; | 433 result = !result; |
481 } | 434 } |
482 SetValue(instr, Bool::Get(result)); | 435 SetValue(instr, Bool::Get(result)); |
483 } | 436 } |
484 } | 437 } |
485 | 438 |
486 | |
487 static bool CompareIntegers(Token::Kind kind, | 439 static bool CompareIntegers(Token::Kind kind, |
488 const Integer& left, | 440 const Integer& left, |
489 const Integer& right) { | 441 const Integer& right) { |
490 const int result = left.CompareWith(right); | 442 const int result = left.CompareWith(right); |
491 switch (kind) { | 443 switch (kind) { |
492 case Token::kEQ: | 444 case Token::kEQ: |
493 return (result == 0); | 445 return (result == 0); |
494 case Token::kNE: | 446 case Token::kNE: |
495 return (result != 0); | 447 return (result != 0); |
496 case Token::kLT: | 448 case Token::kLT: |
497 return (result < 0); | 449 return (result < 0); |
498 case Token::kGT: | 450 case Token::kGT: |
499 return (result > 0); | 451 return (result > 0); |
500 case Token::kLTE: | 452 case Token::kLTE: |
501 return (result <= 0); | 453 return (result <= 0); |
502 case Token::kGTE: | 454 case Token::kGTE: |
503 return (result >= 0); | 455 return (result >= 0); |
504 default: | 456 default: |
505 UNREACHABLE(); | 457 UNREACHABLE(); |
506 return false; | 458 return false; |
507 } | 459 } |
508 } | 460 } |
509 | 461 |
510 | |
511 // Comparison instruction that is equivalent to the (left & right) == 0 | 462 // Comparison instruction that is equivalent to the (left & right) == 0 |
512 // comparison pattern. | 463 // comparison pattern. |
513 void ConstantPropagator::VisitTestSmi(TestSmiInstr* instr) { | 464 void ConstantPropagator::VisitTestSmi(TestSmiInstr* instr) { |
514 const Object& left = instr->left()->definition()->constant_value(); | 465 const Object& left = instr->left()->definition()->constant_value(); |
515 const Object& right = instr->right()->definition()->constant_value(); | 466 const Object& right = instr->right()->definition()->constant_value(); |
516 if (IsNonConstant(left) || IsNonConstant(right)) { | 467 if (IsNonConstant(left) || IsNonConstant(right)) { |
517 SetValue(instr, non_constant_); | 468 SetValue(instr, non_constant_); |
518 } else if (IsConstant(left) && IsConstant(right)) { | 469 } else if (IsConstant(left) && IsConstant(right)) { |
519 // BitOp does not work on Bigints. | 470 // BitOp does not work on Bigints. |
520 if (left.IsInteger() && right.IsInteger() && !left.IsBigint() && | 471 if (left.IsInteger() && right.IsInteger() && !left.IsBigint() && |
521 !right.IsBigint()) { | 472 !right.IsBigint()) { |
522 const bool result = CompareIntegers( | 473 const bool result = CompareIntegers( |
523 instr->kind(), | 474 instr->kind(), |
524 Integer::Handle(Z, Integer::Cast(left).BitOp(Token::kBIT_AND, | 475 Integer::Handle(Z, Integer::Cast(left).BitOp(Token::kBIT_AND, |
525 Integer::Cast(right))), | 476 Integer::Cast(right))), |
526 Smi::Handle(Z, Smi::New(0))); | 477 Smi::Handle(Z, Smi::New(0))); |
527 SetValue(instr, result ? Bool::True() : Bool::False()); | 478 SetValue(instr, result ? Bool::True() : Bool::False()); |
528 } else { | 479 } else { |
529 SetValue(instr, non_constant_); | 480 SetValue(instr, non_constant_); |
530 } | 481 } |
531 } | 482 } |
532 } | 483 } |
533 | 484 |
534 | |
535 void ConstantPropagator::VisitTestCids(TestCidsInstr* instr) { | 485 void ConstantPropagator::VisitTestCids(TestCidsInstr* instr) { |
536 // TODO(sra): Constant fold test. | 486 // TODO(sra): Constant fold test. |
537 SetValue(instr, non_constant_); | 487 SetValue(instr, non_constant_); |
538 } | 488 } |
539 | 489 |
540 | |
541 void ConstantPropagator::VisitEqualityCompare(EqualityCompareInstr* instr) { | 490 void ConstantPropagator::VisitEqualityCompare(EqualityCompareInstr* instr) { |
542 Definition* left_defn = instr->left()->definition(); | 491 Definition* left_defn = instr->left()->definition(); |
543 Definition* right_defn = instr->right()->definition(); | 492 Definition* right_defn = instr->right()->definition(); |
544 | 493 |
545 if (RawObject::IsIntegerClassId(instr->operation_cid())) { | 494 if (RawObject::IsIntegerClassId(instr->operation_cid())) { |
546 // Fold x == x, and x != x to true/false for numbers comparisons. | 495 // Fold x == x, and x != x to true/false for numbers comparisons. |
547 Definition* unwrapped_left_defn = UnwrapPhi(left_defn); | 496 Definition* unwrapped_left_defn = UnwrapPhi(left_defn); |
548 Definition* unwrapped_right_defn = UnwrapPhi(right_defn); | 497 Definition* unwrapped_right_defn = UnwrapPhi(right_defn); |
549 if (unwrapped_left_defn == unwrapped_right_defn) { | 498 if (unwrapped_left_defn == unwrapped_right_defn) { |
550 // Fold x === x, and x !== x to true/false. | 499 // Fold x === x, and x !== x to true/false. |
(...skipping 19 matching lines...) Expand all Loading... |
570 SetValue(instr, Bool::Get(result)); | 519 SetValue(instr, Bool::Get(result)); |
571 } else if (left.IsString() && right.IsString()) { | 520 } else if (left.IsString() && right.IsString()) { |
572 const bool result = String::Cast(left).Equals(String::Cast(right)); | 521 const bool result = String::Cast(left).Equals(String::Cast(right)); |
573 SetValue(instr, Bool::Get((instr->kind() == Token::kEQ) == result)); | 522 SetValue(instr, Bool::Get((instr->kind() == Token::kEQ) == result)); |
574 } else { | 523 } else { |
575 SetValue(instr, non_constant_); | 524 SetValue(instr, non_constant_); |
576 } | 525 } |
577 } | 526 } |
578 } | 527 } |
579 | 528 |
580 | |
581 void ConstantPropagator::VisitRelationalOp(RelationalOpInstr* instr) { | 529 void ConstantPropagator::VisitRelationalOp(RelationalOpInstr* instr) { |
582 const Object& left = instr->left()->definition()->constant_value(); | 530 const Object& left = instr->left()->definition()->constant_value(); |
583 const Object& right = instr->right()->definition()->constant_value(); | 531 const Object& right = instr->right()->definition()->constant_value(); |
584 if (IsNonConstant(left) || IsNonConstant(right)) { | 532 if (IsNonConstant(left) || IsNonConstant(right)) { |
585 SetValue(instr, non_constant_); | 533 SetValue(instr, non_constant_); |
586 } else if (IsConstant(left) && IsConstant(right)) { | 534 } else if (IsConstant(left) && IsConstant(right)) { |
587 if (left.IsInteger() && right.IsInteger()) { | 535 if (left.IsInteger() && right.IsInteger()) { |
588 const bool result = CompareIntegers(instr->kind(), Integer::Cast(left), | 536 const bool result = CompareIntegers(instr->kind(), Integer::Cast(left), |
589 Integer::Cast(right)); | 537 Integer::Cast(right)); |
590 SetValue(instr, Bool::Get(result)); | 538 SetValue(instr, Bool::Get(result)); |
591 } else if (left.IsDouble() && right.IsDouble()) { | 539 } else if (left.IsDouble() && right.IsDouble()) { |
592 // TODO(srdjan): Implement. | 540 // TODO(srdjan): Implement. |
593 SetValue(instr, non_constant_); | 541 SetValue(instr, non_constant_); |
594 } else { | 542 } else { |
595 SetValue(instr, non_constant_); | 543 SetValue(instr, non_constant_); |
596 } | 544 } |
597 } | 545 } |
598 } | 546 } |
599 | 547 |
600 | |
601 void ConstantPropagator::VisitNativeCall(NativeCallInstr* instr) { | 548 void ConstantPropagator::VisitNativeCall(NativeCallInstr* instr) { |
602 SetValue(instr, non_constant_); | 549 SetValue(instr, non_constant_); |
603 } | 550 } |
604 | 551 |
605 | |
606 void ConstantPropagator::VisitDebugStepCheck(DebugStepCheckInstr* instr) { | 552 void ConstantPropagator::VisitDebugStepCheck(DebugStepCheckInstr* instr) { |
607 // Nothing to do. | 553 // Nothing to do. |
608 } | 554 } |
609 | 555 |
610 | |
611 void ConstantPropagator::VisitOneByteStringFromCharCode( | 556 void ConstantPropagator::VisitOneByteStringFromCharCode( |
612 OneByteStringFromCharCodeInstr* instr) { | 557 OneByteStringFromCharCodeInstr* instr) { |
613 const Object& o = instr->char_code()->definition()->constant_value(); | 558 const Object& o = instr->char_code()->definition()->constant_value(); |
614 if (o.IsNull() || IsNonConstant(o)) { | 559 if (o.IsNull() || IsNonConstant(o)) { |
615 SetValue(instr, non_constant_); | 560 SetValue(instr, non_constant_); |
616 } else if (IsConstant(o)) { | 561 } else if (IsConstant(o)) { |
617 const intptr_t ch_code = Smi::Cast(o).Value(); | 562 const intptr_t ch_code = Smi::Cast(o).Value(); |
618 ASSERT(ch_code >= 0); | 563 ASSERT(ch_code >= 0); |
619 if (ch_code < Symbols::kMaxOneCharCodeSymbol) { | 564 if (ch_code < Symbols::kMaxOneCharCodeSymbol) { |
620 RawString** table = Symbols::PredefinedAddress(); | 565 RawString** table = Symbols::PredefinedAddress(); |
621 SetValue(instr, String::ZoneHandle(Z, table[ch_code])); | 566 SetValue(instr, String::ZoneHandle(Z, table[ch_code])); |
622 } else { | 567 } else { |
623 SetValue(instr, non_constant_); | 568 SetValue(instr, non_constant_); |
624 } | 569 } |
625 } | 570 } |
626 } | 571 } |
627 | 572 |
628 | |
629 void ConstantPropagator::VisitStringToCharCode(StringToCharCodeInstr* instr) { | 573 void ConstantPropagator::VisitStringToCharCode(StringToCharCodeInstr* instr) { |
630 const Object& o = instr->str()->definition()->constant_value(); | 574 const Object& o = instr->str()->definition()->constant_value(); |
631 if (o.IsNull() || IsNonConstant(o)) { | 575 if (o.IsNull() || IsNonConstant(o)) { |
632 SetValue(instr, non_constant_); | 576 SetValue(instr, non_constant_); |
633 } else if (IsConstant(o)) { | 577 } else if (IsConstant(o)) { |
634 const String& str = String::Cast(o); | 578 const String& str = String::Cast(o); |
635 const intptr_t result = | 579 const intptr_t result = |
636 (str.Length() == 1) ? static_cast<intptr_t>(str.CharAt(0)) : -1; | 580 (str.Length() == 1) ? static_cast<intptr_t>(str.CharAt(0)) : -1; |
637 SetValue(instr, Smi::ZoneHandle(Z, Smi::New(result))); | 581 SetValue(instr, Smi::ZoneHandle(Z, Smi::New(result))); |
638 } | 582 } |
639 } | 583 } |
640 | 584 |
641 | |
642 void ConstantPropagator::VisitStringInterpolate(StringInterpolateInstr* instr) { | 585 void ConstantPropagator::VisitStringInterpolate(StringInterpolateInstr* instr) { |
643 SetValue(instr, non_constant_); | 586 SetValue(instr, non_constant_); |
644 } | 587 } |
645 | 588 |
646 | |
647 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) { | 589 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) { |
648 const Object& array_obj = instr->array()->definition()->constant_value(); | 590 const Object& array_obj = instr->array()->definition()->constant_value(); |
649 const Object& index_obj = instr->index()->definition()->constant_value(); | 591 const Object& index_obj = instr->index()->definition()->constant_value(); |
650 if (IsNonConstant(array_obj) || IsNonConstant(index_obj)) { | 592 if (IsNonConstant(array_obj) || IsNonConstant(index_obj)) { |
651 SetValue(instr, non_constant_); | 593 SetValue(instr, non_constant_); |
652 } else if (IsConstant(array_obj) && IsConstant(index_obj)) { | 594 } else if (IsConstant(array_obj) && IsConstant(index_obj)) { |
653 // Need index to be Smi and array to be either String or an immutable array. | 595 // Need index to be Smi and array to be either String or an immutable array. |
654 if (!index_obj.IsSmi()) { | 596 if (!index_obj.IsSmi()) { |
655 // Should not occur. | 597 // Should not occur. |
656 SetValue(instr, non_constant_); | 598 SetValue(instr, non_constant_); |
(...skipping 16 matching lines...) Expand all Loading... |
673 result ^= a.At(index); | 615 result ^= a.At(index); |
674 SetValue(instr, result); | 616 SetValue(instr, result); |
675 return; | 617 return; |
676 } | 618 } |
677 } | 619 } |
678 } | 620 } |
679 SetValue(instr, non_constant_); | 621 SetValue(instr, non_constant_); |
680 } | 622 } |
681 } | 623 } |
682 | 624 |
683 | |
684 void ConstantPropagator::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) { | 625 void ConstantPropagator::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) { |
685 // TODO(zerny): Implement constant propagation. | 626 // TODO(zerny): Implement constant propagation. |
686 SetValue(instr, non_constant_); | 627 SetValue(instr, non_constant_); |
687 } | 628 } |
688 | 629 |
689 | |
690 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { | 630 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { |
691 SetValue(instr, instr->value()->definition()->constant_value()); | 631 SetValue(instr, instr->value()->definition()->constant_value()); |
692 } | 632 } |
693 | 633 |
694 | |
695 void ConstantPropagator::VisitStoreInstanceField( | 634 void ConstantPropagator::VisitStoreInstanceField( |
696 StoreInstanceFieldInstr* instr) { | 635 StoreInstanceFieldInstr* instr) { |
697 SetValue(instr, instr->value()->definition()->constant_value()); | 636 SetValue(instr, instr->value()->definition()->constant_value()); |
698 } | 637 } |
699 | 638 |
700 | |
701 void ConstantPropagator::VisitInitStaticField(InitStaticFieldInstr* instr) { | 639 void ConstantPropagator::VisitInitStaticField(InitStaticFieldInstr* instr) { |
702 // Nothing to do. | 640 // Nothing to do. |
703 } | 641 } |
704 | 642 |
705 | |
706 void ConstantPropagator::VisitLoadStaticField(LoadStaticFieldInstr* instr) { | 643 void ConstantPropagator::VisitLoadStaticField(LoadStaticFieldInstr* instr) { |
707 if (!FLAG_fields_may_be_reset) { | 644 if (!FLAG_fields_may_be_reset) { |
708 const Field& field = instr->StaticField(); | 645 const Field& field = instr->StaticField(); |
709 ASSERT(field.is_static()); | 646 ASSERT(field.is_static()); |
710 Instance& obj = Instance::Handle(Z, field.StaticValue()); | 647 Instance& obj = Instance::Handle(Z, field.StaticValue()); |
711 if (field.is_final() && (obj.raw() != Object::sentinel().raw()) && | 648 if (field.is_final() && (obj.raw() != Object::sentinel().raw()) && |
712 (obj.raw() != Object::transition_sentinel().raw())) { | 649 (obj.raw() != Object::transition_sentinel().raw())) { |
713 if (obj.IsSmi() || obj.IsOld()) { | 650 if (obj.IsSmi() || obj.IsOld()) { |
714 SetValue(instr, obj); | 651 SetValue(instr, obj); |
715 return; | 652 return; |
716 } | 653 } |
717 } | 654 } |
718 } | 655 } |
719 SetValue(instr, non_constant_); | 656 SetValue(instr, non_constant_); |
720 } | 657 } |
721 | 658 |
722 | |
723 void ConstantPropagator::VisitStoreStaticField(StoreStaticFieldInstr* instr) { | 659 void ConstantPropagator::VisitStoreStaticField(StoreStaticFieldInstr* instr) { |
724 SetValue(instr, instr->value()->definition()->constant_value()); | 660 SetValue(instr, instr->value()->definition()->constant_value()); |
725 } | 661 } |
726 | 662 |
727 | |
728 void ConstantPropagator::VisitBooleanNegate(BooleanNegateInstr* instr) { | 663 void ConstantPropagator::VisitBooleanNegate(BooleanNegateInstr* instr) { |
729 const Object& value = instr->value()->definition()->constant_value(); | 664 const Object& value = instr->value()->definition()->constant_value(); |
730 if (IsNonConstant(value)) { | 665 if (IsNonConstant(value)) { |
731 SetValue(instr, non_constant_); | 666 SetValue(instr, non_constant_); |
732 } else if (IsConstant(value)) { | 667 } else if (IsConstant(value)) { |
733 bool val = value.raw() != Bool::True().raw(); | 668 bool val = value.raw() != Bool::True().raw(); |
734 SetValue(instr, Bool::Get(val)); | 669 SetValue(instr, Bool::Get(val)); |
735 } | 670 } |
736 } | 671 } |
737 | 672 |
738 | |
739 void ConstantPropagator::VisitInstanceOf(InstanceOfInstr* instr) { | 673 void ConstantPropagator::VisitInstanceOf(InstanceOfInstr* instr) { |
740 Definition* def = instr->value()->definition(); | 674 Definition* def = instr->value()->definition(); |
741 const Object& value = def->constant_value(); | 675 const Object& value = def->constant_value(); |
742 if (IsNonConstant(value)) { | 676 if (IsNonConstant(value)) { |
743 const AbstractType& checked_type = instr->type(); | 677 const AbstractType& checked_type = instr->type(); |
744 intptr_t value_cid = instr->value()->definition()->Type()->ToCid(); | 678 intptr_t value_cid = instr->value()->definition()->Type()->ToCid(); |
745 Representation rep = def->representation(); | 679 Representation rep = def->representation(); |
746 if ((checked_type.IsFloat32x4Type() && (rep == kUnboxedFloat32x4)) || | 680 if ((checked_type.IsFloat32x4Type() && (rep == kUnboxedFloat32x4)) || |
747 (checked_type.IsInt32x4Type() && (rep == kUnboxedInt32x4)) || | 681 (checked_type.IsInt32x4Type() && (rep == kUnboxedInt32x4)) || |
748 (checked_type.IsDoubleType() && (rep == kUnboxedDouble) && | 682 (checked_type.IsDoubleType() && (rep == kUnboxedDouble) && |
(...skipping 22 matching lines...) Expand all Loading... |
771 // Can only have bound error with generics. | 705 // Can only have bound error with generics. |
772 ASSERT(bound_error.IsNull()); | 706 ASSERT(bound_error.IsNull()); |
773 SetValue(instr, Bool::Get(is_instance)); | 707 SetValue(instr, Bool::Get(is_instance)); |
774 return; | 708 return; |
775 } | 709 } |
776 } | 710 } |
777 SetValue(instr, non_constant_); | 711 SetValue(instr, non_constant_); |
778 } | 712 } |
779 } | 713 } |
780 | 714 |
781 | |
782 void ConstantPropagator::VisitCreateArray(CreateArrayInstr* instr) { | 715 void ConstantPropagator::VisitCreateArray(CreateArrayInstr* instr) { |
783 SetValue(instr, non_constant_); | 716 SetValue(instr, non_constant_); |
784 } | 717 } |
785 | 718 |
786 | |
787 void ConstantPropagator::VisitAllocateObject(AllocateObjectInstr* instr) { | 719 void ConstantPropagator::VisitAllocateObject(AllocateObjectInstr* instr) { |
788 SetValue(instr, non_constant_); | 720 SetValue(instr, non_constant_); |
789 } | 721 } |
790 | 722 |
791 | |
792 void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) { | 723 void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) { |
793 SetValue(instr, non_constant_); | 724 SetValue(instr, non_constant_); |
794 } | 725 } |
795 | 726 |
796 | |
797 void ConstantPropagator::VisitLoadClassId(LoadClassIdInstr* instr) { | 727 void ConstantPropagator::VisitLoadClassId(LoadClassIdInstr* instr) { |
798 intptr_t cid = instr->object()->Type()->ToCid(); | 728 intptr_t cid = instr->object()->Type()->ToCid(); |
799 if (cid != kDynamicCid) { | 729 if (cid != kDynamicCid) { |
800 SetValue(instr, Smi::ZoneHandle(Z, Smi::New(cid))); | 730 SetValue(instr, Smi::ZoneHandle(Z, Smi::New(cid))); |
801 return; | 731 return; |
802 } | 732 } |
803 | 733 |
804 const Object& object = instr->object()->definition()->constant_value(); | 734 const Object& object = instr->object()->definition()->constant_value(); |
805 if (IsConstant(object)) { | 735 if (IsConstant(object)) { |
806 cid = object.GetClassId(); | 736 cid = object.GetClassId(); |
807 if (!Field::IsExternalizableCid(cid)) { | 737 if (!Field::IsExternalizableCid(cid)) { |
808 SetValue(instr, Smi::ZoneHandle(Z, Smi::New(cid))); | 738 SetValue(instr, Smi::ZoneHandle(Z, Smi::New(cid))); |
809 return; | 739 return; |
810 } | 740 } |
811 } | 741 } |
812 SetValue(instr, non_constant_); | 742 SetValue(instr, non_constant_); |
813 } | 743 } |
814 | 744 |
815 | |
816 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) { | 745 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) { |
817 Value* instance = instr->instance(); | 746 Value* instance = instr->instance(); |
818 if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) && | 747 if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) && |
819 instance->definition()->OriginalDefinition()->IsCreateArray()) { | 748 instance->definition()->OriginalDefinition()->IsCreateArray()) { |
820 Value* num_elements = instance->definition() | 749 Value* num_elements = instance->definition() |
821 ->OriginalDefinition() | 750 ->OriginalDefinition() |
822 ->AsCreateArray() | 751 ->AsCreateArray() |
823 ->num_elements(); | 752 ->num_elements(); |
824 if (num_elements->BindsToConstant() && | 753 if (num_elements->BindsToConstant() && |
825 num_elements->BoundConstant().IsSmi()) { | 754 num_elements->BoundConstant().IsSmi()) { |
(...skipping 27 matching lines...) Expand all Loading... |
853 if (instr->Evaluate(constant, &value)) { | 782 if (instr->Evaluate(constant, &value)) { |
854 SetValue(instr, Object::ZoneHandle(Z, value.raw())); | 783 SetValue(instr, Object::ZoneHandle(Z, value.raw())); |
855 return; | 784 return; |
856 } | 785 } |
857 } | 786 } |
858 } | 787 } |
859 | 788 |
860 SetValue(instr, non_constant_); | 789 SetValue(instr, non_constant_); |
861 } | 790 } |
862 | 791 |
863 | |
864 void ConstantPropagator::VisitInstantiateType(InstantiateTypeInstr* instr) { | 792 void ConstantPropagator::VisitInstantiateType(InstantiateTypeInstr* instr) { |
865 const Object& object = | 793 const Object& object = |
866 instr->instantiator_type_arguments()->definition()->constant_value(); | 794 instr->instantiator_type_arguments()->definition()->constant_value(); |
867 if (IsNonConstant(object)) { | 795 if (IsNonConstant(object)) { |
868 SetValue(instr, non_constant_); | 796 SetValue(instr, non_constant_); |
869 return; | 797 return; |
870 } | 798 } |
871 if (IsConstant(object)) { | 799 if (IsConstant(object)) { |
872 if (instr->type().IsTypeParameter() && | 800 if (instr->type().IsTypeParameter() && |
873 TypeParameter::Cast(instr->type()).IsClassTypeParameter()) { | 801 TypeParameter::Cast(instr->type()).IsClassTypeParameter()) { |
874 if (object.IsNull()) { | 802 if (object.IsNull()) { |
875 SetValue(instr, Object::dynamic_type()); | 803 SetValue(instr, Object::dynamic_type()); |
876 return; | 804 return; |
877 } | 805 } |
878 // We could try to instantiate the type parameter and return it if no | 806 // We could try to instantiate the type parameter and return it if no |
879 // malformed error is reported. | 807 // malformed error is reported. |
880 } | 808 } |
881 SetValue(instr, non_constant_); | 809 SetValue(instr, non_constant_); |
882 } | 810 } |
883 // TODO(regis): We can do the same as above for a function type parameter. | 811 // TODO(regis): We can do the same as above for a function type parameter. |
884 // Better: If both instantiator type arguments and function type arguments are | 812 // Better: If both instantiator type arguments and function type arguments are |
885 // constant, instantiate the type if no bound error is reported. | 813 // constant, instantiate the type if no bound error is reported. |
886 } | 814 } |
887 | 815 |
888 | |
889 void ConstantPropagator::VisitInstantiateTypeArguments( | 816 void ConstantPropagator::VisitInstantiateTypeArguments( |
890 InstantiateTypeArgumentsInstr* instr) { | 817 InstantiateTypeArgumentsInstr* instr) { |
891 const Object& instantiator_type_args = | 818 const Object& instantiator_type_args = |
892 instr->instantiator_type_arguments()->definition()->constant_value(); | 819 instr->instantiator_type_arguments()->definition()->constant_value(); |
893 const Object& function_type_args = | 820 const Object& function_type_args = |
894 instr->function_type_arguments()->definition()->constant_value(); | 821 instr->function_type_arguments()->definition()->constant_value(); |
895 if (IsNonConstant(instantiator_type_args) || | 822 if (IsNonConstant(instantiator_type_args) || |
896 IsNonConstant(function_type_args)) { | 823 IsNonConstant(function_type_args)) { |
897 SetValue(instr, non_constant_); | 824 SetValue(instr, non_constant_); |
898 return; | 825 return; |
(...skipping 16 matching lines...) Expand all Loading... |
915 } | 842 } |
916 // TODO(regis): If both instantiator type arguments and function type | 843 // TODO(regis): If both instantiator type arguments and function type |
917 // arguments are constant, instantiate the type arguments if no bound error | 844 // arguments are constant, instantiate the type arguments if no bound error |
918 // is reported. | 845 // is reported. |
919 // TODO(regis): If either instantiator type arguments or function type | 846 // TODO(regis): If either instantiator type arguments or function type |
920 // arguments are constant null, check | 847 // arguments are constant null, check |
921 // type_arguments().IsRawWhenInstantiatedFromRaw() separately for each | 848 // type_arguments().IsRawWhenInstantiatedFromRaw() separately for each |
922 // genericity. | 849 // genericity. |
923 } | 850 } |
924 | 851 |
925 | |
926 void ConstantPropagator::VisitAllocateContext(AllocateContextInstr* instr) { | 852 void ConstantPropagator::VisitAllocateContext(AllocateContextInstr* instr) { |
927 SetValue(instr, non_constant_); | 853 SetValue(instr, non_constant_); |
928 } | 854 } |
929 | 855 |
930 | |
931 void ConstantPropagator::VisitAllocateUninitializedContext( | 856 void ConstantPropagator::VisitAllocateUninitializedContext( |
932 AllocateUninitializedContextInstr* instr) { | 857 AllocateUninitializedContextInstr* instr) { |
933 SetValue(instr, non_constant_); | 858 SetValue(instr, non_constant_); |
934 } | 859 } |
935 | 860 |
936 | |
937 void ConstantPropagator::VisitCloneContext(CloneContextInstr* instr) { | 861 void ConstantPropagator::VisitCloneContext(CloneContextInstr* instr) { |
938 SetValue(instr, non_constant_); | 862 SetValue(instr, non_constant_); |
939 } | 863 } |
940 | 864 |
941 | |
942 void ConstantPropagator::VisitBinaryIntegerOp(BinaryIntegerOpInstr* binary_op) { | 865 void ConstantPropagator::VisitBinaryIntegerOp(BinaryIntegerOpInstr* binary_op) { |
943 const Object& left = binary_op->left()->definition()->constant_value(); | 866 const Object& left = binary_op->left()->definition()->constant_value(); |
944 const Object& right = binary_op->right()->definition()->constant_value(); | 867 const Object& right = binary_op->right()->definition()->constant_value(); |
945 if (IsConstant(left) && IsConstant(right)) { | 868 if (IsConstant(left) && IsConstant(right)) { |
946 if (left.IsInteger() && right.IsInteger()) { | 869 if (left.IsInteger() && right.IsInteger()) { |
947 const Integer& left_int = Integer::Cast(left); | 870 const Integer& left_int = Integer::Cast(left); |
948 const Integer& right_int = Integer::Cast(right); | 871 const Integer& right_int = Integer::Cast(right); |
949 const Integer& result = | 872 const Integer& result = |
950 Integer::Handle(Z, binary_op->Evaluate(left_int, right_int)); | 873 Integer::Handle(Z, binary_op->Evaluate(left_int, right_int)); |
951 if (!result.IsNull()) { | 874 if (!result.IsNull()) { |
952 SetValue(binary_op, Integer::ZoneHandle(Z, result.raw())); | 875 SetValue(binary_op, Integer::ZoneHandle(Z, result.raw())); |
953 return; | 876 return; |
954 } | 877 } |
955 } | 878 } |
956 } | 879 } |
957 | 880 |
958 SetValue(binary_op, non_constant_); | 881 SetValue(binary_op, non_constant_); |
959 } | 882 } |
960 | 883 |
961 | |
962 void ConstantPropagator::VisitCheckedSmiOp(CheckedSmiOpInstr* instr) { | 884 void ConstantPropagator::VisitCheckedSmiOp(CheckedSmiOpInstr* instr) { |
963 SetValue(instr, non_constant_); | 885 SetValue(instr, non_constant_); |
964 } | 886 } |
965 | 887 |
966 | |
967 void ConstantPropagator::VisitCheckedSmiComparison( | 888 void ConstantPropagator::VisitCheckedSmiComparison( |
968 CheckedSmiComparisonInstr* instr) { | 889 CheckedSmiComparisonInstr* instr) { |
969 SetValue(instr, non_constant_); | 890 SetValue(instr, non_constant_); |
970 } | 891 } |
971 | 892 |
972 | |
973 void ConstantPropagator::VisitBinarySmiOp(BinarySmiOpInstr* instr) { | 893 void ConstantPropagator::VisitBinarySmiOp(BinarySmiOpInstr* instr) { |
974 VisitBinaryIntegerOp(instr); | 894 VisitBinaryIntegerOp(instr); |
975 } | 895 } |
976 | 896 |
977 | |
978 void ConstantPropagator::VisitBinaryInt32Op(BinaryInt32OpInstr* instr) { | 897 void ConstantPropagator::VisitBinaryInt32Op(BinaryInt32OpInstr* instr) { |
979 VisitBinaryIntegerOp(instr); | 898 VisitBinaryIntegerOp(instr); |
980 } | 899 } |
981 | 900 |
982 | |
983 void ConstantPropagator::VisitBinaryUint32Op(BinaryUint32OpInstr* instr) { | 901 void ConstantPropagator::VisitBinaryUint32Op(BinaryUint32OpInstr* instr) { |
984 VisitBinaryIntegerOp(instr); | 902 VisitBinaryIntegerOp(instr); |
985 } | 903 } |
986 | 904 |
987 | |
988 void ConstantPropagator::VisitShiftUint32Op(ShiftUint32OpInstr* instr) { | 905 void ConstantPropagator::VisitShiftUint32Op(ShiftUint32OpInstr* instr) { |
989 VisitBinaryIntegerOp(instr); | 906 VisitBinaryIntegerOp(instr); |
990 } | 907 } |
991 | 908 |
992 | |
993 void ConstantPropagator::VisitBinaryMintOp(BinaryMintOpInstr* instr) { | 909 void ConstantPropagator::VisitBinaryMintOp(BinaryMintOpInstr* instr) { |
994 VisitBinaryIntegerOp(instr); | 910 VisitBinaryIntegerOp(instr); |
995 } | 911 } |
996 | 912 |
997 | |
998 void ConstantPropagator::VisitShiftMintOp(ShiftMintOpInstr* instr) { | 913 void ConstantPropagator::VisitShiftMintOp(ShiftMintOpInstr* instr) { |
999 VisitBinaryIntegerOp(instr); | 914 VisitBinaryIntegerOp(instr); |
1000 } | 915 } |
1001 | 916 |
1002 | |
1003 void ConstantPropagator::VisitBoxInt64(BoxInt64Instr* instr) { | 917 void ConstantPropagator::VisitBoxInt64(BoxInt64Instr* instr) { |
1004 // TODO(kmillikin): Handle box operation. | 918 // TODO(kmillikin): Handle box operation. |
1005 SetValue(instr, non_constant_); | 919 SetValue(instr, non_constant_); |
1006 } | 920 } |
1007 | 921 |
1008 | |
1009 void ConstantPropagator::VisitUnboxInt64(UnboxInt64Instr* instr) { | 922 void ConstantPropagator::VisitUnboxInt64(UnboxInt64Instr* instr) { |
1010 // TODO(kmillikin): Handle unbox operation. | 923 // TODO(kmillikin): Handle unbox operation. |
1011 SetValue(instr, non_constant_); | 924 SetValue(instr, non_constant_); |
1012 } | 925 } |
1013 | 926 |
1014 | |
1015 void ConstantPropagator::VisitUnaryIntegerOp(UnaryIntegerOpInstr* unary_op) { | 927 void ConstantPropagator::VisitUnaryIntegerOp(UnaryIntegerOpInstr* unary_op) { |
1016 const Object& value = unary_op->value()->definition()->constant_value(); | 928 const Object& value = unary_op->value()->definition()->constant_value(); |
1017 if (IsConstant(value) && value.IsInteger()) { | 929 if (IsConstant(value) && value.IsInteger()) { |
1018 const Integer& value_int = Integer::Cast(value); | 930 const Integer& value_int = Integer::Cast(value); |
1019 const Integer& result = Integer::Handle(Z, unary_op->Evaluate(value_int)); | 931 const Integer& result = Integer::Handle(Z, unary_op->Evaluate(value_int)); |
1020 if (!result.IsNull()) { | 932 if (!result.IsNull()) { |
1021 SetValue(unary_op, Integer::ZoneHandle(Z, result.raw())); | 933 SetValue(unary_op, Integer::ZoneHandle(Z, result.raw())); |
1022 return; | 934 return; |
1023 } | 935 } |
1024 } | 936 } |
1025 | 937 |
1026 SetValue(unary_op, non_constant_); | 938 SetValue(unary_op, non_constant_); |
1027 } | 939 } |
1028 | 940 |
1029 | |
1030 void ConstantPropagator::VisitUnaryMintOp(UnaryMintOpInstr* instr) { | 941 void ConstantPropagator::VisitUnaryMintOp(UnaryMintOpInstr* instr) { |
1031 VisitUnaryIntegerOp(instr); | 942 VisitUnaryIntegerOp(instr); |
1032 } | 943 } |
1033 | 944 |
1034 | |
1035 void ConstantPropagator::VisitUnarySmiOp(UnarySmiOpInstr* instr) { | 945 void ConstantPropagator::VisitUnarySmiOp(UnarySmiOpInstr* instr) { |
1036 VisitUnaryIntegerOp(instr); | 946 VisitUnaryIntegerOp(instr); |
1037 } | 947 } |
1038 | 948 |
1039 | |
1040 void ConstantPropagator::VisitUnaryDoubleOp(UnaryDoubleOpInstr* instr) { | 949 void ConstantPropagator::VisitUnaryDoubleOp(UnaryDoubleOpInstr* instr) { |
1041 const Object& value = instr->value()->definition()->constant_value(); | 950 const Object& value = instr->value()->definition()->constant_value(); |
1042 if (IsNonConstant(value)) { | 951 if (IsNonConstant(value)) { |
1043 SetValue(instr, non_constant_); | 952 SetValue(instr, non_constant_); |
1044 } else if (IsConstant(value)) { | 953 } else if (IsConstant(value)) { |
1045 // TODO(kmillikin): Handle unary operations. | 954 // TODO(kmillikin): Handle unary operations. |
1046 SetValue(instr, non_constant_); | 955 SetValue(instr, non_constant_); |
1047 } | 956 } |
1048 } | 957 } |
1049 | 958 |
1050 | |
1051 void ConstantPropagator::VisitSmiToDouble(SmiToDoubleInstr* instr) { | 959 void ConstantPropagator::VisitSmiToDouble(SmiToDoubleInstr* instr) { |
1052 const Object& value = instr->value()->definition()->constant_value(); | 960 const Object& value = instr->value()->definition()->constant_value(); |
1053 if (IsConstant(value) && value.IsInteger()) { | 961 if (IsConstant(value) && value.IsInteger()) { |
1054 SetValue(instr, | 962 SetValue(instr, |
1055 Double::Handle(Z, Double::New(Integer::Cast(value).AsDoubleValue(), | 963 Double::Handle(Z, Double::New(Integer::Cast(value).AsDoubleValue(), |
1056 Heap::kOld))); | 964 Heap::kOld))); |
1057 } else if (!IsUnknown(value)) { | 965 } else if (!IsUnknown(value)) { |
1058 SetValue(instr, non_constant_); | 966 SetValue(instr, non_constant_); |
1059 } | 967 } |
1060 } | 968 } |
1061 | 969 |
1062 | |
1063 void ConstantPropagator::VisitMintToDouble(MintToDoubleInstr* instr) { | 970 void ConstantPropagator::VisitMintToDouble(MintToDoubleInstr* instr) { |
1064 const Object& value = instr->value()->definition()->constant_value(); | 971 const Object& value = instr->value()->definition()->constant_value(); |
1065 if (IsConstant(value) && value.IsInteger()) { | 972 if (IsConstant(value) && value.IsInteger()) { |
1066 SetValue(instr, | 973 SetValue(instr, |
1067 Double::Handle(Z, Double::New(Integer::Cast(value).AsDoubleValue(), | 974 Double::Handle(Z, Double::New(Integer::Cast(value).AsDoubleValue(), |
1068 Heap::kOld))); | 975 Heap::kOld))); |
1069 } else if (!IsUnknown(value)) { | 976 } else if (!IsUnknown(value)) { |
1070 SetValue(instr, non_constant_); | 977 SetValue(instr, non_constant_); |
1071 } | 978 } |
1072 } | 979 } |
1073 | 980 |
1074 | |
1075 void ConstantPropagator::VisitInt32ToDouble(Int32ToDoubleInstr* instr) { | 981 void ConstantPropagator::VisitInt32ToDouble(Int32ToDoubleInstr* instr) { |
1076 const Object& value = instr->value()->definition()->constant_value(); | 982 const Object& value = instr->value()->definition()->constant_value(); |
1077 if (IsConstant(value) && value.IsInteger()) { | 983 if (IsConstant(value) && value.IsInteger()) { |
1078 SetValue(instr, | 984 SetValue(instr, |
1079 Double::Handle(Z, Double::New(Integer::Cast(value).AsDoubleValue(), | 985 Double::Handle(Z, Double::New(Integer::Cast(value).AsDoubleValue(), |
1080 Heap::kOld))); | 986 Heap::kOld))); |
1081 } else if (!IsUnknown(value)) { | 987 } else if (!IsUnknown(value)) { |
1082 SetValue(instr, non_constant_); | 988 SetValue(instr, non_constant_); |
1083 } | 989 } |
1084 } | 990 } |
1085 | 991 |
1086 | |
1087 void ConstantPropagator::VisitDoubleToInteger(DoubleToIntegerInstr* instr) { | 992 void ConstantPropagator::VisitDoubleToInteger(DoubleToIntegerInstr* instr) { |
1088 // TODO(kmillikin): Handle conversion. | 993 // TODO(kmillikin): Handle conversion. |
1089 SetValue(instr, non_constant_); | 994 SetValue(instr, non_constant_); |
1090 } | 995 } |
1091 | 996 |
1092 | |
1093 void ConstantPropagator::VisitDoubleToSmi(DoubleToSmiInstr* instr) { | 997 void ConstantPropagator::VisitDoubleToSmi(DoubleToSmiInstr* instr) { |
1094 // TODO(kmillikin): Handle conversion. | 998 // TODO(kmillikin): Handle conversion. |
1095 SetValue(instr, non_constant_); | 999 SetValue(instr, non_constant_); |
1096 } | 1000 } |
1097 | 1001 |
1098 | |
1099 void ConstantPropagator::VisitDoubleToDouble(DoubleToDoubleInstr* instr) { | 1002 void ConstantPropagator::VisitDoubleToDouble(DoubleToDoubleInstr* instr) { |
1100 // TODO(kmillikin): Handle conversion. | 1003 // TODO(kmillikin): Handle conversion. |
1101 SetValue(instr, non_constant_); | 1004 SetValue(instr, non_constant_); |
1102 } | 1005 } |
1103 | 1006 |
1104 | |
1105 void ConstantPropagator::VisitDoubleToFloat(DoubleToFloatInstr* instr) { | 1007 void ConstantPropagator::VisitDoubleToFloat(DoubleToFloatInstr* instr) { |
1106 // TODO(kmillikin): Handle conversion. | 1008 // TODO(kmillikin): Handle conversion. |
1107 SetValue(instr, non_constant_); | 1009 SetValue(instr, non_constant_); |
1108 } | 1010 } |
1109 | 1011 |
1110 | |
1111 void ConstantPropagator::VisitFloatToDouble(FloatToDoubleInstr* instr) { | 1012 void ConstantPropagator::VisitFloatToDouble(FloatToDoubleInstr* instr) { |
1112 // TODO(kmillikin): Handle conversion. | 1013 // TODO(kmillikin): Handle conversion. |
1113 SetValue(instr, non_constant_); | 1014 SetValue(instr, non_constant_); |
1114 } | 1015 } |
1115 | 1016 |
1116 | |
1117 void ConstantPropagator::VisitInvokeMathCFunction( | 1017 void ConstantPropagator::VisitInvokeMathCFunction( |
1118 InvokeMathCFunctionInstr* instr) { | 1018 InvokeMathCFunctionInstr* instr) { |
1119 // TODO(kmillikin): Handle conversion. | 1019 // TODO(kmillikin): Handle conversion. |
1120 SetValue(instr, non_constant_); | 1020 SetValue(instr, non_constant_); |
1121 } | 1021 } |
1122 | 1022 |
1123 | |
1124 void ConstantPropagator::VisitTruncDivMod(TruncDivModInstr* instr) { | 1023 void ConstantPropagator::VisitTruncDivMod(TruncDivModInstr* instr) { |
1125 // TODO(srdjan): Handle merged instruction. | 1024 // TODO(srdjan): Handle merged instruction. |
1126 SetValue(instr, non_constant_); | 1025 SetValue(instr, non_constant_); |
1127 } | 1026 } |
1128 | 1027 |
1129 | |
1130 void ConstantPropagator::VisitExtractNthOutput(ExtractNthOutputInstr* instr) { | 1028 void ConstantPropagator::VisitExtractNthOutput(ExtractNthOutputInstr* instr) { |
1131 SetValue(instr, non_constant_); | 1029 SetValue(instr, non_constant_); |
1132 } | 1030 } |
1133 | 1031 |
1134 | |
1135 void ConstantPropagator::VisitConstant(ConstantInstr* instr) { | 1032 void ConstantPropagator::VisitConstant(ConstantInstr* instr) { |
1136 SetValue(instr, instr->value()); | 1033 SetValue(instr, instr->value()); |
1137 } | 1034 } |
1138 | 1035 |
1139 | |
1140 void ConstantPropagator::VisitUnboxedConstant(UnboxedConstantInstr* instr) { | 1036 void ConstantPropagator::VisitUnboxedConstant(UnboxedConstantInstr* instr) { |
1141 SetValue(instr, instr->value()); | 1037 SetValue(instr, instr->value()); |
1142 } | 1038 } |
1143 | 1039 |
1144 | |
1145 void ConstantPropagator::VisitConstraint(ConstraintInstr* instr) { | 1040 void ConstantPropagator::VisitConstraint(ConstraintInstr* instr) { |
1146 // Should not be used outside of range analysis. | 1041 // Should not be used outside of range analysis. |
1147 UNREACHABLE(); | 1042 UNREACHABLE(); |
1148 } | 1043 } |
1149 | 1044 |
1150 | |
1151 void ConstantPropagator::VisitMaterializeObject(MaterializeObjectInstr* instr) { | 1045 void ConstantPropagator::VisitMaterializeObject(MaterializeObjectInstr* instr) { |
1152 // Should not be used outside of allocation elimination pass. | 1046 // Should not be used outside of allocation elimination pass. |
1153 UNREACHABLE(); | 1047 UNREACHABLE(); |
1154 } | 1048 } |
1155 | 1049 |
1156 | |
1157 static bool IsIntegerOrDouble(const Object& value) { | 1050 static bool IsIntegerOrDouble(const Object& value) { |
1158 return value.IsInteger() || value.IsDouble(); | 1051 return value.IsInteger() || value.IsDouble(); |
1159 } | 1052 } |
1160 | 1053 |
1161 | |
1162 static double ToDouble(const Object& value) { | 1054 static double ToDouble(const Object& value) { |
1163 return value.IsInteger() ? Integer::Cast(value).AsDoubleValue() | 1055 return value.IsInteger() ? Integer::Cast(value).AsDoubleValue() |
1164 : Double::Cast(value).value(); | 1056 : Double::Cast(value).value(); |
1165 } | 1057 } |
1166 | 1058 |
1167 | |
1168 void ConstantPropagator::VisitBinaryDoubleOp(BinaryDoubleOpInstr* instr) { | 1059 void ConstantPropagator::VisitBinaryDoubleOp(BinaryDoubleOpInstr* instr) { |
1169 const Object& left = instr->left()->definition()->constant_value(); | 1060 const Object& left = instr->left()->definition()->constant_value(); |
1170 const Object& right = instr->right()->definition()->constant_value(); | 1061 const Object& right = instr->right()->definition()->constant_value(); |
1171 if (IsNonConstant(left) || IsNonConstant(right)) { | 1062 if (IsNonConstant(left) || IsNonConstant(right)) { |
1172 SetValue(instr, non_constant_); | 1063 SetValue(instr, non_constant_); |
1173 } else if (left.IsInteger() && right.IsInteger()) { | 1064 } else if (left.IsInteger() && right.IsInteger()) { |
1174 SetValue(instr, non_constant_); | 1065 SetValue(instr, non_constant_); |
1175 } else if (IsIntegerOrDouble(left) && IsIntegerOrDouble(right)) { | 1066 } else if (IsIntegerOrDouble(left) && IsIntegerOrDouble(right)) { |
1176 const double left_val = ToDouble(left); | 1067 const double left_val = ToDouble(left); |
1177 const double right_val = ToDouble(right); | 1068 const double right_val = ToDouble(right); |
(...skipping 12 matching lines...) Expand all Loading... |
1190 result_val = left_val / right_val; | 1081 result_val = left_val / right_val; |
1191 break; | 1082 break; |
1192 default: | 1083 default: |
1193 UNREACHABLE(); | 1084 UNREACHABLE(); |
1194 } | 1085 } |
1195 const Double& result = Double::ZoneHandle(Double::NewCanonical(result_val)); | 1086 const Double& result = Double::ZoneHandle(Double::NewCanonical(result_val)); |
1196 SetValue(instr, result); | 1087 SetValue(instr, result); |
1197 } | 1088 } |
1198 } | 1089 } |
1199 | 1090 |
1200 | |
1201 void ConstantPropagator::VisitDoubleTestOp(DoubleTestOpInstr* instr) { | 1091 void ConstantPropagator::VisitDoubleTestOp(DoubleTestOpInstr* instr) { |
1202 const Object& value = instr->value()->definition()->constant_value(); | 1092 const Object& value = instr->value()->definition()->constant_value(); |
1203 const bool is_negated = instr->kind() != Token::kEQ; | 1093 const bool is_negated = instr->kind() != Token::kEQ; |
1204 if (value.IsInteger()) { | 1094 if (value.IsInteger()) { |
1205 SetValue(instr, is_negated ? Bool::True() : Bool::False()); | 1095 SetValue(instr, is_negated ? Bool::True() : Bool::False()); |
1206 } else if (IsIntegerOrDouble(value)) { | 1096 } else if (IsIntegerOrDouble(value)) { |
1207 switch (instr->op_kind()) { | 1097 switch (instr->op_kind()) { |
1208 case MethodRecognizer::kDouble_getIsNaN: { | 1098 case MethodRecognizer::kDouble_getIsNaN: { |
1209 const bool is_nan = isnan(ToDouble(value)); | 1099 const bool is_nan = isnan(ToDouble(value)); |
1210 SetValue(instr, Bool::Get(is_negated ? !is_nan : is_nan)); | 1100 SetValue(instr, Bool::Get(is_negated ? !is_nan : is_nan)); |
1211 break; | 1101 break; |
1212 } | 1102 } |
1213 case MethodRecognizer::kDouble_getIsInfinite: { | 1103 case MethodRecognizer::kDouble_getIsInfinite: { |
1214 const bool is_inf = isinf(ToDouble(value)); | 1104 const bool is_inf = isinf(ToDouble(value)); |
1215 SetValue(instr, Bool::Get(is_negated ? !is_inf : is_inf)); | 1105 SetValue(instr, Bool::Get(is_negated ? !is_inf : is_inf)); |
1216 break; | 1106 break; |
1217 } | 1107 } |
1218 default: | 1108 default: |
1219 UNREACHABLE(); | 1109 UNREACHABLE(); |
1220 } | 1110 } |
1221 } else { | 1111 } else { |
1222 SetValue(instr, non_constant_); | 1112 SetValue(instr, non_constant_); |
1223 } | 1113 } |
1224 } | 1114 } |
1225 | 1115 |
1226 | |
1227 void ConstantPropagator::VisitBinaryFloat32x4Op(BinaryFloat32x4OpInstr* instr) { | 1116 void ConstantPropagator::VisitBinaryFloat32x4Op(BinaryFloat32x4OpInstr* instr) { |
1228 const Object& left = instr->left()->definition()->constant_value(); | 1117 const Object& left = instr->left()->definition()->constant_value(); |
1229 const Object& right = instr->right()->definition()->constant_value(); | 1118 const Object& right = instr->right()->definition()->constant_value(); |
1230 if (IsNonConstant(left) || IsNonConstant(right)) { | 1119 if (IsNonConstant(left) || IsNonConstant(right)) { |
1231 SetValue(instr, non_constant_); | 1120 SetValue(instr, non_constant_); |
1232 } else if (IsConstant(left) && IsConstant(right)) { | 1121 } else if (IsConstant(left) && IsConstant(right)) { |
1233 // TODO(kmillikin): Handle binary operation. | 1122 // TODO(kmillikin): Handle binary operation. |
1234 SetValue(instr, non_constant_); | 1123 SetValue(instr, non_constant_); |
1235 } | 1124 } |
1236 } | 1125 } |
1237 | 1126 |
1238 | |
1239 void ConstantPropagator::VisitFloat32x4Constructor( | 1127 void ConstantPropagator::VisitFloat32x4Constructor( |
1240 Float32x4ConstructorInstr* instr) { | 1128 Float32x4ConstructorInstr* instr) { |
1241 SetValue(instr, non_constant_); | 1129 SetValue(instr, non_constant_); |
1242 } | 1130 } |
1243 | 1131 |
1244 | |
1245 void ConstantPropagator::VisitSimd32x4Shuffle(Simd32x4ShuffleInstr* instr) { | 1132 void ConstantPropagator::VisitSimd32x4Shuffle(Simd32x4ShuffleInstr* instr) { |
1246 SetValue(instr, non_constant_); | 1133 SetValue(instr, non_constant_); |
1247 } | 1134 } |
1248 | 1135 |
1249 | |
1250 void ConstantPropagator::VisitSimd32x4ShuffleMix( | 1136 void ConstantPropagator::VisitSimd32x4ShuffleMix( |
1251 Simd32x4ShuffleMixInstr* instr) { | 1137 Simd32x4ShuffleMixInstr* instr) { |
1252 SetValue(instr, non_constant_); | 1138 SetValue(instr, non_constant_); |
1253 } | 1139 } |
1254 | 1140 |
1255 | |
1256 void ConstantPropagator::VisitSimd32x4GetSignMask( | 1141 void ConstantPropagator::VisitSimd32x4GetSignMask( |
1257 Simd32x4GetSignMaskInstr* instr) { | 1142 Simd32x4GetSignMaskInstr* instr) { |
1258 SetValue(instr, non_constant_); | 1143 SetValue(instr, non_constant_); |
1259 } | 1144 } |
1260 | 1145 |
1261 | |
1262 void ConstantPropagator::VisitFloat32x4Zero(Float32x4ZeroInstr* instr) { | 1146 void ConstantPropagator::VisitFloat32x4Zero(Float32x4ZeroInstr* instr) { |
1263 SetValue(instr, non_constant_); | 1147 SetValue(instr, non_constant_); |
1264 } | 1148 } |
1265 | 1149 |
1266 | |
1267 void ConstantPropagator::VisitFloat32x4Splat(Float32x4SplatInstr* instr) { | 1150 void ConstantPropagator::VisitFloat32x4Splat(Float32x4SplatInstr* instr) { |
1268 SetValue(instr, non_constant_); | 1151 SetValue(instr, non_constant_); |
1269 } | 1152 } |
1270 | 1153 |
1271 | |
1272 void ConstantPropagator::VisitFloat32x4Comparison( | 1154 void ConstantPropagator::VisitFloat32x4Comparison( |
1273 Float32x4ComparisonInstr* instr) { | 1155 Float32x4ComparisonInstr* instr) { |
1274 SetValue(instr, non_constant_); | 1156 SetValue(instr, non_constant_); |
1275 } | 1157 } |
1276 | 1158 |
1277 | |
1278 void ConstantPropagator::VisitFloat32x4MinMax(Float32x4MinMaxInstr* instr) { | 1159 void ConstantPropagator::VisitFloat32x4MinMax(Float32x4MinMaxInstr* instr) { |
1279 SetValue(instr, non_constant_); | 1160 SetValue(instr, non_constant_); |
1280 } | 1161 } |
1281 | 1162 |
1282 | |
1283 void ConstantPropagator::VisitFloat32x4Scale(Float32x4ScaleInstr* instr) { | 1163 void ConstantPropagator::VisitFloat32x4Scale(Float32x4ScaleInstr* instr) { |
1284 SetValue(instr, non_constant_); | 1164 SetValue(instr, non_constant_); |
1285 } | 1165 } |
1286 | 1166 |
1287 | |
1288 void ConstantPropagator::VisitFloat32x4Sqrt(Float32x4SqrtInstr* instr) { | 1167 void ConstantPropagator::VisitFloat32x4Sqrt(Float32x4SqrtInstr* instr) { |
1289 SetValue(instr, non_constant_); | 1168 SetValue(instr, non_constant_); |
1290 } | 1169 } |
1291 | 1170 |
1292 | |
1293 void ConstantPropagator::VisitFloat32x4ZeroArg(Float32x4ZeroArgInstr* instr) { | 1171 void ConstantPropagator::VisitFloat32x4ZeroArg(Float32x4ZeroArgInstr* instr) { |
1294 SetValue(instr, non_constant_); | 1172 SetValue(instr, non_constant_); |
1295 } | 1173 } |
1296 | 1174 |
1297 | |
1298 void ConstantPropagator::VisitFloat32x4Clamp(Float32x4ClampInstr* instr) { | 1175 void ConstantPropagator::VisitFloat32x4Clamp(Float32x4ClampInstr* instr) { |
1299 SetValue(instr, non_constant_); | 1176 SetValue(instr, non_constant_); |
1300 } | 1177 } |
1301 | 1178 |
1302 | |
1303 void ConstantPropagator::VisitFloat32x4With(Float32x4WithInstr* instr) { | 1179 void ConstantPropagator::VisitFloat32x4With(Float32x4WithInstr* instr) { |
1304 SetValue(instr, non_constant_); | 1180 SetValue(instr, non_constant_); |
1305 } | 1181 } |
1306 | 1182 |
1307 | |
1308 void ConstantPropagator::VisitFloat32x4ToInt32x4( | 1183 void ConstantPropagator::VisitFloat32x4ToInt32x4( |
1309 Float32x4ToInt32x4Instr* instr) { | 1184 Float32x4ToInt32x4Instr* instr) { |
1310 SetValue(instr, non_constant_); | 1185 SetValue(instr, non_constant_); |
1311 } | 1186 } |
1312 | 1187 |
1313 | |
1314 void ConstantPropagator::VisitInt32x4Constructor( | 1188 void ConstantPropagator::VisitInt32x4Constructor( |
1315 Int32x4ConstructorInstr* instr) { | 1189 Int32x4ConstructorInstr* instr) { |
1316 SetValue(instr, non_constant_); | 1190 SetValue(instr, non_constant_); |
1317 } | 1191 } |
1318 | 1192 |
1319 | |
1320 void ConstantPropagator::VisitInt32x4BoolConstructor( | 1193 void ConstantPropagator::VisitInt32x4BoolConstructor( |
1321 Int32x4BoolConstructorInstr* instr) { | 1194 Int32x4BoolConstructorInstr* instr) { |
1322 SetValue(instr, non_constant_); | 1195 SetValue(instr, non_constant_); |
1323 } | 1196 } |
1324 | 1197 |
1325 | |
1326 void ConstantPropagator::VisitInt32x4GetFlag(Int32x4GetFlagInstr* instr) { | 1198 void ConstantPropagator::VisitInt32x4GetFlag(Int32x4GetFlagInstr* instr) { |
1327 SetValue(instr, non_constant_); | 1199 SetValue(instr, non_constant_); |
1328 } | 1200 } |
1329 | 1201 |
1330 | |
1331 void ConstantPropagator::VisitInt32x4SetFlag(Int32x4SetFlagInstr* instr) { | 1202 void ConstantPropagator::VisitInt32x4SetFlag(Int32x4SetFlagInstr* instr) { |
1332 SetValue(instr, non_constant_); | 1203 SetValue(instr, non_constant_); |
1333 } | 1204 } |
1334 | 1205 |
1335 | |
1336 void ConstantPropagator::VisitInt32x4Select(Int32x4SelectInstr* instr) { | 1206 void ConstantPropagator::VisitInt32x4Select(Int32x4SelectInstr* instr) { |
1337 SetValue(instr, non_constant_); | 1207 SetValue(instr, non_constant_); |
1338 } | 1208 } |
1339 | 1209 |
1340 | |
1341 void ConstantPropagator::VisitInt32x4ToFloat32x4( | 1210 void ConstantPropagator::VisitInt32x4ToFloat32x4( |
1342 Int32x4ToFloat32x4Instr* instr) { | 1211 Int32x4ToFloat32x4Instr* instr) { |
1343 SetValue(instr, non_constant_); | 1212 SetValue(instr, non_constant_); |
1344 } | 1213 } |
1345 | 1214 |
1346 | |
1347 void ConstantPropagator::VisitBinaryInt32x4Op(BinaryInt32x4OpInstr* instr) { | 1215 void ConstantPropagator::VisitBinaryInt32x4Op(BinaryInt32x4OpInstr* instr) { |
1348 SetValue(instr, non_constant_); | 1216 SetValue(instr, non_constant_); |
1349 } | 1217 } |
1350 | 1218 |
1351 | |
1352 void ConstantPropagator::VisitSimd64x2Shuffle(Simd64x2ShuffleInstr* instr) { | 1219 void ConstantPropagator::VisitSimd64x2Shuffle(Simd64x2ShuffleInstr* instr) { |
1353 SetValue(instr, non_constant_); | 1220 SetValue(instr, non_constant_); |
1354 } | 1221 } |
1355 | 1222 |
1356 | |
1357 void ConstantPropagator::VisitBinaryFloat64x2Op(BinaryFloat64x2OpInstr* instr) { | 1223 void ConstantPropagator::VisitBinaryFloat64x2Op(BinaryFloat64x2OpInstr* instr) { |
1358 SetValue(instr, non_constant_); | 1224 SetValue(instr, non_constant_); |
1359 } | 1225 } |
1360 | 1226 |
1361 | |
1362 void ConstantPropagator::VisitFloat32x4ToFloat64x2( | 1227 void ConstantPropagator::VisitFloat32x4ToFloat64x2( |
1363 Float32x4ToFloat64x2Instr* instr) { | 1228 Float32x4ToFloat64x2Instr* instr) { |
1364 SetValue(instr, non_constant_); | 1229 SetValue(instr, non_constant_); |
1365 } | 1230 } |
1366 | 1231 |
1367 | |
1368 void ConstantPropagator::VisitFloat64x2ToFloat32x4( | 1232 void ConstantPropagator::VisitFloat64x2ToFloat32x4( |
1369 Float64x2ToFloat32x4Instr* instr) { | 1233 Float64x2ToFloat32x4Instr* instr) { |
1370 SetValue(instr, non_constant_); | 1234 SetValue(instr, non_constant_); |
1371 } | 1235 } |
1372 | 1236 |
1373 | |
1374 void ConstantPropagator::VisitFloat64x2Zero(Float64x2ZeroInstr* instr) { | 1237 void ConstantPropagator::VisitFloat64x2Zero(Float64x2ZeroInstr* instr) { |
1375 SetValue(instr, non_constant_); | 1238 SetValue(instr, non_constant_); |
1376 } | 1239 } |
1377 | 1240 |
1378 | |
1379 void ConstantPropagator::VisitFloat64x2Splat(Float64x2SplatInstr* instr) { | 1241 void ConstantPropagator::VisitFloat64x2Splat(Float64x2SplatInstr* instr) { |
1380 SetValue(instr, non_constant_); | 1242 SetValue(instr, non_constant_); |
1381 } | 1243 } |
1382 | 1244 |
1383 | |
1384 void ConstantPropagator::VisitFloat64x2Constructor( | 1245 void ConstantPropagator::VisitFloat64x2Constructor( |
1385 Float64x2ConstructorInstr* instr) { | 1246 Float64x2ConstructorInstr* instr) { |
1386 SetValue(instr, non_constant_); | 1247 SetValue(instr, non_constant_); |
1387 } | 1248 } |
1388 | 1249 |
1389 | |
1390 void ConstantPropagator::VisitFloat64x2ZeroArg(Float64x2ZeroArgInstr* instr) { | 1250 void ConstantPropagator::VisitFloat64x2ZeroArg(Float64x2ZeroArgInstr* instr) { |
1391 // TODO(johnmccutchan): Implement constant propagation. | 1251 // TODO(johnmccutchan): Implement constant propagation. |
1392 SetValue(instr, non_constant_); | 1252 SetValue(instr, non_constant_); |
1393 } | 1253 } |
1394 | 1254 |
1395 | |
1396 void ConstantPropagator::VisitFloat64x2OneArg(Float64x2OneArgInstr* instr) { | 1255 void ConstantPropagator::VisitFloat64x2OneArg(Float64x2OneArgInstr* instr) { |
1397 // TODO(johnmccutchan): Implement constant propagation. | 1256 // TODO(johnmccutchan): Implement constant propagation. |
1398 SetValue(instr, non_constant_); | 1257 SetValue(instr, non_constant_); |
1399 } | 1258 } |
1400 | 1259 |
1401 | |
1402 void ConstantPropagator::VisitMathUnary(MathUnaryInstr* instr) { | 1260 void ConstantPropagator::VisitMathUnary(MathUnaryInstr* instr) { |
1403 const Object& value = instr->value()->definition()->constant_value(); | 1261 const Object& value = instr->value()->definition()->constant_value(); |
1404 if (IsNonConstant(value)) { | 1262 if (IsNonConstant(value)) { |
1405 SetValue(instr, non_constant_); | 1263 SetValue(instr, non_constant_); |
1406 } else if (IsConstant(value)) { | 1264 } else if (IsConstant(value)) { |
1407 // TODO(kmillikin): Handle Math's unary operations (sqrt, cos, sin). | 1265 // TODO(kmillikin): Handle Math's unary operations (sqrt, cos, sin). |
1408 SetValue(instr, non_constant_); | 1266 SetValue(instr, non_constant_); |
1409 } | 1267 } |
1410 } | 1268 } |
1411 | 1269 |
1412 | |
1413 void ConstantPropagator::VisitMathMinMax(MathMinMaxInstr* instr) { | 1270 void ConstantPropagator::VisitMathMinMax(MathMinMaxInstr* instr) { |
1414 const Object& left = instr->left()->definition()->constant_value(); | 1271 const Object& left = instr->left()->definition()->constant_value(); |
1415 const Object& right = instr->right()->definition()->constant_value(); | 1272 const Object& right = instr->right()->definition()->constant_value(); |
1416 if (IsNonConstant(left) || IsNonConstant(right)) { | 1273 if (IsNonConstant(left) || IsNonConstant(right)) { |
1417 SetValue(instr, non_constant_); | 1274 SetValue(instr, non_constant_); |
1418 } else if (IsConstant(left) && IsConstant(right)) { | 1275 } else if (IsConstant(left) && IsConstant(right)) { |
1419 // TODO(srdjan): Handle min and max. | 1276 // TODO(srdjan): Handle min and max. |
1420 SetValue(instr, non_constant_); | 1277 SetValue(instr, non_constant_); |
1421 } | 1278 } |
1422 } | 1279 } |
1423 | 1280 |
1424 | |
1425 void ConstantPropagator::VisitCaseInsensitiveCompareUC16( | 1281 void ConstantPropagator::VisitCaseInsensitiveCompareUC16( |
1426 CaseInsensitiveCompareUC16Instr* instr) { | 1282 CaseInsensitiveCompareUC16Instr* instr) { |
1427 SetValue(instr, non_constant_); | 1283 SetValue(instr, non_constant_); |
1428 } | 1284 } |
1429 | 1285 |
1430 | |
1431 void ConstantPropagator::VisitUnbox(UnboxInstr* instr) { | 1286 void ConstantPropagator::VisitUnbox(UnboxInstr* instr) { |
1432 const Object& value = instr->value()->definition()->constant_value(); | 1287 const Object& value = instr->value()->definition()->constant_value(); |
1433 if (IsNonConstant(value)) { | 1288 if (IsNonConstant(value)) { |
1434 SetValue(instr, non_constant_); | 1289 SetValue(instr, non_constant_); |
1435 } else if (IsConstant(value)) { | 1290 } else if (IsConstant(value)) { |
1436 // TODO(kmillikin): Handle conversion. | 1291 // TODO(kmillikin): Handle conversion. |
1437 SetValue(instr, non_constant_); | 1292 SetValue(instr, non_constant_); |
1438 } | 1293 } |
1439 } | 1294 } |
1440 | 1295 |
1441 | |
1442 void ConstantPropagator::VisitBox(BoxInstr* instr) { | 1296 void ConstantPropagator::VisitBox(BoxInstr* instr) { |
1443 const Object& value = instr->value()->definition()->constant_value(); | 1297 const Object& value = instr->value()->definition()->constant_value(); |
1444 if (IsNonConstant(value)) { | 1298 if (IsNonConstant(value)) { |
1445 SetValue(instr, non_constant_); | 1299 SetValue(instr, non_constant_); |
1446 } else if (IsConstant(value)) { | 1300 } else if (IsConstant(value)) { |
1447 // TODO(kmillikin): Handle conversion. | 1301 // TODO(kmillikin): Handle conversion. |
1448 SetValue(instr, non_constant_); | 1302 SetValue(instr, non_constant_); |
1449 } | 1303 } |
1450 } | 1304 } |
1451 | 1305 |
1452 | |
1453 void ConstantPropagator::VisitBoxUint32(BoxUint32Instr* instr) { | 1306 void ConstantPropagator::VisitBoxUint32(BoxUint32Instr* instr) { |
1454 // TODO(kmillikin): Handle box operation. | 1307 // TODO(kmillikin): Handle box operation. |
1455 SetValue(instr, non_constant_); | 1308 SetValue(instr, non_constant_); |
1456 } | 1309 } |
1457 | 1310 |
1458 | |
1459 void ConstantPropagator::VisitUnboxUint32(UnboxUint32Instr* instr) { | 1311 void ConstantPropagator::VisitUnboxUint32(UnboxUint32Instr* instr) { |
1460 // TODO(kmillikin): Handle unbox operation. | 1312 // TODO(kmillikin): Handle unbox operation. |
1461 SetValue(instr, non_constant_); | 1313 SetValue(instr, non_constant_); |
1462 } | 1314 } |
1463 | 1315 |
1464 | |
1465 void ConstantPropagator::VisitBoxInt32(BoxInt32Instr* instr) { | 1316 void ConstantPropagator::VisitBoxInt32(BoxInt32Instr* instr) { |
1466 // TODO(kmillikin): Handle box operation. | 1317 // TODO(kmillikin): Handle box operation. |
1467 SetValue(instr, non_constant_); | 1318 SetValue(instr, non_constant_); |
1468 } | 1319 } |
1469 | 1320 |
1470 | |
1471 void ConstantPropagator::VisitUnboxInt32(UnboxInt32Instr* instr) { | 1321 void ConstantPropagator::VisitUnboxInt32(UnboxInt32Instr* instr) { |
1472 // TODO(kmillikin): Handle unbox operation. | 1322 // TODO(kmillikin): Handle unbox operation. |
1473 SetValue(instr, non_constant_); | 1323 SetValue(instr, non_constant_); |
1474 } | 1324 } |
1475 | 1325 |
1476 | |
1477 void ConstantPropagator::VisitUnboxedIntConverter( | 1326 void ConstantPropagator::VisitUnboxedIntConverter( |
1478 UnboxedIntConverterInstr* instr) { | 1327 UnboxedIntConverterInstr* instr) { |
1479 SetValue(instr, non_constant_); | 1328 SetValue(instr, non_constant_); |
1480 } | 1329 } |
1481 | 1330 |
1482 | |
1483 void ConstantPropagator::VisitUnaryUint32Op(UnaryUint32OpInstr* instr) { | 1331 void ConstantPropagator::VisitUnaryUint32Op(UnaryUint32OpInstr* instr) { |
1484 // TODO(kmillikin): Handle unary operations. | 1332 // TODO(kmillikin): Handle unary operations. |
1485 SetValue(instr, non_constant_); | 1333 SetValue(instr, non_constant_); |
1486 } | 1334 } |
1487 | 1335 |
1488 | |
1489 void ConstantPropagator::Analyze() { | 1336 void ConstantPropagator::Analyze() { |
1490 GraphEntryInstr* entry = graph_->graph_entry(); | 1337 GraphEntryInstr* entry = graph_->graph_entry(); |
1491 reachable_->Add(entry->preorder_number()); | 1338 reachable_->Add(entry->preorder_number()); |
1492 block_worklist_.Add(entry); | 1339 block_worklist_.Add(entry); |
1493 | 1340 |
1494 while (true) { | 1341 while (true) { |
1495 if (block_worklist_.is_empty()) { | 1342 if (block_worklist_.is_empty()) { |
1496 if (definition_worklist_.IsEmpty()) break; | 1343 if (definition_worklist_.IsEmpty()) break; |
1497 Definition* definition = definition_worklist_.RemoveLast(); | 1344 Definition* definition = definition_worklist_.RemoveLast(); |
1498 Value* use = definition->input_use_list(); | 1345 Value* use = definition->input_use_list(); |
1499 while (use != NULL) { | 1346 while (use != NULL) { |
1500 use->instruction()->Accept(this); | 1347 use->instruction()->Accept(this); |
1501 use = use->next_use(); | 1348 use = use->next_use(); |
1502 } | 1349 } |
1503 } else { | 1350 } else { |
1504 BlockEntryInstr* block = block_worklist_.RemoveLast(); | 1351 BlockEntryInstr* block = block_worklist_.RemoveLast(); |
1505 block->Accept(this); | 1352 block->Accept(this); |
1506 } | 1353 } |
1507 } | 1354 } |
1508 } | 1355 } |
1509 | 1356 |
1510 | |
1511 static bool IsEmptyBlock(BlockEntryInstr* block) { | 1357 static bool IsEmptyBlock(BlockEntryInstr* block) { |
1512 return block->next()->IsGoto() && | 1358 return block->next()->IsGoto() && |
1513 (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)) && | 1359 (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)) && |
1514 !block->IsIndirectEntry(); | 1360 !block->IsIndirectEntry(); |
1515 } | 1361 } |
1516 | 1362 |
1517 | |
1518 // Traverses a chain of empty blocks and returns the first reachable non-empty | 1363 // Traverses a chain of empty blocks and returns the first reachable non-empty |
1519 // block that is not dominated by the start block. The empty blocks are added | 1364 // block that is not dominated by the start block. The empty blocks are added |
1520 // to the supplied bit vector. | 1365 // to the supplied bit vector. |
1521 static BlockEntryInstr* FindFirstNonEmptySuccessor(TargetEntryInstr* block, | 1366 static BlockEntryInstr* FindFirstNonEmptySuccessor(TargetEntryInstr* block, |
1522 BitVector* empty_blocks) { | 1367 BitVector* empty_blocks) { |
1523 BlockEntryInstr* current = block; | 1368 BlockEntryInstr* current = block; |
1524 while (IsEmptyBlock(current) && block->Dominates(current)) { | 1369 while (IsEmptyBlock(current) && block->Dominates(current)) { |
1525 ASSERT(!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)); | 1370 ASSERT(!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)); |
1526 empty_blocks->Add(current->preorder_number()); | 1371 empty_blocks->Add(current->preorder_number()); |
1527 current = current->next()->AsGoto()->successor(); | 1372 current = current->next()->AsGoto()->successor(); |
1528 } | 1373 } |
1529 return current; | 1374 return current; |
1530 } | 1375 } |
1531 | 1376 |
1532 | |
1533 void ConstantPropagator::EliminateRedundantBranches() { | 1377 void ConstantPropagator::EliminateRedundantBranches() { |
1534 // Canonicalize branches that have no side-effects and where true- and | 1378 // Canonicalize branches that have no side-effects and where true- and |
1535 // false-targets are the same. | 1379 // false-targets are the same. |
1536 bool changed = false; | 1380 bool changed = false; |
1537 BitVector* empty_blocks = new (Z) BitVector(Z, graph_->preorder().length()); | 1381 BitVector* empty_blocks = new (Z) BitVector(Z, graph_->preorder().length()); |
1538 for (BlockIterator b = graph_->postorder_iterator(); !b.Done(); b.Advance()) { | 1382 for (BlockIterator b = graph_->postorder_iterator(); !b.Done(); b.Advance()) { |
1539 BlockEntryInstr* block = b.Current(); | 1383 BlockEntryInstr* block = b.Current(); |
1540 BranchInstr* branch = block->last_instruction()->AsBranch(); | 1384 BranchInstr* branch = block->last_instruction()->AsBranch(); |
1541 empty_blocks->Clear(); | 1385 empty_blocks->Clear(); |
1542 if ((branch != NULL) && branch->Effects().IsNone()) { | 1386 if ((branch != NULL) && branch->Effects().IsNone()) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1579 } | 1423 } |
1580 | 1424 |
1581 if (changed) { | 1425 if (changed) { |
1582 graph_->DiscoverBlocks(); | 1426 graph_->DiscoverBlocks(); |
1583 // TODO(fschneider): Update dominator tree in place instead of recomputing. | 1427 // TODO(fschneider): Update dominator tree in place instead of recomputing. |
1584 GrowableArray<BitVector*> dominance_frontier; | 1428 GrowableArray<BitVector*> dominance_frontier; |
1585 graph_->ComputeDominators(&dominance_frontier); | 1429 graph_->ComputeDominators(&dominance_frontier); |
1586 } | 1430 } |
1587 } | 1431 } |
1588 | 1432 |
1589 | |
1590 void ConstantPropagator::Transform() { | 1433 void ConstantPropagator::Transform() { |
1591 if (FLAG_trace_constant_propagation && | 1434 if (FLAG_trace_constant_propagation && |
1592 FlowGraphPrinter::ShouldPrint(graph_->function())) { | 1435 FlowGraphPrinter::ShouldPrint(graph_->function())) { |
1593 FlowGraphPrinter::PrintGraph("Before CP", graph_); | 1436 FlowGraphPrinter::PrintGraph("Before CP", graph_); |
1594 } | 1437 } |
1595 | 1438 |
1596 // We will recompute dominators, block ordering, block ids, block last | 1439 // We will recompute dominators, block ordering, block ids, block last |
1597 // instructions, previous pointers, predecessors, etc. after eliminating | 1440 // instructions, previous pointers, predecessors, etc. after eliminating |
1598 // unreachable code. We do not maintain those properties during the | 1441 // unreachable code. We do not maintain those properties during the |
1599 // transformation. | 1442 // transformation. |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1734 GrowableArray<BitVector*> dominance_frontier; | 1577 GrowableArray<BitVector*> dominance_frontier; |
1735 graph_->ComputeDominators(&dominance_frontier); | 1578 graph_->ComputeDominators(&dominance_frontier); |
1736 | 1579 |
1737 if (FLAG_trace_constant_propagation && | 1580 if (FLAG_trace_constant_propagation && |
1738 FlowGraphPrinter::ShouldPrint(graph_->function())) { | 1581 FlowGraphPrinter::ShouldPrint(graph_->function())) { |
1739 FlowGraphPrinter::PrintGraph("After CP", graph_); | 1582 FlowGraphPrinter::PrintGraph("After CP", graph_); |
1740 } | 1583 } |
1741 } | 1584 } |
1742 | 1585 |
1743 } // namespace dart | 1586 } // namespace dart |
OLD | NEW |