Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(429)

Side by Side Diff: runtime/vm/flow_graph.cc

Issue 2481873005: clang-format runtime/vm (Closed)
Patch Set: Merge Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/flow_graph.h ('k') | runtime/vm/flow_graph_allocator.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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/flow_graph.h" 5 #include "vm/flow_graph.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/cha.h" 8 #include "vm/cha.h"
9 #include "vm/flow_graph_builder.h" 9 #include "vm/flow_graph_builder.h"
10 #include "vm/flow_graph_compiler.h" 10 #include "vm/flow_graph_compiler.h"
11 #include "vm/flow_graph_range_analysis.h" 11 #include "vm/flow_graph_range_analysis.h"
12 #include "vm/il_printer.h" 12 #include "vm/il_printer.h"
13 #include "vm/intermediate_language.h" 13 #include "vm/intermediate_language.h"
14 #include "vm/growable_array.h" 14 #include "vm/growable_array.h"
15 #include "vm/object_store.h" 15 #include "vm/object_store.h"
16 16
17 namespace dart { 17 namespace dart {
18 18
19 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_IA32) 19 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_IA32)
20 DEFINE_FLAG(bool, trace_smi_widening, false, "Trace Smi->Int32 widening pass."); 20 DEFINE_FLAG(bool, trace_smi_widening, false, "Trace Smi->Int32 widening pass.");
21 #endif 21 #endif
22 DEFINE_FLAG(bool, prune_dead_locals, true, "optimize dead locals away"); 22 DEFINE_FLAG(bool, prune_dead_locals, true, "optimize dead locals away");
23 DECLARE_FLAG(bool, verify_compiler); 23 DECLARE_FLAG(bool, verify_compiler);
24 24
25 25
26 FlowGraph::FlowGraph(const ParsedFunction& parsed_function, 26 FlowGraph::FlowGraph(const ParsedFunction& parsed_function,
27 GraphEntryInstr* graph_entry, 27 GraphEntryInstr* graph_entry,
28 intptr_t max_block_id) 28 intptr_t max_block_id)
29 : thread_(Thread::Current()), 29 : thread_(Thread::Current()),
30 parent_(), 30 parent_(),
31 current_ssa_temp_index_(0), 31 current_ssa_temp_index_(0),
32 max_block_id_(max_block_id), 32 max_block_id_(max_block_id),
33 parsed_function_(parsed_function), 33 parsed_function_(parsed_function),
34 num_copied_params_(parsed_function.num_copied_params()), 34 num_copied_params_(parsed_function.num_copied_params()),
35 num_non_copied_params_(parsed_function.num_non_copied_params()), 35 num_non_copied_params_(parsed_function.num_non_copied_params()),
36 graph_entry_(graph_entry), 36 graph_entry_(graph_entry),
37 preorder_(), 37 preorder_(),
38 postorder_(), 38 postorder_(),
39 reverse_postorder_(), 39 reverse_postorder_(),
40 optimized_block_order_(), 40 optimized_block_order_(),
41 constant_null_(NULL), 41 constant_null_(NULL),
42 constant_dead_(NULL), 42 constant_dead_(NULL),
43 constant_empty_context_(NULL), 43 constant_empty_context_(NULL),
44 block_effects_(NULL), 44 block_effects_(NULL),
45 licm_allowed_(true), 45 licm_allowed_(true),
46 loop_headers_(NULL), 46 loop_headers_(NULL),
47 loop_invariant_loads_(NULL), 47 loop_invariant_loads_(NULL),
48 deferred_prefixes_(parsed_function.deferred_prefixes()), 48 deferred_prefixes_(parsed_function.deferred_prefixes()),
49 captured_parameters_(new(zone()) BitVector(zone(), variable_count())), 49 captured_parameters_(new (zone()) BitVector(zone(), variable_count())),
50 inlining_id_(-1) { 50 inlining_id_(-1) {
51 DiscoverBlocks(); 51 DiscoverBlocks();
52 } 52 }
53 53
54 54
55 void FlowGraph::EnsureSSATempIndex(Definition* defn, 55 void FlowGraph::EnsureSSATempIndex(Definition* defn, Definition* replacement) {
56 Definition* replacement) { 56 if ((replacement->ssa_temp_index() == -1) && (defn->ssa_temp_index() != -1)) {
57 if ((replacement->ssa_temp_index() == -1) &&
58 (defn->ssa_temp_index() != -1)) {
59 AllocateSSAIndexes(replacement); 57 AllocateSSAIndexes(replacement);
60 } 58 }
61 } 59 }
62 60
63 61
64 void FlowGraph::ReplaceCurrentInstruction(ForwardInstructionIterator* iterator, 62 void FlowGraph::ReplaceCurrentInstruction(ForwardInstructionIterator* iterator,
65 Instruction* current, 63 Instruction* current,
66 Instruction* replacement) { 64 Instruction* replacement) {
67 Definition* current_defn = current->AsDefinition(); 65 Definition* current_defn = current->AsDefinition();
68 if ((replacement != NULL) && (current_defn != NULL)) { 66 if ((replacement != NULL) && (current_defn != NULL)) {
(...skipping 24 matching lines...) Expand all
93 } 91 }
94 } 92 }
95 iterator->RemoveCurrentFromGraph(); 93 iterator->RemoveCurrentFromGraph();
96 } 94 }
97 95
98 96
99 void FlowGraph::AddToDeferredPrefixes( 97 void FlowGraph::AddToDeferredPrefixes(
100 ZoneGrowableArray<const LibraryPrefix*>* from) { 98 ZoneGrowableArray<const LibraryPrefix*>* from) {
101 ZoneGrowableArray<const LibraryPrefix*>* to = deferred_prefixes(); 99 ZoneGrowableArray<const LibraryPrefix*>* to = deferred_prefixes();
102 for (intptr_t i = 0; i < from->length(); i++) { 100 for (intptr_t i = 0; i < from->length(); i++) {
103 const LibraryPrefix* prefix = (*from)[i]; 101 const LibraryPrefix* prefix = (*from)[i];
104 for (intptr_t j = 0; j < to->length(); j++) { 102 for (intptr_t j = 0; j < to->length(); j++) {
105 if ((*to)[j]->raw() == prefix->raw()) { 103 if ((*to)[j]->raw() == prefix->raw()) {
106 return; 104 return;
107 } 105 }
108 } 106 }
109 to->Add(prefix); 107 to->Add(prefix);
110 } 108 }
111 } 109 }
112 110
113 111
114 bool FlowGraph::ShouldReorderBlocks(const Function& function, 112 bool FlowGraph::ShouldReorderBlocks(const Function& function,
115 bool is_optimized) { 113 bool is_optimized) {
116 return is_optimized 114 return is_optimized && FLAG_reorder_basic_blocks && !function.is_intrinsic();
117 && FLAG_reorder_basic_blocks
118 && !function.is_intrinsic();
119 } 115 }
120 116
121 117
122 GrowableArray<BlockEntryInstr*>* FlowGraph::CodegenBlockOrder( 118 GrowableArray<BlockEntryInstr*>* FlowGraph::CodegenBlockOrder(
123 bool is_optimized) { 119 bool is_optimized) {
124 return ShouldReorderBlocks(function(), is_optimized) 120 return ShouldReorderBlocks(function(), is_optimized) ? &optimized_block_order_
125 ? &optimized_block_order_ 121 : &reverse_postorder_;
126 : &reverse_postorder_;
127 } 122 }
128 123
129 124
130 ConstantInstr* FlowGraph::GetConstant(const Object& object) { 125 ConstantInstr* FlowGraph::GetConstant(const Object& object) {
131 ConstantInstr* constant = constant_instr_pool_.LookupValue(object); 126 ConstantInstr* constant = constant_instr_pool_.LookupValue(object);
132 if (constant == NULL) { 127 if (constant == NULL) {
133 // Otherwise, allocate and add it to the pool. 128 // Otherwise, allocate and add it to the pool.
134 constant = new(zone()) ConstantInstr( 129 constant =
135 Object::ZoneHandle(zone(), object.raw())); 130 new (zone()) ConstantInstr(Object::ZoneHandle(zone(), object.raw()));
136 constant->set_ssa_temp_index(alloc_ssa_temp_index()); 131 constant->set_ssa_temp_index(alloc_ssa_temp_index());
137 132
138 AddToInitialDefinitions(constant); 133 AddToInitialDefinitions(constant);
139 constant_instr_pool_.Insert(constant); 134 constant_instr_pool_.Insert(constant);
140 } 135 }
141 return constant; 136 return constant;
142 } 137 }
143 138
144 139
145 void FlowGraph::AddToInitialDefinitions(Definition* defn) { 140 void FlowGraph::AddToInitialDefinitions(Definition* defn) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 } 183 }
189 return prev->AppendInstruction(instr); 184 return prev->AppendInstruction(instr);
190 } 185 }
191 186
192 187
193 // A wrapper around block entries including an index of the next successor to 188 // A wrapper around block entries including an index of the next successor to
194 // be read. 189 // be read.
195 class BlockTraversalState { 190 class BlockTraversalState {
196 public: 191 public:
197 explicit BlockTraversalState(BlockEntryInstr* block) 192 explicit BlockTraversalState(BlockEntryInstr* block)
198 : block_(block), 193 : block_(block),
199 next_successor_ix_(block->last_instruction()->SuccessorCount() - 1) { } 194 next_successor_ix_(block->last_instruction()->SuccessorCount() - 1) {}
200 195
201 bool HasNextSuccessor() const { return next_successor_ix_ >= 0; } 196 bool HasNextSuccessor() const { return next_successor_ix_ >= 0; }
202 BlockEntryInstr* NextSuccessor() { 197 BlockEntryInstr* NextSuccessor() {
203 ASSERT(HasNextSuccessor()); 198 ASSERT(HasNextSuccessor());
204 return block_->last_instruction()->SuccessorAt(next_successor_ix_--); 199 return block_->last_instruction()->SuccessorAt(next_successor_ix_--);
205 } 200 }
206 201
207 BlockEntryInstr* block() const { return block_; } 202 BlockEntryInstr* block() const { return block_; }
208 203
209 private: 204 private:
(...skipping 10 matching lines...) Expand all
220 // Initialize state. 215 // Initialize state.
221 preorder_.Clear(); 216 preorder_.Clear();
222 postorder_.Clear(); 217 postorder_.Clear();
223 reverse_postorder_.Clear(); 218 reverse_postorder_.Clear();
224 parent_.Clear(); 219 parent_.Clear();
225 220
226 GrowableArray<BlockTraversalState> block_stack; 221 GrowableArray<BlockTraversalState> block_stack;
227 graph_entry_->DiscoverBlock(NULL, &preorder_, &parent_); 222 graph_entry_->DiscoverBlock(NULL, &preorder_, &parent_);
228 block_stack.Add(BlockTraversalState(graph_entry_)); 223 block_stack.Add(BlockTraversalState(graph_entry_));
229 while (!block_stack.is_empty()) { 224 while (!block_stack.is_empty()) {
230 BlockTraversalState &state = block_stack.Last(); 225 BlockTraversalState& state = block_stack.Last();
231 BlockEntryInstr* block = state.block(); 226 BlockEntryInstr* block = state.block();
232 if (state.HasNextSuccessor()) { 227 if (state.HasNextSuccessor()) {
233 // Process successors one-by-one. 228 // Process successors one-by-one.
234 BlockEntryInstr* succ = state.NextSuccessor(); 229 BlockEntryInstr* succ = state.NextSuccessor();
235 if (succ->DiscoverBlock(block, &preorder_, &parent_)) { 230 if (succ->DiscoverBlock(block, &preorder_, &parent_)) {
236 block_stack.Add(BlockTraversalState(succ)); 231 block_stack.Add(BlockTraversalState(succ));
237 } 232 }
238 } else { 233 } else {
239 // All successors have been processed, pop the current block entry node 234 // All successors have been processed, pop the current block entry node
240 // and add it to the postorder list. 235 // and add it to the postorder list.
(...skipping 13 matching lines...) Expand all
254 249
255 // Block effects are using postorder numbering. Discard computed information. 250 // Block effects are using postorder numbering. Discard computed information.
256 block_effects_ = NULL; 251 block_effects_ = NULL;
257 loop_headers_ = NULL; 252 loop_headers_ = NULL;
258 loop_invariant_loads_ = NULL; 253 loop_invariant_loads_ = NULL;
259 } 254 }
260 255
261 256
262 void FlowGraph::MergeBlocks() { 257 void FlowGraph::MergeBlocks() {
263 bool changed = false; 258 bool changed = false;
264 BitVector* merged = new(zone()) BitVector(zone(), postorder().length()); 259 BitVector* merged = new (zone()) BitVector(zone(), postorder().length());
265 for (BlockIterator block_it = reverse_postorder_iterator(); 260 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
266 !block_it.Done();
267 block_it.Advance()) { 261 block_it.Advance()) {
268 BlockEntryInstr* block = block_it.Current(); 262 BlockEntryInstr* block = block_it.Current();
269 if (block->IsGraphEntry()) continue; 263 if (block->IsGraphEntry()) continue;
270 if (merged->Contains(block->postorder_number())) continue; 264 if (merged->Contains(block->postorder_number())) continue;
271 265
272 Instruction* last = block->last_instruction(); 266 Instruction* last = block->last_instruction();
273 BlockEntryInstr* successor = NULL; 267 BlockEntryInstr* successor = NULL;
274 while ((!last->IsIndirectGoto()) && 268 while ((!last->IsIndirectGoto()) && (last->SuccessorCount() == 1) &&
275 (last->SuccessorCount() == 1) &&
276 (!last->SuccessorAt(0)->IsIndirectEntry()) && 269 (!last->SuccessorAt(0)->IsIndirectEntry()) &&
277 (last->SuccessorAt(0)->PredecessorCount() == 1) && 270 (last->SuccessorAt(0)->PredecessorCount() == 1) &&
278 (block->try_index() == last->SuccessorAt(0)->try_index())) { 271 (block->try_index() == last->SuccessorAt(0)->try_index())) {
279 successor = last->SuccessorAt(0); 272 successor = last->SuccessorAt(0);
280 ASSERT(last->IsGoto()); 273 ASSERT(last->IsGoto());
281 274
282 // Remove environment uses and unlink goto and block entry. 275 // Remove environment uses and unlink goto and block entry.
283 successor->UnuseAllInputs(); 276 successor->UnuseAllInputs();
284 last->previous()->LinkTo(successor->next()); 277 last->previous()->LinkTo(successor->next());
285 last->UnuseAllInputs(); 278 last->UnuseAllInputs();
286 279
287 last = successor->last_instruction(); 280 last = successor->last_instruction();
288 merged->Add(successor->postorder_number()); 281 merged->Add(successor->postorder_number());
289 changed = true; 282 changed = true;
290 if (FLAG_trace_optimization) { 283 if (FLAG_trace_optimization) {
291 OS::Print("Merged blocks B%" Pd " and B%" Pd "\n", 284 OS::Print("Merged blocks B%" Pd " and B%" Pd "\n", block->block_id(),
292 block->block_id(),
293 successor->block_id()); 285 successor->block_id());
294 } 286 }
295 } 287 }
296 // The new block inherits the block id of the last successor to maintain 288 // The new block inherits the block id of the last successor to maintain
297 // the order of phi inputs at its successors consistent with block ids. 289 // the order of phi inputs at its successors consistent with block ids.
298 if (successor != NULL) { 290 if (successor != NULL) {
299 block->set_block_id(successor->block_id()); 291 block->set_block_id(successor->block_id());
300 } 292 }
301 } 293 }
302 // Recompute block order after changes were made. 294 // Recompute block order after changes were made.
(...skipping 11 matching lines...) Expand all
314 return count; 306 return count;
315 } 307 }
316 308
317 309
318 static void VerifyUseListsInInstruction(Instruction* instr) { 310 static void VerifyUseListsInInstruction(Instruction* instr) {
319 ASSERT(instr != NULL); 311 ASSERT(instr != NULL);
320 ASSERT(!instr->IsJoinEntry()); 312 ASSERT(!instr->IsJoinEntry());
321 for (intptr_t i = 0; i < instr->InputCount(); ++i) { 313 for (intptr_t i = 0; i < instr->InputCount(); ++i) {
322 Value* use = instr->InputAt(i); 314 Value* use = instr->InputAt(i);
323 ASSERT(use->definition() != NULL); 315 ASSERT(use->definition() != NULL);
324 ASSERT((use->definition() != instr) || 316 ASSERT((use->definition() != instr) || use->definition()->IsPhi() ||
325 use->definition()->IsPhi() ||
326 use->definition()->IsMaterializeObject()); 317 use->definition()->IsMaterializeObject());
327 ASSERT(use->instruction() == instr); 318 ASSERT(use->instruction() == instr);
328 ASSERT(use->use_index() == i); 319 ASSERT(use->use_index() == i);
329 ASSERT(!FLAG_verify_compiler || 320 ASSERT(!FLAG_verify_compiler ||
330 (1 == MembershipCount(use, use->definition()->input_use_list()))); 321 (1 == MembershipCount(use, use->definition()->input_use_list())));
331 } 322 }
332 if (instr->env() != NULL) { 323 if (instr->env() != NULL) {
333 intptr_t use_index = 0; 324 intptr_t use_index = 0;
334 for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) { 325 for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) {
335 Value* use = it.CurrentValue(); 326 Value* use = it.CurrentValue();
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 ASSERT(instr->IsBlockEntry() || 365 ASSERT(instr->IsBlockEntry() ||
375 (instr->IsPhi() && instr->AsPhi()->is_alive()) || 366 (instr->IsPhi() && instr->AsPhi()->is_alive()) ||
376 (instr->previous() != NULL)); 367 (instr->previous() != NULL));
377 prev = curr; 368 prev = curr;
378 curr = curr->next_use(); 369 curr = curr->next_use();
379 } 370 }
380 } 371 }
381 } 372 }
382 373
383 void FlowGraph::ComputeIsReceiverRecursive( 374 void FlowGraph::ComputeIsReceiverRecursive(
384 PhiInstr* phi, GrowableArray<PhiInstr*>* unmark) const { 375 PhiInstr* phi,
376 GrowableArray<PhiInstr*>* unmark) const {
385 if (phi->is_receiver() != PhiInstr::kUnknownReceiver) return; 377 if (phi->is_receiver() != PhiInstr::kUnknownReceiver) return;
386 phi->set_is_receiver(PhiInstr::kReceiver); 378 phi->set_is_receiver(PhiInstr::kReceiver);
387 for (intptr_t i = 0; i < phi->InputCount(); ++i) { 379 for (intptr_t i = 0; i < phi->InputCount(); ++i) {
388 Definition* def = phi->InputAt(i)->definition(); 380 Definition* def = phi->InputAt(i)->definition();
389 if (def->IsParameter() && (def->AsParameter()->index() == 0)) continue; 381 if (def->IsParameter() && (def->AsParameter()->index() == 0)) continue;
390 if (!def->IsPhi()) { 382 if (!def->IsPhi()) {
391 phi->set_is_receiver(PhiInstr::kNotReceiver); 383 phi->set_is_receiver(PhiInstr::kNotReceiver);
392 break; 384 break;
393 } 385 }
394 ComputeIsReceiverRecursive(def->AsPhi(), unmark); 386 ComputeIsReceiverRecursive(def->AsPhi(), unmark);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 bool FlowGraph::InstanceCallNeedsClassCheck(InstanceCallInstr* call, 433 bool FlowGraph::InstanceCallNeedsClassCheck(InstanceCallInstr* call,
442 RawFunction::Kind kind) const { 434 RawFunction::Kind kind) const {
443 if (!FLAG_use_cha_deopt && !isolate()->all_classes_finalized()) { 435 if (!FLAG_use_cha_deopt && !isolate()->all_classes_finalized()) {
444 // Even if class or function are private, lazy class finalization 436 // Even if class or function are private, lazy class finalization
445 // may later add overriding methods. 437 // may later add overriding methods.
446 return true; 438 return true;
447 } 439 }
448 Definition* callee_receiver = call->ArgumentAt(0); 440 Definition* callee_receiver = call->ArgumentAt(0);
449 ASSERT(callee_receiver != NULL); 441 ASSERT(callee_receiver != NULL);
450 if (function().IsDynamicFunction() && IsReceiver(callee_receiver)) { 442 if (function().IsDynamicFunction() && IsReceiver(callee_receiver)) {
451 const String& name = (kind == RawFunction::kMethodExtractor) 443 const String& name =
452 ? String::Handle(zone(), Field::NameFromGetter(call->function_name())) 444 (kind == RawFunction::kMethodExtractor)
453 : call->function_name(); 445 ? String::Handle(zone(),
446 Field::NameFromGetter(call->function_name()))
447 : call->function_name();
454 const Class& cls = Class::Handle(zone(), function().Owner()); 448 const Class& cls = Class::Handle(zone(), function().Owner());
455 intptr_t subclass_count = 0; 449 intptr_t subclass_count = 0;
456 if (!thread()->cha()->HasOverride(cls, name, &subclass_count)) { 450 if (!thread()->cha()->HasOverride(cls, name, &subclass_count)) {
457 if (FLAG_trace_cha) { 451 if (FLAG_trace_cha) {
458 THR_Print(" **(CHA) Instance call needs no check, " 452 THR_Print(
453 " **(CHA) Instance call needs no check, "
459 "no overrides of '%s' '%s'\n", 454 "no overrides of '%s' '%s'\n",
460 name.ToCString(), cls.ToCString()); 455 name.ToCString(), cls.ToCString());
461 } 456 }
462 thread()->cha()->AddToGuardedClasses(cls, subclass_count); 457 thread()->cha()->AddToGuardedClasses(cls, subclass_count);
463 return false; 458 return false;
464 } 459 }
465 } 460 }
466 return true; 461 return true;
467 } 462 }
468 463
469 464
470
471 bool FlowGraph::VerifyUseLists() { 465 bool FlowGraph::VerifyUseLists() {
472 // Verify the initial definitions. 466 // Verify the initial definitions.
473 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); ++i) { 467 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); ++i) {
474 VerifyUseListsInInstruction((*graph_entry_->initial_definitions())[i]); 468 VerifyUseListsInInstruction((*graph_entry_->initial_definitions())[i]);
475 } 469 }
476 470
477 // Verify phis in join entries and the instructions in each block. 471 // Verify phis in join entries and the instructions in each block.
478 for (intptr_t i = 0; i < preorder_.length(); ++i) { 472 for (intptr_t i = 0; i < preorder_.length(); ++i) {
479 BlockEntryInstr* entry = preorder_[i]; 473 BlockEntryInstr* entry = preorder_[i];
480 JoinEntryInstr* join = entry->AsJoinEntry(); 474 JoinEntryInstr* join = entry->AsJoinEntry();
481 if (join != NULL) { 475 if (join != NULL) {
482 for (PhiIterator it(join); !it.Done(); it.Advance()) { 476 for (PhiIterator it(join); !it.Done(); it.Advance()) {
483 PhiInstr* phi = it.Current(); 477 PhiInstr* phi = it.Current();
484 ASSERT(phi != NULL); 478 ASSERT(phi != NULL);
485 VerifyUseListsInInstruction(phi); 479 VerifyUseListsInInstruction(phi);
486 } 480 }
487 } 481 }
488 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 482 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
489 VerifyUseListsInInstruction(it.Current()); 483 VerifyUseListsInInstruction(it.Current());
490 } 484 }
491 } 485 }
492 return true; // Return true so we can ASSERT validation. 486 return true; // Return true so we can ASSERT validation.
493 } 487 }
494 488
495 489
496 LivenessAnalysis::LivenessAnalysis( 490 LivenessAnalysis::LivenessAnalysis(
497 intptr_t variable_count, 491 intptr_t variable_count,
498 const GrowableArray<BlockEntryInstr*>& postorder) 492 const GrowableArray<BlockEntryInstr*>& postorder)
499 : zone_(Thread::Current()->zone()), 493 : zone_(Thread::Current()->zone()),
500 variable_count_(variable_count), 494 variable_count_(variable_count),
501 postorder_(postorder), 495 postorder_(postorder),
502 live_out_(postorder.length()), 496 live_out_(postorder.length()),
503 kill_(postorder.length()), 497 kill_(postorder.length()),
504 live_in_(postorder.length()) { 498 live_in_(postorder.length()) {}
505 }
506 499
507 500
508 bool LivenessAnalysis::UpdateLiveOut(const BlockEntryInstr& block) { 501 bool LivenessAnalysis::UpdateLiveOut(const BlockEntryInstr& block) {
509 BitVector* live_out = live_out_[block.postorder_number()]; 502 BitVector* live_out = live_out_[block.postorder_number()];
510 bool changed = false; 503 bool changed = false;
511 Instruction* last = block.last_instruction(); 504 Instruction* last = block.last_instruction();
512 ASSERT(last != NULL); 505 ASSERT(last != NULL);
513 for (intptr_t i = 0; i < last->SuccessorCount(); i++) { 506 for (intptr_t i = 0; i < last->SuccessorCount(); i++) {
514 BlockEntryInstr* succ = last->SuccessorAt(i); 507 BlockEntryInstr* succ = last->SuccessorAt(i);
515 ASSERT(succ != NULL); 508 ASSERT(succ != NULL);
(...skipping 30 matching lines...) Expand all
546 changed = true; 539 changed = true;
547 } 540 }
548 } 541 }
549 } while (changed); 542 } while (changed);
550 } 543 }
551 544
552 545
553 void LivenessAnalysis::Analyze() { 546 void LivenessAnalysis::Analyze() {
554 const intptr_t block_count = postorder_.length(); 547 const intptr_t block_count = postorder_.length();
555 for (intptr_t i = 0; i < block_count; i++) { 548 for (intptr_t i = 0; i < block_count; i++) {
556 live_out_.Add(new(zone()) BitVector(zone(), variable_count_)); 549 live_out_.Add(new (zone()) BitVector(zone(), variable_count_));
557 kill_.Add(new(zone()) BitVector(zone(), variable_count_)); 550 kill_.Add(new (zone()) BitVector(zone(), variable_count_));
558 live_in_.Add(new(zone()) BitVector(zone(), variable_count_)); 551 live_in_.Add(new (zone()) BitVector(zone(), variable_count_));
559 } 552 }
560 553
561 ComputeInitialSets(); 554 ComputeInitialSets();
562 ComputeLiveInAndLiveOutSets(); 555 ComputeLiveInAndLiveOutSets();
563 } 556 }
564 557
565 558
566 static void PrintBitVector(const char* tag, BitVector* v) { 559 static void PrintBitVector(const char* tag, BitVector* v) {
567 OS::Print("%s:", tag); 560 OS::Print("%s:", tag);
568 for (BitVector::Iterator it(v); !it.Done(); it.Advance()) { 561 for (BitVector::Iterator it(v); !it.Done(); it.Advance()) {
(...skipping 23 matching lines...) Expand all
592 } 585 }
593 586
594 587
595 // Computes liveness information for local variables. 588 // Computes liveness information for local variables.
596 class VariableLivenessAnalysis : public LivenessAnalysis { 589 class VariableLivenessAnalysis : public LivenessAnalysis {
597 public: 590 public:
598 explicit VariableLivenessAnalysis(FlowGraph* flow_graph) 591 explicit VariableLivenessAnalysis(FlowGraph* flow_graph)
599 : LivenessAnalysis(flow_graph->variable_count(), flow_graph->postorder()), 592 : LivenessAnalysis(flow_graph->variable_count(), flow_graph->postorder()),
600 flow_graph_(flow_graph), 593 flow_graph_(flow_graph),
601 num_non_copied_params_(flow_graph->num_non_copied_params()), 594 num_non_copied_params_(flow_graph->num_non_copied_params()),
602 assigned_vars_() { } 595 assigned_vars_() {}
603 596
604 // For every block (in preorder) compute and return set of variables that 597 // For every block (in preorder) compute and return set of variables that
605 // have new assigned values flowing out of that block. 598 // have new assigned values flowing out of that block.
606 const GrowableArray<BitVector*>& ComputeAssignedVars() { 599 const GrowableArray<BitVector*>& ComputeAssignedVars() {
607 // We can't directly return kill_ because it uses postorder numbering while 600 // We can't directly return kill_ because it uses postorder numbering while
608 // SSA construction uses preorder numbering internally. 601 // SSA construction uses preorder numbering internally.
609 // We have to permute postorder into preorder. 602 // We have to permute postorder into preorder.
610 assigned_vars_.Clear(); 603 assigned_vars_.Clear();
611 604
612 const intptr_t block_count = flow_graph_->preorder().length(); 605 const intptr_t block_count = flow_graph_->preorder().length();
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 658
666 const FlowGraph* flow_graph_; 659 const FlowGraph* flow_graph_;
667 const intptr_t num_non_copied_params_; 660 const intptr_t num_non_copied_params_;
668 GrowableArray<BitVector*> assigned_vars_; 661 GrowableArray<BitVector*> assigned_vars_;
669 }; 662 };
670 663
671 664
672 void VariableLivenessAnalysis::ComputeInitialSets() { 665 void VariableLivenessAnalysis::ComputeInitialSets() {
673 const intptr_t block_count = postorder_.length(); 666 const intptr_t block_count = postorder_.length();
674 667
675 BitVector* last_loads = new(zone()) BitVector(zone(), variable_count_); 668 BitVector* last_loads = new (zone()) BitVector(zone(), variable_count_);
676 for (intptr_t i = 0; i < block_count; i++) { 669 for (intptr_t i = 0; i < block_count; i++) {
677 BlockEntryInstr* block = postorder_[i]; 670 BlockEntryInstr* block = postorder_[i];
678 671
679 BitVector* kill = kill_[i]; 672 BitVector* kill = kill_[i];
680 BitVector* live_in = live_in_[i]; 673 BitVector* live_in = live_in_[i];
681 last_loads->Clear(); 674 last_loads->Clear();
682 675
683 // There is an implicit use (load-local) of every local variable at each 676 // There is an implicit use (load-local) of every local variable at each
684 // call inside a try{} block and every call has an implicit control-flow 677 // call inside a try{} block and every call has an implicit control-flow
685 // to the catch entry. As an approximation we mark all locals as live 678 // to the catch entry. As an approximation we mark all locals as live
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
736 ASSERT((next_virtual_register_number == 0) || (inlining_parameters != NULL)); 729 ASSERT((next_virtual_register_number == 0) || (inlining_parameters != NULL));
737 current_ssa_temp_index_ = next_virtual_register_number; 730 current_ssa_temp_index_ = next_virtual_register_number;
738 GrowableArray<BitVector*> dominance_frontier; 731 GrowableArray<BitVector*> dominance_frontier;
739 ComputeDominators(&dominance_frontier); 732 ComputeDominators(&dominance_frontier);
740 733
741 VariableLivenessAnalysis variable_liveness(this); 734 VariableLivenessAnalysis variable_liveness(this);
742 variable_liveness.Analyze(); 735 variable_liveness.Analyze();
743 736
744 GrowableArray<PhiInstr*> live_phis; 737 GrowableArray<PhiInstr*> live_phis;
745 738
746 InsertPhis(preorder_, 739 InsertPhis(preorder_, variable_liveness.ComputeAssignedVars(),
747 variable_liveness.ComputeAssignedVars(), 740 dominance_frontier, &live_phis);
748 dominance_frontier,
749 &live_phis);
750 741
751 742
752 // Rename uses to reference inserted phis where appropriate. 743 // Rename uses to reference inserted phis where appropriate.
753 // Collect phis that reach a non-environment use. 744 // Collect phis that reach a non-environment use.
754 Rename(&live_phis, &variable_liveness, inlining_parameters); 745 Rename(&live_phis, &variable_liveness, inlining_parameters);
755 746
756 // Propagate alive mark transitively from alive phis and then remove 747 // Propagate alive mark transitively from alive phis and then remove
757 // non-live ones. 748 // non-live ones.
758 RemoveDeadPhis(&live_phis); 749 RemoveDeadPhis(&live_phis);
759 } 750 }
(...skipping 13 matching lines...) Expand all
773 // that eliminates a pass by using nearest-common ancestor (NCA) to 764 // that eliminates a pass by using nearest-common ancestor (NCA) to
774 // compute immediate dominators from semidominators. It also removes a 765 // compute immediate dominators from semidominators. It also removes a
775 // level of indirection in the link-eval forest data structure. 766 // level of indirection in the link-eval forest data structure.
776 // 767 //
777 // The algorithm is described in Georgiadis, Tarjan, and Werneck's 768 // The algorithm is described in Georgiadis, Tarjan, and Werneck's
778 // "Finding Dominators in Practice". 769 // "Finding Dominators in Practice".
779 // See http://www.cs.princeton.edu/~rwerneck/dominators/ . 770 // See http://www.cs.princeton.edu/~rwerneck/dominators/ .
780 771
781 // All arrays are maps between preorder basic-block numbers. 772 // All arrays are maps between preorder basic-block numbers.
782 intptr_t size = parent_.length(); 773 intptr_t size = parent_.length();
783 GrowableArray<intptr_t> idom(size); // Immediate dominator. 774 GrowableArray<intptr_t> idom(size); // Immediate dominator.
784 GrowableArray<intptr_t> semi(size); // Semidominator. 775 GrowableArray<intptr_t> semi(size); // Semidominator.
785 GrowableArray<intptr_t> label(size); // Label for link-eval forest. 776 GrowableArray<intptr_t> label(size); // Label for link-eval forest.
786 777
787 // 1. First pass: compute semidominators as in Lengauer-Tarjan. 778 // 1. First pass: compute semidominators as in Lengauer-Tarjan.
788 // Semidominators are computed from a depth-first spanning tree and are an 779 // Semidominators are computed from a depth-first spanning tree and are an
789 // approximation of immediate dominators. 780 // approximation of immediate dominators.
790 781
791 // Use a link-eval data structure with path compression. Implement path 782 // Use a link-eval data structure with path compression. Implement path
792 // compression in place by mutating the parent array. Each block has a 783 // compression in place by mutating the parent array. Each block has a
793 // label, which is the minimum block number on the compressed path. 784 // label, which is the minimum block number on the compressed path.
794 785
795 // Initialize idom, semi, and label used by SEMI-NCA. Initialize the 786 // Initialize idom, semi, and label used by SEMI-NCA. Initialize the
796 // dominance frontier output array. 787 // dominance frontier output array.
797 for (intptr_t i = 0; i < size; ++i) { 788 for (intptr_t i = 0; i < size; ++i) {
798 idom.Add(parent_[i]); 789 idom.Add(parent_[i]);
799 semi.Add(i); 790 semi.Add(i);
800 label.Add(i); 791 label.Add(i);
801 dominance_frontier->Add(new(zone()) BitVector(zone(), size)); 792 dominance_frontier->Add(new (zone()) BitVector(zone(), size));
802 } 793 }
803 794
804 // Loop over the blocks in reverse preorder (not including the graph 795 // Loop over the blocks in reverse preorder (not including the graph
805 // entry). Clear the dominated blocks in the graph entry in case 796 // entry). Clear the dominated blocks in the graph entry in case
806 // ComputeDominators is used to recompute them. 797 // ComputeDominators is used to recompute them.
807 preorder_[0]->ClearDominatedBlocks(); 798 preorder_[0]->ClearDominatedBlocks();
808 for (intptr_t block_index = size - 1; block_index >= 1; --block_index) { 799 for (intptr_t block_index = size - 1; block_index >= 1; --block_index) {
809 // Loop over the predecessors. 800 // Loop over the predecessors.
810 BlockEntryInstr* block = preorder_[block_index]; 801 BlockEntryInstr* block = preorder_[block_index];
811 // Clear the immediately dominated blocks in case ComputeDominators is 802 // Clear the immediately dominated blocks in case ComputeDominators is
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 intptr_t next_index = (*parent)[current_index]; 861 intptr_t next_index = (*parent)[current_index];
871 if (next_index > start_index) { 862 if (next_index > start_index) {
872 CompressPath(start_index, next_index, parent, label); 863 CompressPath(start_index, next_index, parent, label);
873 (*label)[current_index] = 864 (*label)[current_index] =
874 Utils::Minimum((*label)[current_index], (*label)[next_index]); 865 Utils::Minimum((*label)[current_index], (*label)[next_index]);
875 (*parent)[current_index] = (*parent)[next_index]; 866 (*parent)[current_index] = (*parent)[next_index];
876 } 867 }
877 } 868 }
878 869
879 870
880 void FlowGraph::InsertPhis( 871 void FlowGraph::InsertPhis(const GrowableArray<BlockEntryInstr*>& preorder,
881 const GrowableArray<BlockEntryInstr*>& preorder, 872 const GrowableArray<BitVector*>& assigned_vars,
882 const GrowableArray<BitVector*>& assigned_vars, 873 const GrowableArray<BitVector*>& dom_frontier,
883 const GrowableArray<BitVector*>& dom_frontier, 874 GrowableArray<PhiInstr*>* live_phis) {
884 GrowableArray<PhiInstr*>* live_phis) {
885 const intptr_t block_count = preorder.length(); 875 const intptr_t block_count = preorder.length();
886 // Map preorder block number to the highest variable index that has a phi 876 // Map preorder block number to the highest variable index that has a phi
887 // in that block. Use it to avoid inserting multiple phis for the same 877 // in that block. Use it to avoid inserting multiple phis for the same
888 // variable. 878 // variable.
889 GrowableArray<intptr_t> has_already(block_count); 879 GrowableArray<intptr_t> has_already(block_count);
890 // Map preorder block number to the highest variable index for which the 880 // Map preorder block number to the highest variable index for which the
891 // block went on the worklist. Use it to avoid adding the same block to 881 // block went on the worklist. Use it to avoid adding the same block to
892 // the worklist more than once for the same variable. 882 // the worklist more than once for the same variable.
893 GrowableArray<intptr_t> work(block_count); 883 GrowableArray<intptr_t> work(block_count);
894 884
895 // Initialize has_already and work. 885 // Initialize has_already and work.
896 for (intptr_t block_index = 0; block_index < block_count; ++block_index) { 886 for (intptr_t block_index = 0; block_index < block_count; ++block_index) {
897 has_already.Add(-1); 887 has_already.Add(-1);
898 work.Add(-1); 888 work.Add(-1);
899 } 889 }
900 890
901 // Insert phis for each variable in turn. 891 // Insert phis for each variable in turn.
902 GrowableArray<BlockEntryInstr*> worklist; 892 GrowableArray<BlockEntryInstr*> worklist;
903 for (intptr_t var_index = 0; var_index < variable_count(); ++var_index) { 893 for (intptr_t var_index = 0; var_index < variable_count(); ++var_index) {
904 const bool always_live = !FLAG_prune_dead_locals || 894 const bool always_live =
905 (var_index == CurrentContextEnvIndex()); 895 !FLAG_prune_dead_locals || (var_index == CurrentContextEnvIndex());
906 // Add to the worklist each block containing an assignment. 896 // Add to the worklist each block containing an assignment.
907 for (intptr_t block_index = 0; block_index < block_count; ++block_index) { 897 for (intptr_t block_index = 0; block_index < block_count; ++block_index) {
908 if (assigned_vars[block_index]->Contains(var_index)) { 898 if (assigned_vars[block_index]->Contains(var_index)) {
909 work[block_index] = var_index; 899 work[block_index] = var_index;
910 worklist.Add(preorder[block_index]); 900 worklist.Add(preorder[block_index]);
911 } 901 }
912 } 902 }
913 903
914 while (!worklist.is_empty()) { 904 while (!worklist.is_empty()) {
915 BlockEntryInstr* current = worklist.RemoveLast(); 905 BlockEntryInstr* current = worklist.RemoveLast();
916 // Ensure a phi for each block in the dominance frontier of current. 906 // Ensure a phi for each block in the dominance frontier of current.
917 for (BitVector::Iterator it(dom_frontier[current->preorder_number()]); 907 for (BitVector::Iterator it(dom_frontier[current->preorder_number()]);
918 !it.Done(); 908 !it.Done(); it.Advance()) {
919 it.Advance()) {
920 int index = it.Current(); 909 int index = it.Current();
921 if (has_already[index] < var_index) { 910 if (has_already[index] < var_index) {
922 BlockEntryInstr* block = preorder[index]; 911 BlockEntryInstr* block = preorder[index];
923 ASSERT(block->IsJoinEntry()); 912 ASSERT(block->IsJoinEntry());
924 PhiInstr* phi = block->AsJoinEntry()->InsertPhi(var_index, 913 PhiInstr* phi =
925 variable_count()); 914 block->AsJoinEntry()->InsertPhi(var_index, variable_count());
926 if (always_live) { 915 if (always_live) {
927 phi->mark_alive(); 916 phi->mark_alive();
928 live_phis->Add(phi); 917 live_phis->Add(phi);
929 } 918 }
930 has_already[index] = var_index; 919 has_already[index] = var_index;
931 if (work[index] < var_index) { 920 if (work[index] < var_index) {
932 work[index] = var_index; 921 work[index] = var_index;
933 worklist.Add(block); 922 worklist.Add(block);
934 } 923 }
935 } 924 }
936 } 925 }
937 } 926 }
938 } 927 }
939 } 928 }
940 929
941 930
942 void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis, 931 void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis,
943 VariableLivenessAnalysis* variable_liveness, 932 VariableLivenessAnalysis* variable_liveness,
944 ZoneGrowableArray<Definition*>* inlining_parameters) { 933 ZoneGrowableArray<Definition*>* inlining_parameters) {
945 GraphEntryInstr* entry = graph_entry(); 934 GraphEntryInstr* entry = graph_entry();
946 935
947 // Initial renaming environment. 936 // Initial renaming environment.
948 GrowableArray<Definition*> env(variable_count()); 937 GrowableArray<Definition*> env(variable_count());
949 938
950 // Add global constants to the initial definitions. 939 // Add global constants to the initial definitions.
951 constant_null_ = GetConstant(Object::ZoneHandle()); 940 constant_null_ = GetConstant(Object::ZoneHandle());
952 constant_dead_ = GetConstant(Symbols::OptimizedOut()); 941 constant_dead_ = GetConstant(Symbols::OptimizedOut());
953 constant_empty_context_ = GetConstant(Context::Handle( 942 constant_empty_context_ =
954 isolate()->object_store()->empty_context())); 943 GetConstant(Context::Handle(isolate()->object_store()->empty_context()));
955 944
956 // Add parameters to the initial definitions and renaming environment. 945 // Add parameters to the initial definitions and renaming environment.
957 if (inlining_parameters != NULL) { 946 if (inlining_parameters != NULL) {
958 // Use known parameters. 947 // Use known parameters.
959 ASSERT(parameter_count() == inlining_parameters->length()); 948 ASSERT(parameter_count() == inlining_parameters->length());
960 for (intptr_t i = 0; i < parameter_count(); ++i) { 949 for (intptr_t i = 0; i < parameter_count(); ++i) {
961 Definition* defn = (*inlining_parameters)[i]; 950 Definition* defn = (*inlining_parameters)[i];
962 AllocateSSAIndexes(defn); 951 AllocateSSAIndexes(defn);
963 AddToInitialDefinitions(defn); 952 AddToInitialDefinitions(defn);
964 env.Add(defn); 953 env.Add(defn);
965 } 954 }
966 } else { 955 } else {
967 // Create new parameters. For functions compiled for OSR, the locals 956 // Create new parameters. For functions compiled for OSR, the locals
968 // are unknown and so treated like parameters. 957 // are unknown and so treated like parameters.
969 intptr_t count = IsCompiledForOsr() ? variable_count() : parameter_count(); 958 intptr_t count = IsCompiledForOsr() ? variable_count() : parameter_count();
970 for (intptr_t i = 0; i < count; ++i) { 959 for (intptr_t i = 0; i < count; ++i) {
971 ParameterInstr* param = new(zone()) ParameterInstr(i, entry); 960 ParameterInstr* param = new (zone()) ParameterInstr(i, entry);
972 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. 961 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp.
973 AddToInitialDefinitions(param); 962 AddToInitialDefinitions(param);
974 env.Add(param); 963 env.Add(param);
975 } 964 }
976 } 965 }
977 966
978 // Initialize all locals in the renaming environment For OSR, the locals have 967 // Initialize all locals in the renaming environment For OSR, the locals have
979 // already been handled as parameters. 968 // already been handled as parameters.
980 if (!IsCompiledForOsr()) { 969 if (!IsCompiledForOsr()) {
981 for (intptr_t i = parameter_count(); i < variable_count(); ++i) { 970 for (intptr_t i = parameter_count(); i < variable_count(); ++i) {
(...skipping 18 matching lines...) Expand all
1000 // on entry to the catch. 989 // on entry to the catch.
1001 entry->set_fixed_slot_count(num_stack_locals() + num_copied_params()); 990 entry->set_fixed_slot_count(num_stack_locals() + num_copied_params());
1002 } 991 }
1003 RenameRecursive(entry, &env, live_phis, variable_liveness); 992 RenameRecursive(entry, &env, live_phis, variable_liveness);
1004 } 993 }
1005 994
1006 995
1007 void FlowGraph::AttachEnvironment(Instruction* instr, 996 void FlowGraph::AttachEnvironment(Instruction* instr,
1008 GrowableArray<Definition*>* env) { 997 GrowableArray<Definition*>* env) {
1009 Environment* deopt_env = 998 Environment* deopt_env =
1010 Environment::From(zone(), 999 Environment::From(zone(), *env, num_non_copied_params_, parsed_function_);
1011 *env,
1012 num_non_copied_params_,
1013 parsed_function_);
1014 if (instr->IsClosureCall()) { 1000 if (instr->IsClosureCall()) {
1015 deopt_env = deopt_env->DeepCopy(zone(), 1001 deopt_env =
1016 deopt_env->Length() - instr->InputCount()); 1002 deopt_env->DeepCopy(zone(), deopt_env->Length() - instr->InputCount());
1017 } 1003 }
1018 instr->SetEnvironment(deopt_env); 1004 instr->SetEnvironment(deopt_env);
1019 for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) { 1005 for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) {
1020 Value* use = it.CurrentValue(); 1006 Value* use = it.CurrentValue();
1021 use->definition()->AddEnvUse(use); 1007 use->definition()->AddEnvUse(use);
1022 } 1008 }
1023 if (instr->CanDeoptimize()) { 1009 if (instr->CanDeoptimize()) {
1024 instr->env()->set_deopt_id(instr->deopt_id()); 1010 instr->env()->set_deopt_id(instr->deopt_id());
1025 } 1011 }
1026 } 1012 }
(...skipping 20 matching lines...) Expand all
1047 // more redundant phis. 1033 // more redundant phis.
1048 phi->mark_alive(); 1034 phi->mark_alive();
1049 live_phis->Add(phi); 1035 live_phis->Add(phi);
1050 } 1036 }
1051 } 1037 }
1052 } 1038 }
1053 } 1039 }
1054 } else if (block_entry->IsCatchBlockEntry()) { 1040 } else if (block_entry->IsCatchBlockEntry()) {
1055 // Add real definitions for all locals and parameters. 1041 // Add real definitions for all locals and parameters.
1056 for (intptr_t i = 0; i < env->length(); ++i) { 1042 for (intptr_t i = 0; i < env->length(); ++i) {
1057 ParameterInstr* param = new(zone()) ParameterInstr(i, block_entry); 1043 ParameterInstr* param = new (zone()) ParameterInstr(i, block_entry);
1058 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. 1044 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp.
1059 (*env)[i] = param; 1045 (*env)[i] = param;
1060 block_entry->AsCatchBlockEntry()->initial_definitions()->Add(param); 1046 block_entry->AsCatchBlockEntry()->initial_definitions()->Add(param);
1061 } 1047 }
1062 } 1048 }
1063 1049
1064 // Prune non-live variables at block entry by replacing their environment 1050 // Prune non-live variables at block entry by replacing their environment
1065 // slots with null. 1051 // slots with null.
1066 BitVector* live_in = variable_liveness->GetLiveInSet(block_entry); 1052 BitVector* live_in = variable_liveness->GetLiveInSet(block_entry);
1067 for (intptr_t i = 0; i < variable_count(); i++) { 1053 for (intptr_t i = 0; i < variable_count(); i++) {
1068 // TODO(fschneider): Make sure that live_in always contains the 1054 // TODO(fschneider): Make sure that live_in always contains the
1069 // CurrentContext variable to avoid the special case here. 1055 // CurrentContext variable to avoid the special case here.
1070 if (FLAG_prune_dead_locals && 1056 if (FLAG_prune_dead_locals && !live_in->Contains(i) &&
1071 !live_in->Contains(i) &&
1072 (i != CurrentContextEnvIndex())) { 1057 (i != CurrentContextEnvIndex())) {
1073 (*env)[i] = constant_dead(); 1058 (*env)[i] = constant_dead();
1074 } 1059 }
1075 } 1060 }
1076 1061
1077 // Attach environment to the block entry. 1062 // Attach environment to the block entry.
1078 AttachEnvironment(block_entry, env); 1063 AttachEnvironment(block_entry, env);
1079 1064
1080 // 2. Process normal instructions. 1065 // 2. Process normal instructions.
1081 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) { 1066 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) {
(...skipping 10 matching lines...) Expand all
1092 // For each use of a LoadLocal, StoreLocal, DropTemps or Constant: Replace 1077 // For each use of a LoadLocal, StoreLocal, DropTemps or Constant: Replace
1093 // it with the renamed value. 1078 // it with the renamed value.
1094 for (intptr_t i = current->InputCount() - 1; i >= 0; --i) { 1079 for (intptr_t i = current->InputCount() - 1; i >= 0; --i) {
1095 Value* v = current->InputAt(i); 1080 Value* v = current->InputAt(i);
1096 // Update expression stack. 1081 // Update expression stack.
1097 ASSERT(env->length() > variable_count()); 1082 ASSERT(env->length() > variable_count());
1098 1083
1099 Definition* reaching_defn = env->RemoveLast(); 1084 Definition* reaching_defn = env->RemoveLast();
1100 Definition* input_defn = v->definition(); 1085 Definition* input_defn = v->definition();
1101 if (input_defn != reaching_defn) { 1086 if (input_defn != reaching_defn) {
1102 ASSERT(input_defn->IsLoadLocal() || 1087 ASSERT(input_defn->IsLoadLocal() || input_defn->IsStoreLocal() ||
1103 input_defn->IsStoreLocal() || 1088 input_defn->IsDropTemps() || input_defn->IsConstant());
1104 input_defn->IsDropTemps() ||
1105 input_defn->IsConstant());
1106 // Assert we are not referencing nulls in the initial environment. 1089 // Assert we are not referencing nulls in the initial environment.
1107 ASSERT(reaching_defn->ssa_temp_index() != -1); 1090 ASSERT(reaching_defn->ssa_temp_index() != -1);
1108 v->set_definition(reaching_defn); 1091 v->set_definition(reaching_defn);
1109 input_defn = reaching_defn; 1092 input_defn = reaching_defn;
1110 } 1093 }
1111 input_defn->AddInputUse(v); 1094 input_defn->AddInputUse(v);
1112 } 1095 }
1113 1096
1114 // Drop pushed arguments for calls. 1097 // Drop pushed arguments for calls.
1115 for (intptr_t j = 0; j < current->ArgumentCount(); j++) { 1098 for (intptr_t j = 0; j < current->ArgumentCount(); j++) {
1116 env->RemoveLast(); 1099 env->RemoveLast();
1117 } 1100 }
1118 1101
1119 // 2b. Handle LoadLocal, StoreLocal, DropTemps and Constant. 1102 // 2b. Handle LoadLocal, StoreLocal, DropTemps and Constant.
1120 Definition* definition = current->AsDefinition(); 1103 Definition* definition = current->AsDefinition();
1121 if (definition != NULL) { 1104 if (definition != NULL) {
1122 LoadLocalInstr* load = definition->AsLoadLocal(); 1105 LoadLocalInstr* load = definition->AsLoadLocal();
1123 StoreLocalInstr* store = definition->AsStoreLocal(); 1106 StoreLocalInstr* store = definition->AsStoreLocal();
1124 DropTempsInstr* drop = definition->AsDropTemps(); 1107 DropTempsInstr* drop = definition->AsDropTemps();
1125 ConstantInstr* constant = definition->AsConstant(); 1108 ConstantInstr* constant = definition->AsConstant();
1126 if ((load != NULL) || 1109 if ((load != NULL) || (store != NULL) || (drop != NULL) ||
1127 (store != NULL) ||
1128 (drop != NULL) ||
1129 (constant != NULL)) { 1110 (constant != NULL)) {
1130 Definition* result = NULL; 1111 Definition* result = NULL;
1131 if (store != NULL) { 1112 if (store != NULL) {
1132 // Update renaming environment. 1113 // Update renaming environment.
1133 intptr_t index = store->local().BitIndexIn(num_non_copied_params_); 1114 intptr_t index = store->local().BitIndexIn(num_non_copied_params_);
1134 result = store->value()->definition(); 1115 result = store->value()->definition();
1135 1116
1136 if (!FLAG_prune_dead_locals || 1117 if (!FLAG_prune_dead_locals ||
1137 variable_liveness->IsStoreAlive(block_entry, store)) { 1118 variable_liveness->IsStoreAlive(block_entry, store)) {
1138 (*env)[index] = result; 1119 (*env)[index] = result;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1213 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) { 1194 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) {
1214 JoinEntryInstr* successor = 1195 JoinEntryInstr* successor =
1215 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry(); 1196 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry();
1216 intptr_t pred_index = successor->IndexOfPredecessor(block_entry); 1197 intptr_t pred_index = successor->IndexOfPredecessor(block_entry);
1217 ASSERT(pred_index >= 0); 1198 ASSERT(pred_index >= 0);
1218 if (successor->phis() != NULL) { 1199 if (successor->phis() != NULL) {
1219 for (intptr_t i = 0; i < successor->phis()->length(); ++i) { 1200 for (intptr_t i = 0; i < successor->phis()->length(); ++i) {
1220 PhiInstr* phi = (*successor->phis())[i]; 1201 PhiInstr* phi = (*successor->phis())[i];
1221 if (phi != NULL) { 1202 if (phi != NULL) {
1222 // Rename input operand. 1203 // Rename input operand.
1223 Value* use = new(zone()) Value((*env)[i]); 1204 Value* use = new (zone()) Value((*env)[i]);
1224 phi->SetInputAt(pred_index, use); 1205 phi->SetInputAt(pred_index, use);
1225 } 1206 }
1226 } 1207 }
1227 } 1208 }
1228 } 1209 }
1229 } 1210 }
1230 1211
1231 1212
1232 void FlowGraph::RemoveDeadPhis(GrowableArray<PhiInstr*>* live_phis) { 1213 void FlowGraph::RemoveDeadPhis(GrowableArray<PhiInstr*>* live_phis) {
1233 // Augment live_phis with those that have implicit real used at 1214 // Augment live_phis with those that have implicit real used at
1234 // potentially throwing instructions if there is a try-catch in this graph. 1215 // potentially throwing instructions if there is a try-catch in this graph.
1235 if (graph_entry()->SuccessorCount() > 1) { 1216 if (graph_entry()->SuccessorCount() > 1) {
1236 for (BlockIterator it(postorder_iterator()); !it.Done(); it.Advance()) { 1217 for (BlockIterator it(postorder_iterator()); !it.Done(); it.Advance()) {
1237 JoinEntryInstr* join = it.Current()->AsJoinEntry(); 1218 JoinEntryInstr* join = it.Current()->AsJoinEntry();
1238 if (join == NULL) continue; 1219 if (join == NULL) continue;
1239 for (PhiIterator phi_it(join); !phi_it.Done(); phi_it.Advance()) { 1220 for (PhiIterator phi_it(join); !phi_it.Done(); phi_it.Advance()) {
1240 PhiInstr* phi = phi_it.Current(); 1221 PhiInstr* phi = phi_it.Current();
1241 if (phi == NULL || 1222 if (phi == NULL || phi->is_alive() || (phi->input_use_list() != NULL) ||
1242 phi->is_alive() ||
1243 (phi->input_use_list() != NULL) ||
1244 (phi->env_use_list() == NULL)) { 1223 (phi->env_use_list() == NULL)) {
1245 continue; 1224 continue;
1246 } 1225 }
1247 for (Value::Iterator it(phi->env_use_list()); 1226 for (Value::Iterator it(phi->env_use_list()); !it.Done();
1248 !it.Done();
1249 it.Advance()) { 1227 it.Advance()) {
1250 Value* use = it.Current(); 1228 Value* use = it.Current();
1251 if (use->instruction()->MayThrow() && 1229 if (use->instruction()->MayThrow() &&
1252 use->instruction()->GetBlock()->InsideTryBlock()) { 1230 use->instruction()->GetBlock()->InsideTryBlock()) {
1253 live_phis->Add(phi); 1231 live_phis->Add(phi);
1254 phi->mark_alive(); 1232 phi->mark_alive();
1255 break; 1233 break;
1256 } 1234 }
1257 } 1235 }
1258 } 1236 }
(...skipping 14 matching lines...) Expand all
1273 1251
1274 for (BlockIterator it(postorder_iterator()); !it.Done(); it.Advance()) { 1252 for (BlockIterator it(postorder_iterator()); !it.Done(); it.Advance()) {
1275 JoinEntryInstr* join = it.Current()->AsJoinEntry(); 1253 JoinEntryInstr* join = it.Current()->AsJoinEntry();
1276 if (join != NULL) join->RemoveDeadPhis(constant_dead()); 1254 if (join != NULL) join->RemoveDeadPhis(constant_dead());
1277 } 1255 }
1278 } 1256 }
1279 1257
1280 1258
1281 void FlowGraph::RemoveRedefinitions() { 1259 void FlowGraph::RemoveRedefinitions() {
1282 // Remove redefinition instructions inserted to inhibit hoisting. 1260 // Remove redefinition instructions inserted to inhibit hoisting.
1283 for (BlockIterator block_it = reverse_postorder_iterator(); 1261 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
1284 !block_it.Done();
1285 block_it.Advance()) { 1262 block_it.Advance()) {
1286 for (ForwardInstructionIterator instr_it(block_it.Current()); 1263 for (ForwardInstructionIterator instr_it(block_it.Current());
1287 !instr_it.Done(); 1264 !instr_it.Done(); instr_it.Advance()) {
1288 instr_it.Advance()) {
1289 RedefinitionInstr* redefinition = instr_it.Current()->AsRedefinition(); 1265 RedefinitionInstr* redefinition = instr_it.Current()->AsRedefinition();
1290 if (redefinition != NULL) { 1266 if (redefinition != NULL) {
1291 Definition* original; 1267 Definition* original;
1292 do { 1268 do {
1293 original = redefinition->value()->definition(); 1269 original = redefinition->value()->definition();
1294 } while (original->IsRedefinition()); 1270 } while (original->IsRedefinition());
1295 redefinition->ReplaceUsesWith(original); 1271 redefinition->ReplaceUsesWith(original);
1296 instr_it.RemoveCurrentFromGraph(); 1272 instr_it.RemoveCurrentFromGraph();
1297 } 1273 }
1298 } 1274 }
1299 } 1275 }
1300 } 1276 }
1301 1277
1302 1278
1303 // Find the natural loop for the back edge m->n and attach loop information 1279 // Find the natural loop for the back edge m->n and attach loop information
1304 // to block n (loop header). The algorithm is described in "Advanced Compiler 1280 // to block n (loop header). The algorithm is described in "Advanced Compiler
1305 // Design & Implementation" (Muchnick) p192. 1281 // Design & Implementation" (Muchnick) p192.
1306 BitVector* FlowGraph::FindLoop(BlockEntryInstr* m, BlockEntryInstr* n) const { 1282 BitVector* FlowGraph::FindLoop(BlockEntryInstr* m, BlockEntryInstr* n) const {
1307 GrowableArray<BlockEntryInstr*> stack; 1283 GrowableArray<BlockEntryInstr*> stack;
1308 BitVector* loop = new(zone()) BitVector(zone(), preorder_.length()); 1284 BitVector* loop = new (zone()) BitVector(zone(), preorder_.length());
1309 1285
1310 loop->Add(n->preorder_number()); 1286 loop->Add(n->preorder_number());
1311 if (n != m) { 1287 if (n != m) {
1312 loop->Add(m->preorder_number()); 1288 loop->Add(m->preorder_number());
1313 stack.Add(m); 1289 stack.Add(m);
1314 } 1290 }
1315 1291
1316 while (!stack.is_empty()) { 1292 while (!stack.is_empty()) {
1317 BlockEntryInstr* p = stack.RemoveLast(); 1293 BlockEntryInstr* p = stack.RemoveLast();
1318 for (intptr_t i = 0; i < p->PredecessorCount(); ++i) { 1294 for (intptr_t i = 0; i < p->PredecessorCount(); ++i) {
1319 BlockEntryInstr* q = p->PredecessorAt(i); 1295 BlockEntryInstr* q = p->PredecessorAt(i);
1320 if (!loop->Contains(q->preorder_number())) { 1296 if (!loop->Contains(q->preorder_number())) {
1321 loop->Add(q->preorder_number()); 1297 loop->Add(q->preorder_number());
1322 stack.Add(q); 1298 stack.Add(q);
1323 } 1299 }
1324 } 1300 }
1325 } 1301 }
1326 return loop; 1302 return loop;
1327 } 1303 }
1328 1304
1329 1305
1330 ZoneGrowableArray<BlockEntryInstr*>* FlowGraph::ComputeLoops() const { 1306 ZoneGrowableArray<BlockEntryInstr*>* FlowGraph::ComputeLoops() const {
1331 ZoneGrowableArray<BlockEntryInstr*>* loop_headers = 1307 ZoneGrowableArray<BlockEntryInstr*>* loop_headers =
1332 new(zone()) ZoneGrowableArray<BlockEntryInstr*>(); 1308 new (zone()) ZoneGrowableArray<BlockEntryInstr*>();
1333 1309
1334 for (BlockIterator it = postorder_iterator(); 1310 for (BlockIterator it = postorder_iterator(); !it.Done(); it.Advance()) {
1335 !it.Done();
1336 it.Advance()) {
1337 BlockEntryInstr* block = it.Current(); 1311 BlockEntryInstr* block = it.Current();
1338 for (intptr_t i = 0; i < block->PredecessorCount(); ++i) { 1312 for (intptr_t i = 0; i < block->PredecessorCount(); ++i) {
1339 BlockEntryInstr* pred = block->PredecessorAt(i); 1313 BlockEntryInstr* pred = block->PredecessorAt(i);
1340 if (block->Dominates(pred)) { 1314 if (block->Dominates(pred)) {
1341 if (FLAG_trace_optimization) { 1315 if (FLAG_trace_optimization) {
1342 OS::Print("Back edge B%" Pd " -> B%" Pd "\n", pred->block_id(), 1316 OS::Print("Back edge B%" Pd " -> B%" Pd "\n", pred->block_id(),
1343 block->block_id()); 1317 block->block_id());
1344 } 1318 }
1345 BitVector* loop_info = FindLoop(pred, block); 1319 BitVector* loop_info = FindLoop(pred, block);
1346 // Loops that share the same loop header are treated as one loop. 1320 // Loops that share the same loop header are treated as one loop.
(...skipping 10 matching lines...) Expand all
1357 block->set_loop_info(loop_info); 1331 block->set_loop_info(loop_info);
1358 loop_headers->Add(block); 1332 loop_headers->Add(block);
1359 } 1333 }
1360 } 1334 }
1361 } 1335 }
1362 } 1336 }
1363 if (FLAG_trace_optimization) { 1337 if (FLAG_trace_optimization) {
1364 for (intptr_t i = 0; i < loop_headers->length(); ++i) { 1338 for (intptr_t i = 0; i < loop_headers->length(); ++i) {
1365 BlockEntryInstr* header = (*loop_headers)[i]; 1339 BlockEntryInstr* header = (*loop_headers)[i];
1366 OS::Print("Loop header B%" Pd "\n", header->block_id()); 1340 OS::Print("Loop header B%" Pd "\n", header->block_id());
1367 for (BitVector::Iterator it(header->loop_info()); 1341 for (BitVector::Iterator it(header->loop_info()); !it.Done();
1368 !it.Done();
1369 it.Advance()) { 1342 it.Advance()) {
1370 OS::Print(" B%" Pd "\n", preorder_[it.Current()]->block_id()); 1343 OS::Print(" B%" Pd "\n", preorder_[it.Current()]->block_id());
1371 } 1344 }
1372 } 1345 }
1373 } 1346 }
1374 return loop_headers; 1347 return loop_headers;
1375 } 1348 }
1376 1349
1377 1350
1378 intptr_t FlowGraph::InstructionCount() const { 1351 intptr_t FlowGraph::InstructionCount() const {
1379 intptr_t size = 0; 1352 intptr_t size = 0;
1380 // Iterate each block, skipping the graph entry. 1353 // Iterate each block, skipping the graph entry.
1381 for (intptr_t i = 1; i < preorder_.length(); ++i) { 1354 for (intptr_t i = 1; i < preorder_.length(); ++i) {
1382 for (ForwardInstructionIterator it(preorder_[i]); 1355 for (ForwardInstructionIterator it(preorder_[i]); !it.Done();
1383 !it.Done();
1384 it.Advance()) { 1356 it.Advance()) {
1385 ++size; 1357 ++size;
1386 } 1358 }
1387 } 1359 }
1388 return size; 1360 return size;
1389 } 1361 }
1390 1362
1391 1363
1392 void FlowGraph::ComputeBlockEffects() { 1364 void FlowGraph::ComputeBlockEffects() {
1393 block_effects_ = new(zone()) BlockEffects(this); 1365 block_effects_ = new (zone()) BlockEffects(this);
1394 } 1366 }
1395 1367
1396 1368
1397 BlockEffects::BlockEffects(FlowGraph* flow_graph) 1369 BlockEffects::BlockEffects(FlowGraph* flow_graph)
1398 : available_at_(flow_graph->postorder().length()) { 1370 : available_at_(flow_graph->postorder().length()) {
1399 // We are tracking a single effect. 1371 // We are tracking a single effect.
1400 ASSERT(EffectSet::kLastEffect == 1); 1372 ASSERT(EffectSet::kLastEffect == 1);
1401 Zone* zone = flow_graph->zone(); 1373 Zone* zone = flow_graph->zone();
1402 const intptr_t block_count = flow_graph->postorder().length(); 1374 const intptr_t block_count = flow_graph->postorder().length();
1403 1375
1404 // Set of blocks that contain side-effects. 1376 // Set of blocks that contain side-effects.
1405 BitVector* kill = new(zone) BitVector(zone, block_count); 1377 BitVector* kill = new (zone) BitVector(zone, block_count);
1406 1378
1407 // Per block available-after sets. Block A is available after the block B if 1379 // Per block available-after sets. Block A is available after the block B if
1408 // and only if A is either equal to B or A is available at B and B contains no 1380 // and only if A is either equal to B or A is available at B and B contains no
1409 // side-effects. Initially we consider all blocks available after all other 1381 // side-effects. Initially we consider all blocks available after all other
1410 // blocks. 1382 // blocks.
1411 GrowableArray<BitVector*> available_after(block_count); 1383 GrowableArray<BitVector*> available_after(block_count);
1412 1384
1413 // Discover all blocks with side-effects. 1385 // Discover all blocks with side-effects.
1414 for (BlockIterator it = flow_graph->postorder_iterator(); 1386 for (BlockIterator it = flow_graph->postorder_iterator(); !it.Done();
1415 !it.Done();
1416 it.Advance()) { 1387 it.Advance()) {
1417 available_at_.Add(NULL); 1388 available_at_.Add(NULL);
1418 available_after.Add(NULL); 1389 available_after.Add(NULL);
1419 1390
1420 BlockEntryInstr* block = it.Current(); 1391 BlockEntryInstr* block = it.Current();
1421 for (ForwardInstructionIterator it(block); 1392 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
1422 !it.Done();
1423 it.Advance()) {
1424 if (!it.Current()->Effects().IsNone()) { 1393 if (!it.Current()->Effects().IsNone()) {
1425 kill->Add(block->postorder_number()); 1394 kill->Add(block->postorder_number());
1426 break; 1395 break;
1427 } 1396 }
1428 } 1397 }
1429 } 1398 }
1430 1399
1431 BitVector* temp = new(zone) BitVector(zone, block_count); 1400 BitVector* temp = new (zone) BitVector(zone, block_count);
1432 1401
1433 // Recompute available-at based on predecessors' available-after until the fix 1402 // Recompute available-at based on predecessors' available-after until the fix
1434 // point is reached. 1403 // point is reached.
1435 bool changed; 1404 bool changed;
1436 do { 1405 do {
1437 changed = false; 1406 changed = false;
1438 1407
1439 for (BlockIterator it = flow_graph->reverse_postorder_iterator(); 1408 for (BlockIterator it = flow_graph->reverse_postorder_iterator();
1440 !it.Done(); 1409 !it.Done(); it.Advance()) {
1441 it.Advance()) {
1442 BlockEntryInstr* block = it.Current(); 1410 BlockEntryInstr* block = it.Current();
1443 const intptr_t block_num = block->postorder_number(); 1411 const intptr_t block_num = block->postorder_number();
1444 1412
1445 if (block->IsGraphEntry()) { 1413 if (block->IsGraphEntry()) {
1446 temp->Clear(); // Nothing is live-in into graph entry. 1414 temp->Clear(); // Nothing is live-in into graph entry.
1447 } else { 1415 } else {
1448 // Available-at is an intersection of all predecessors' available-after 1416 // Available-at is an intersection of all predecessors' available-after
1449 // sets. 1417 // sets.
1450 temp->SetAll(); 1418 temp->SetAll();
1451 for (intptr_t i = 0; i < block->PredecessorCount(); i++) { 1419 for (intptr_t i = 0; i < block->PredecessorCount(); i++) {
1452 const intptr_t pred = block->PredecessorAt(i)->postorder_number(); 1420 const intptr_t pred = block->PredecessorAt(i)->postorder_number();
1453 if (available_after[pred] != NULL) { 1421 if (available_after[pred] != NULL) {
1454 temp->Intersect(available_after[pred]); 1422 temp->Intersect(available_after[pred]);
1455 } 1423 }
1456 } 1424 }
1457 } 1425 }
1458 1426
1459 BitVector* current = available_at_[block_num]; 1427 BitVector* current = available_at_[block_num];
1460 if ((current == NULL) || !current->Equals(*temp)) { 1428 if ((current == NULL) || !current->Equals(*temp)) {
1461 // Available-at changed: update it and recompute available-after. 1429 // Available-at changed: update it and recompute available-after.
1462 if (available_at_[block_num] == NULL) { 1430 if (available_at_[block_num] == NULL) {
1463 current = available_at_[block_num] = 1431 current = available_at_[block_num] =
1464 new(zone) BitVector(zone, block_count); 1432 new (zone) BitVector(zone, block_count);
1465 available_after[block_num] = 1433 available_after[block_num] = new (zone) BitVector(zone, block_count);
1466 new(zone) BitVector(zone, block_count);
1467 // Block is always available after itself. 1434 // Block is always available after itself.
1468 available_after[block_num]->Add(block_num); 1435 available_after[block_num]->Add(block_num);
1469 } 1436 }
1470 current->CopyFrom(temp); 1437 current->CopyFrom(temp);
1471 if (!kill->Contains(block_num)) { 1438 if (!kill->Contains(block_num)) {
1472 available_after[block_num]->CopyFrom(temp); 1439 available_after[block_num]->CopyFrom(temp);
1473 // Block is always available after itself. 1440 // Block is always available after itself.
1474 available_after[block_num]->Add(block_num); 1441 available_after[block_num]->Add(block_num);
1475 } 1442 }
1476 changed = true; 1443 changed = true;
1477 } 1444 }
1478 } 1445 }
1479 } while (changed); 1446 } while (changed);
1480 } 1447 }
1481 1448
1482 1449
1483 bool BlockEffects::IsAvailableAt(Instruction* instr, 1450 bool BlockEffects::IsAvailableAt(Instruction* instr,
1484 BlockEntryInstr* block) const { 1451 BlockEntryInstr* block) const {
1485 return (instr->Dependencies().IsNone()) || 1452 return (instr->Dependencies().IsNone()) ||
1486 IsSideEffectFreePath(instr->GetBlock(), block); 1453 IsSideEffectFreePath(instr->GetBlock(), block);
1487 } 1454 }
1488 1455
1489 1456
1490 bool BlockEffects::CanBeMovedTo(Instruction* instr, 1457 bool BlockEffects::CanBeMovedTo(Instruction* instr,
1491 BlockEntryInstr* block) const { 1458 BlockEntryInstr* block) const {
1492 return (instr->Dependencies().IsNone()) || 1459 return (instr->Dependencies().IsNone()) ||
1493 IsSideEffectFreePath(block, instr->GetBlock()); 1460 IsSideEffectFreePath(block, instr->GetBlock());
1494 } 1461 }
1495 1462
1496 1463
1497 bool BlockEffects::IsSideEffectFreePath(BlockEntryInstr* from, 1464 bool BlockEffects::IsSideEffectFreePath(BlockEntryInstr* from,
1498 BlockEntryInstr* to) const { 1465 BlockEntryInstr* to) const {
1499 return available_at_[to->postorder_number()]->Contains( 1466 return available_at_[to->postorder_number()]->Contains(
1500 from->postorder_number()); 1467 from->postorder_number());
1501 } 1468 }
1502 1469
1503 1470
1504 // Quick access to the current zone. 1471 // Quick access to the current zone.
1505 #define Z (zone()) 1472 #define Z (zone())
1506 1473
1507 1474
1508 void FlowGraph::ConvertUse(Value* use, Representation from_rep) { 1475 void FlowGraph::ConvertUse(Value* use, Representation from_rep) {
1509 const Representation to_rep = 1476 const Representation to_rep =
1510 use->instruction()->RequiredInputRepresentation(use->use_index()); 1477 use->instruction()->RequiredInputRepresentation(use->use_index());
1511 if (from_rep == to_rep || to_rep == kNoRepresentation) { 1478 if (from_rep == to_rep || to_rep == kNoRepresentation) {
1512 return; 1479 return;
1513 } 1480 }
1514 InsertConversion(from_rep, to_rep, use, /*is_environment_use=*/ false); 1481 InsertConversion(from_rep, to_rep, use, /*is_environment_use=*/false);
1515 } 1482 }
1516 1483
1517 1484
1518 static bool IsUnboxedInteger(Representation rep) { 1485 static bool IsUnboxedInteger(Representation rep) {
1519 return (rep == kUnboxedInt32) || 1486 return (rep == kUnboxedInt32) || (rep == kUnboxedUint32) ||
1520 (rep == kUnboxedUint32) ||
1521 (rep == kUnboxedMint); 1487 (rep == kUnboxedMint);
1522 } 1488 }
1523 1489
1524 1490
1525 static bool ShouldInlineSimd() { 1491 static bool ShouldInlineSimd() {
1526 return FlowGraphCompiler::SupportsUnboxedSimd128(); 1492 return FlowGraphCompiler::SupportsUnboxedSimd128();
1527 } 1493 }
1528 1494
1529 1495
1530 static bool CanUnboxDouble() { 1496 static bool CanUnboxDouble() {
(...skipping 18 matching lines...) Expand all
1549 // For phis conversions have to be inserted in the predecessor. 1515 // For phis conversions have to be inserted in the predecessor.
1550 insert_before = 1516 insert_before =
1551 phi->block()->PredecessorAt(use->use_index())->last_instruction(); 1517 phi->block()->PredecessorAt(use->use_index())->last_instruction();
1552 deopt_target = NULL; 1518 deopt_target = NULL;
1553 } else { 1519 } else {
1554 deopt_target = insert_before = use->instruction(); 1520 deopt_target = insert_before = use->instruction();
1555 } 1521 }
1556 1522
1557 Definition* converted = NULL; 1523 Definition* converted = NULL;
1558 if (IsUnboxedInteger(from) && IsUnboxedInteger(to)) { 1524 if (IsUnboxedInteger(from) && IsUnboxedInteger(to)) {
1559 const intptr_t deopt_id = (to == kUnboxedInt32) && (deopt_target != NULL) ? 1525 const intptr_t deopt_id = (to == kUnboxedInt32) && (deopt_target != NULL)
1560 deopt_target->DeoptimizationTarget() : Thread::kNoDeoptId; 1526 ? deopt_target->DeoptimizationTarget()
1561 converted = new(Z) UnboxedIntConverterInstr(from, 1527 : Thread::kNoDeoptId;
1562 to, 1528 converted = new (Z)
1563 use->CopyWithType(), 1529 UnboxedIntConverterInstr(from, to, use->CopyWithType(), deopt_id);
1564 deopt_id);
1565 } else if ((from == kUnboxedInt32) && (to == kUnboxedDouble)) { 1530 } else if ((from == kUnboxedInt32) && (to == kUnboxedDouble)) {
1566 converted = new Int32ToDoubleInstr(use->CopyWithType()); 1531 converted = new Int32ToDoubleInstr(use->CopyWithType());
1567 } else if ((from == kUnboxedMint) && 1532 } else if ((from == kUnboxedMint) && (to == kUnboxedDouble) &&
1568 (to == kUnboxedDouble) &&
1569 CanConvertUnboxedMintToDouble()) { 1533 CanConvertUnboxedMintToDouble()) {
1570 const intptr_t deopt_id = (deopt_target != NULL) ? 1534 const intptr_t deopt_id = (deopt_target != NULL)
1571 deopt_target->DeoptimizationTarget() : Thread::kNoDeoptId; 1535 ? deopt_target->DeoptimizationTarget()
1536 : Thread::kNoDeoptId;
1572 ASSERT(CanUnboxDouble()); 1537 ASSERT(CanUnboxDouble());
1573 converted = new MintToDoubleInstr(use->CopyWithType(), deopt_id); 1538 converted = new MintToDoubleInstr(use->CopyWithType(), deopt_id);
1574 } else if ((from == kTagged) && Boxing::Supports(to)) { 1539 } else if ((from == kTagged) && Boxing::Supports(to)) {
1575 const intptr_t deopt_id = (deopt_target != NULL) ? 1540 const intptr_t deopt_id = (deopt_target != NULL)
1576 deopt_target->DeoptimizationTarget() : Thread::kNoDeoptId; 1541 ? deopt_target->DeoptimizationTarget()
1542 : Thread::kNoDeoptId;
1577 converted = UnboxInstr::Create(to, use->CopyWithType(), deopt_id); 1543 converted = UnboxInstr::Create(to, use->CopyWithType(), deopt_id);
1578 } else if ((to == kTagged) && Boxing::Supports(from)) { 1544 } else if ((to == kTagged) && Boxing::Supports(from)) {
1579 converted = BoxInstr::Create(from, use->CopyWithType()); 1545 converted = BoxInstr::Create(from, use->CopyWithType());
1580 } else { 1546 } else {
1581 // We have failed to find a suitable conversion instruction. 1547 // We have failed to find a suitable conversion instruction.
1582 // Insert two "dummy" conversion instructions with the correct 1548 // Insert two "dummy" conversion instructions with the correct
1583 // "from" and "to" representation. The inserted instructions will 1549 // "from" and "to" representation. The inserted instructions will
1584 // trigger a deoptimization if executed. See #12417 for a discussion. 1550 // trigger a deoptimization if executed. See #12417 for a discussion.
1585 const intptr_t deopt_id = (deopt_target != NULL) ? 1551 const intptr_t deopt_id = (deopt_target != NULL)
1586 deopt_target->DeoptimizationTarget() : Thread::kNoDeoptId; 1552 ? deopt_target->DeoptimizationTarget()
1553 : Thread::kNoDeoptId;
1587 ASSERT(Boxing::Supports(from)); 1554 ASSERT(Boxing::Supports(from));
1588 ASSERT(Boxing::Supports(to)); 1555 ASSERT(Boxing::Supports(to));
1589 Definition* boxed = BoxInstr::Create(from, use->CopyWithType()); 1556 Definition* boxed = BoxInstr::Create(from, use->CopyWithType());
1590 use->BindTo(boxed); 1557 use->BindTo(boxed);
1591 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue); 1558 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue);
1592 converted = UnboxInstr::Create(to, new(Z) Value(boxed), deopt_id); 1559 converted = UnboxInstr::Create(to, new (Z) Value(boxed), deopt_id);
1593 } 1560 }
1594 ASSERT(converted != NULL); 1561 ASSERT(converted != NULL);
1595 InsertBefore(insert_before, converted, use->instruction()->env(), 1562 InsertBefore(insert_before, converted, use->instruction()->env(),
1596 FlowGraph::kValue); 1563 FlowGraph::kValue);
1597 if (is_environment_use) { 1564 if (is_environment_use) {
1598 use->BindToEnvironment(converted); 1565 use->BindToEnvironment(converted);
1599 } else { 1566 } else {
1600 use->BindTo(converted); 1567 use->BindTo(converted);
1601 } 1568 }
1602 1569
1603 if ((to == kUnboxedInt32) && (phi != NULL)) { 1570 if ((to == kUnboxedInt32) && (phi != NULL)) {
1604 // Int32 phis are unboxed optimistically. Ensure that unboxing 1571 // Int32 phis are unboxed optimistically. Ensure that unboxing
1605 // has deoptimization target attached from the goto instruction. 1572 // has deoptimization target attached from the goto instruction.
1606 CopyDeoptTarget(converted, insert_before); 1573 CopyDeoptTarget(converted, insert_before);
1607 } 1574 }
1608 } 1575 }
1609 1576
1610 1577
1611 void FlowGraph::ConvertEnvironmentUse(Value* use, Representation from_rep) { 1578 void FlowGraph::ConvertEnvironmentUse(Value* use, Representation from_rep) {
1612 const Representation to_rep = kTagged; 1579 const Representation to_rep = kTagged;
1613 if (from_rep == to_rep) { 1580 if (from_rep == to_rep) {
1614 return; 1581 return;
1615 } 1582 }
1616 InsertConversion(from_rep, to_rep, use, /*is_environment_use=*/ true); 1583 InsertConversion(from_rep, to_rep, use, /*is_environment_use=*/true);
1617 } 1584 }
1618 1585
1619 1586
1620 void FlowGraph::InsertConversionsFor(Definition* def) { 1587 void FlowGraph::InsertConversionsFor(Definition* def) {
1621 const Representation from_rep = def->representation(); 1588 const Representation from_rep = def->representation();
1622 1589
1623 for (Value::Iterator it(def->input_use_list()); 1590 for (Value::Iterator it(def->input_use_list()); !it.Done(); it.Advance()) {
1624 !it.Done();
1625 it.Advance()) {
1626 ConvertUse(it.Current(), from_rep); 1591 ConvertUse(it.Current(), from_rep);
1627 } 1592 }
1628 1593
1629 if (graph_entry()->SuccessorCount() > 1) { 1594 if (graph_entry()->SuccessorCount() > 1) {
1630 for (Value::Iterator it(def->env_use_list()); 1595 for (Value::Iterator it(def->env_use_list()); !it.Done(); it.Advance()) {
1631 !it.Done();
1632 it.Advance()) {
1633 Value* use = it.Current(); 1596 Value* use = it.Current();
1634 if (use->instruction()->MayThrow() && 1597 if (use->instruction()->MayThrow() &&
1635 use->instruction()->GetBlock()->InsideTryBlock()) { 1598 use->instruction()->GetBlock()->InsideTryBlock()) {
1636 // Environment uses at calls inside try-blocks must be converted to 1599 // Environment uses at calls inside try-blocks must be converted to
1637 // tagged representation. 1600 // tagged representation.
1638 ConvertEnvironmentUse(it.Current(), from_rep); 1601 ConvertEnvironmentUse(it.Current(), from_rep);
1639 } 1602 }
1640 } 1603 }
1641 } 1604 }
1642 } 1605 }
(...skipping 18 matching lines...) Expand all
1661 unboxed = kUnboxedInt32x4; 1624 unboxed = kUnboxedInt32x4;
1662 } 1625 }
1663 break; 1626 break;
1664 case kFloat64x2Cid: 1627 case kFloat64x2Cid:
1665 if (ShouldInlineSimd()) { 1628 if (ShouldInlineSimd()) {
1666 unboxed = kUnboxedFloat64x2; 1629 unboxed = kUnboxedFloat64x2;
1667 } 1630 }
1668 break; 1631 break;
1669 } 1632 }
1670 1633
1671 if ((kSmiBits < 32) && 1634 if ((kSmiBits < 32) && (unboxed == kTagged) && phi->Type()->IsInt() &&
1672 (unboxed == kTagged) &&
1673 phi->Type()->IsInt() &&
1674 RangeUtils::Fits(phi->range(), RangeBoundary::kRangeBoundaryInt64)) { 1635 RangeUtils::Fits(phi->range(), RangeBoundary::kRangeBoundaryInt64)) {
1675 // On 32-bit platforms conservatively unbox phis that: 1636 // On 32-bit platforms conservatively unbox phis that:
1676 // - are proven to be of type Int; 1637 // - are proven to be of type Int;
1677 // - fit into 64bits range; 1638 // - fit into 64bits range;
1678 // - have either constants or Box() operations as inputs; 1639 // - have either constants or Box() operations as inputs;
1679 // - have at least one Box() operation as an input; 1640 // - have at least one Box() operation as an input;
1680 // - are used in at least 1 Unbox() operation. 1641 // - are used in at least 1 Unbox() operation.
1681 bool should_unbox = false; 1642 bool should_unbox = false;
1682 for (intptr_t i = 0; i < phi->InputCount(); i++) { 1643 for (intptr_t i = 0; i < phi->InputCount(); i++) {
1683 Definition* input = phi->InputAt(i)->definition(); 1644 Definition* input = phi->InputAt(i)->definition();
1684 if (input->IsBox() && 1645 if (input->IsBox() &&
1685 RangeUtils::Fits(input->range(), 1646 RangeUtils::Fits(input->range(),
1686 RangeBoundary::kRangeBoundaryInt64)) { 1647 RangeBoundary::kRangeBoundaryInt64)) {
1687 should_unbox = true; 1648 should_unbox = true;
1688 } else if (!input->IsConstant()) { 1649 } else if (!input->IsConstant()) {
1689 should_unbox = false; 1650 should_unbox = false;
1690 break; 1651 break;
1691 } 1652 }
1692 } 1653 }
1693 1654
1694 if (should_unbox) { 1655 if (should_unbox) {
1695 // We checked inputs. Check if phi is used in at least one unbox 1656 // We checked inputs. Check if phi is used in at least one unbox
1696 // operation. 1657 // operation.
1697 bool has_unboxed_use = false; 1658 bool has_unboxed_use = false;
1698 for (Value* use = phi->input_use_list(); 1659 for (Value* use = phi->input_use_list(); use != NULL;
1699 use != NULL;
1700 use = use->next_use()) { 1660 use = use->next_use()) {
1701 Instruction* instr = use->instruction(); 1661 Instruction* instr = use->instruction();
1702 if (instr->IsUnbox()) { 1662 if (instr->IsUnbox()) {
1703 has_unboxed_use = true; 1663 has_unboxed_use = true;
1704 break; 1664 break;
1705 } else if (IsUnboxedInteger( 1665 } else if (IsUnboxedInteger(
1706 instr->RequiredInputRepresentation(use->use_index()))) { 1666 instr->RequiredInputRepresentation(use->use_index()))) {
1707 has_unboxed_use = true; 1667 has_unboxed_use = true;
1708 break; 1668 break;
1709 } 1669 }
1710 } 1670 }
1711 1671
1712 if (!has_unboxed_use) { 1672 if (!has_unboxed_use) {
1713 should_unbox = false; 1673 should_unbox = false;
1714 } 1674 }
1715 } 1675 }
1716 1676
1717 if (should_unbox) { 1677 if (should_unbox) {
1718 unboxed = 1678 unboxed =
1719 RangeUtils::Fits(phi->range(), RangeBoundary::kRangeBoundaryInt32) 1679 RangeUtils::Fits(phi->range(), RangeBoundary::kRangeBoundaryInt32)
1720 ? kUnboxedInt32 : kUnboxedMint; 1680 ? kUnboxedInt32
1681 : kUnboxedMint;
1721 } 1682 }
1722 } 1683 }
1723 1684
1724 phi->set_representation(unboxed); 1685 phi->set_representation(unboxed);
1725 } 1686 }
1726 1687
1727 1688
1728 void FlowGraph::SelectRepresentations() { 1689 void FlowGraph::SelectRepresentations() {
1729 // Conservatively unbox all phis that were proven to be of Double, 1690 // Conservatively unbox all phis that were proven to be of Double,
1730 // Float32x4, or Int32x4 type. 1691 // Float32x4, or Int32x4 type.
1731 for (BlockIterator block_it = reverse_postorder_iterator(); 1692 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
1732 !block_it.Done();
1733 block_it.Advance()) { 1693 block_it.Advance()) {
1734 JoinEntryInstr* join_entry = block_it.Current()->AsJoinEntry(); 1694 JoinEntryInstr* join_entry = block_it.Current()->AsJoinEntry();
1735 if (join_entry != NULL) { 1695 if (join_entry != NULL) {
1736 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) { 1696 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
1737 PhiInstr* phi = it.Current(); 1697 PhiInstr* phi = it.Current();
1738 UnboxPhi(phi); 1698 UnboxPhi(phi);
1739 } 1699 }
1740 } 1700 }
1741 } 1701 }
1742 1702
1743 // Process all instructions and insert conversions where needed. 1703 // Process all instructions and insert conversions where needed.
1744 // Visit incoming parameters and constants. 1704 // Visit incoming parameters and constants.
1745 for (intptr_t i = 0; 1705 for (intptr_t i = 0; i < graph_entry()->initial_definitions()->length();
1746 i < graph_entry()->initial_definitions()->length();
1747 i++) { 1706 i++) {
1748 InsertConversionsFor((*graph_entry()->initial_definitions())[i]); 1707 InsertConversionsFor((*graph_entry()->initial_definitions())[i]);
1749 } 1708 }
1750 1709
1751 for (BlockIterator block_it = reverse_postorder_iterator(); 1710 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
1752 !block_it.Done();
1753 block_it.Advance()) { 1711 block_it.Advance()) {
1754 BlockEntryInstr* entry = block_it.Current(); 1712 BlockEntryInstr* entry = block_it.Current();
1755 JoinEntryInstr* join_entry = entry->AsJoinEntry(); 1713 JoinEntryInstr* join_entry = entry->AsJoinEntry();
1756 if (join_entry != NULL) { 1714 if (join_entry != NULL) {
1757 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) { 1715 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
1758 PhiInstr* phi = it.Current(); 1716 PhiInstr* phi = it.Current();
1759 ASSERT(phi != NULL); 1717 ASSERT(phi != NULL);
1760 ASSERT(phi->is_alive()); 1718 ASSERT(phi->is_alive());
1761 InsertConversionsFor(phi); 1719 InsertConversionsFor(phi);
1762 } 1720 }
1763 } 1721 }
1764 CatchBlockEntryInstr* catch_entry = entry->AsCatchBlockEntry(); 1722 CatchBlockEntryInstr* catch_entry = entry->AsCatchBlockEntry();
1765 if (catch_entry != NULL) { 1723 if (catch_entry != NULL) {
1766 for (intptr_t i = 0; 1724 for (intptr_t i = 0; i < catch_entry->initial_definitions()->length();
1767 i < catch_entry->initial_definitions()->length();
1768 i++) { 1725 i++) {
1769 InsertConversionsFor((*catch_entry->initial_definitions())[i]); 1726 InsertConversionsFor((*catch_entry->initial_definitions())[i]);
1770 } 1727 }
1771 } 1728 }
1772 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 1729 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
1773 Definition* def = it.Current()->AsDefinition(); 1730 Definition* def = it.Current()->AsDefinition();
1774 if (def != NULL) { 1731 if (def != NULL) {
1775 InsertConversionsFor(def); 1732 InsertConversionsFor(def);
1776 } 1733 }
1777 } 1734 }
1778 } 1735 }
1779 } 1736 }
1780 1737
1781 1738
1782 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_IA32) 1739 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_IA32)
1783 // Smi widening pass is only meaningful on platforms where Smi 1740 // Smi widening pass is only meaningful on platforms where Smi
1784 // is smaller than 32bit. For now only support it on ARM and ia32. 1741 // is smaller than 32bit. For now only support it on ARM and ia32.
1785 static bool CanBeWidened(BinarySmiOpInstr* smi_op) { 1742 static bool CanBeWidened(BinarySmiOpInstr* smi_op) {
1786 return BinaryInt32OpInstr::IsSupported(smi_op->op_kind(), 1743 return BinaryInt32OpInstr::IsSupported(smi_op->op_kind(), smi_op->left(),
1787 smi_op->left(),
1788 smi_op->right()); 1744 smi_op->right());
1789 } 1745 }
1790 1746
1791 1747
1792 static bool BenefitsFromWidening(BinarySmiOpInstr* smi_op) { 1748 static bool BenefitsFromWidening(BinarySmiOpInstr* smi_op) {
1793 // TODO(vegorov): when shifts with non-constants shift count are supported 1749 // TODO(vegorov): when shifts with non-constants shift count are supported
1794 // add them here as we save untagging for the count. 1750 // add them here as we save untagging for the count.
1795 switch (smi_op->op_kind()) { 1751 switch (smi_op->op_kind()) {
1796 case Token::kMUL: 1752 case Token::kMUL:
1797 case Token::kSHR: 1753 case Token::kSHR:
1798 // For kMUL we save untagging of the argument for kSHR 1754 // For kMUL we save untagging of the argument for kSHR
1799 // we save tagging of the result. 1755 // we save tagging of the result.
1800 return true; 1756 return true;
1801 1757
1802 default: 1758 default:
1803 return false; 1759 return false;
1804 } 1760 }
1805 } 1761 }
1806 1762
1807 1763
1808 void FlowGraph::WidenSmiToInt32() { 1764 void FlowGraph::WidenSmiToInt32() {
1809 GrowableArray<BinarySmiOpInstr*> candidates; 1765 GrowableArray<BinarySmiOpInstr*> candidates;
1810 1766
1811 // Step 1. Collect all instructions that potentially benefit from widening of 1767 // Step 1. Collect all instructions that potentially benefit from widening of
1812 // their operands (or their result) into int32 range. 1768 // their operands (or their result) into int32 range.
1813 for (BlockIterator block_it = reverse_postorder_iterator(); 1769 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
1814 !block_it.Done();
1815 block_it.Advance()) { 1770 block_it.Advance()) {
1816 for (ForwardInstructionIterator instr_it(block_it.Current()); 1771 for (ForwardInstructionIterator instr_it(block_it.Current());
1817 !instr_it.Done(); 1772 !instr_it.Done(); instr_it.Advance()) {
1818 instr_it.Advance()) {
1819 BinarySmiOpInstr* smi_op = instr_it.Current()->AsBinarySmiOp(); 1773 BinarySmiOpInstr* smi_op = instr_it.Current()->AsBinarySmiOp();
1820 if ((smi_op != NULL) && 1774 if ((smi_op != NULL) && smi_op->HasSSATemp() &&
1821 smi_op->HasSSATemp() && 1775 BenefitsFromWidening(smi_op) && CanBeWidened(smi_op)) {
1822 BenefitsFromWidening(smi_op) &&
1823 CanBeWidened(smi_op)) {
1824 candidates.Add(smi_op); 1776 candidates.Add(smi_op);
1825 } 1777 }
1826 } 1778 }
1827 } 1779 }
1828 1780
1829 if (candidates.is_empty()) { 1781 if (candidates.is_empty()) {
1830 return; 1782 return;
1831 } 1783 }
1832 1784
1833 // Step 2. For each block in the graph compute which loop it belongs to. 1785 // Step 2. For each block in the graph compute which loop it belongs to.
1834 // We will use this information later during computation of the widening's 1786 // We will use this information later during computation of the widening's
1835 // gain: we are going to assume that only conversion occuring inside the 1787 // gain: we are going to assume that only conversion occuring inside the
1836 // same loop should be counted against the gain, all other conversions 1788 // same loop should be counted against the gain, all other conversions
1837 // can be hoisted and thus cost nothing compared to the loop cost itself. 1789 // can be hoisted and thus cost nothing compared to the loop cost itself.
1838 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = LoopHeaders(); 1790 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = LoopHeaders();
1839 1791
1840 GrowableArray<intptr_t> loops(preorder().length()); 1792 GrowableArray<intptr_t> loops(preorder().length());
1841 for (intptr_t i = 0; i < preorder().length(); i++) { 1793 for (intptr_t i = 0; i < preorder().length(); i++) {
1842 loops.Add(-1); 1794 loops.Add(-1);
1843 } 1795 }
1844 1796
1845 for (intptr_t loop_id = 0; loop_id < loop_headers.length(); ++loop_id) { 1797 for (intptr_t loop_id = 0; loop_id < loop_headers.length(); ++loop_id) {
1846 for (BitVector::Iterator loop_it(loop_headers[loop_id]->loop_info()); 1798 for (BitVector::Iterator loop_it(loop_headers[loop_id]->loop_info());
1847 !loop_it.Done(); 1799 !loop_it.Done(); loop_it.Advance()) {
1848 loop_it.Advance()) {
1849 loops[loop_it.Current()] = loop_id; 1800 loops[loop_it.Current()] = loop_id;
1850 } 1801 }
1851 } 1802 }
1852 1803
1853 // Step 3. For each candidate transitively collect all other BinarySmiOpInstr 1804 // Step 3. For each candidate transitively collect all other BinarySmiOpInstr
1854 // and PhiInstr that depend on it and that it depends on and count amount of 1805 // and PhiInstr that depend on it and that it depends on and count amount of
1855 // untagging operations that we save in assumption that this whole graph of 1806 // untagging operations that we save in assumption that this whole graph of
1856 // values is using kUnboxedInt32 representation instead of kTagged. 1807 // values is using kUnboxedInt32 representation instead of kTagged.
1857 // Convert those graphs that have positive gain to kUnboxedInt32. 1808 // Convert those graphs that have positive gain to kUnboxedInt32.
1858 1809
1859 // BitVector containing SSA indexes of all processed definitions. Used to skip 1810 // BitVector containing SSA indexes of all processed definitions. Used to skip
1860 // those candidates that belong to dependency graph of another candidate. 1811 // those candidates that belong to dependency graph of another candidate.
1861 BitVector* processed = 1812 BitVector* processed = new (Z) BitVector(Z, current_ssa_temp_index());
1862 new(Z) BitVector(Z, current_ssa_temp_index());
1863 1813
1864 // Worklist used to collect dependency graph. 1814 // Worklist used to collect dependency graph.
1865 DefinitionWorklist worklist(this, candidates.length()); 1815 DefinitionWorklist worklist(this, candidates.length());
1866 for (intptr_t i = 0; i < candidates.length(); i++) { 1816 for (intptr_t i = 0; i < candidates.length(); i++) {
1867 BinarySmiOpInstr* op = candidates[i]; 1817 BinarySmiOpInstr* op = candidates[i];
1868 if (op->WasEliminated() || processed->Contains(op->ssa_temp_index())) { 1818 if (op->WasEliminated() || processed->Contains(op->ssa_temp_index())) {
1869 continue; 1819 continue;
1870 } 1820 }
1871 1821
1872 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { 1822 if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
(...skipping 18 matching lines...) Expand all
1891 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { 1841 if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
1892 THR_Print("^ [%" Pd "] (o) %s\n", gain, defn->ToCString()); 1842 THR_Print("^ [%" Pd "] (o) %s\n", gain, defn->ToCString());
1893 } 1843 }
1894 } 1844 }
1895 1845
1896 const intptr_t defn_loop = loops[defn->GetBlock()->preorder_number()]; 1846 const intptr_t defn_loop = loops[defn->GetBlock()->preorder_number()];
1897 1847
1898 // Process all inputs. 1848 // Process all inputs.
1899 for (intptr_t k = 0; k < defn->InputCount(); k++) { 1849 for (intptr_t k = 0; k < defn->InputCount(); k++) {
1900 Definition* input = defn->InputAt(k)->definition(); 1850 Definition* input = defn->InputAt(k)->definition();
1901 if (input->IsBinarySmiOp() && 1851 if (input->IsBinarySmiOp() && CanBeWidened(input->AsBinarySmiOp())) {
1902 CanBeWidened(input->AsBinarySmiOp())) {
1903 worklist.Add(input); 1852 worklist.Add(input);
1904 } else if (input->IsPhi() && (input->Type()->ToCid() == kSmiCid)) { 1853 } else if (input->IsPhi() && (input->Type()->ToCid() == kSmiCid)) {
1905 worklist.Add(input); 1854 worklist.Add(input);
1906 } else if (input->IsBinaryMintOp()) { 1855 } else if (input->IsBinaryMintOp()) {
1907 // Mint operation produces untagged result. We avoid tagging. 1856 // Mint operation produces untagged result. We avoid tagging.
1908 gain++; 1857 gain++;
1909 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { 1858 if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
1910 THR_Print("^ [%" Pd "] (i) %s\n", gain, input->ToCString()); 1859 THR_Print("^ [%" Pd "] (i) %s\n", gain, input->ToCString());
1911 } 1860 }
1912 } else if (defn_loop == loops[input->GetBlock()->preorder_number()] && 1861 } else if (defn_loop == loops[input->GetBlock()->preorder_number()] &&
1913 (input->Type()->ToCid() == kSmiCid)) { 1862 (input->Type()->ToCid() == kSmiCid)) {
1914 // Input comes from the same loop, is known to be smi and requires 1863 // Input comes from the same loop, is known to be smi and requires
1915 // untagging. 1864 // untagging.
1916 // TODO(vegorov) this heuristic assumes that values that are not 1865 // TODO(vegorov) this heuristic assumes that values that are not
1917 // known to be smi have to be checked and this check can be 1866 // known to be smi have to be checked and this check can be
1918 // coalesced with untagging. Start coalescing them. 1867 // coalesced with untagging. Start coalescing them.
1919 gain--; 1868 gain--;
1920 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { 1869 if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
1921 THR_Print("v [%" Pd "] (i) %s\n", gain, input->ToCString()); 1870 THR_Print("v [%" Pd "] (i) %s\n", gain, input->ToCString());
1922 } 1871 }
1923 } 1872 }
1924 } 1873 }
1925 1874
1926 // Process all uses. 1875 // Process all uses.
1927 for (Value* use = defn->input_use_list(); 1876 for (Value* use = defn->input_use_list(); use != NULL;
1928 use != NULL;
1929 use = use->next_use()) { 1877 use = use->next_use()) {
1930 Instruction* instr = use->instruction(); 1878 Instruction* instr = use->instruction();
1931 Definition* use_defn = instr->AsDefinition(); 1879 Definition* use_defn = instr->AsDefinition();
1932 if (use_defn == NULL) { 1880 if (use_defn == NULL) {
1933 // We assume that tagging before returning or pushing argument costs 1881 // We assume that tagging before returning or pushing argument costs
1934 // very little compared to the cost of the return/call itself. 1882 // very little compared to the cost of the return/call itself.
1935 if (!instr->IsReturn() && !instr->IsPushArgument()) { 1883 if (!instr->IsReturn() && !instr->IsPushArgument()) {
1936 gain--; 1884 gain--;
1937 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { 1885 if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
1938 THR_Print("v [%" Pd "] (u) %s\n", 1886 THR_Print("v [%" Pd "] (u) %s\n", gain,
1939 gain,
1940 use->instruction()->ToCString()); 1887 use->instruction()->ToCString());
1941 } 1888 }
1942 } 1889 }
1943 continue; 1890 continue;
1944 } else if (use_defn->IsBinarySmiOp() && 1891 } else if (use_defn->IsBinarySmiOp() &&
1945 CanBeWidened(use_defn->AsBinarySmiOp())) { 1892 CanBeWidened(use_defn->AsBinarySmiOp())) {
1946 worklist.Add(use_defn); 1893 worklist.Add(use_defn);
1947 } else if (use_defn->IsPhi() && 1894 } else if (use_defn->IsPhi() &&
1948 use_defn->AsPhi()->Type()->ToCid() == kSmiCid) { 1895 use_defn->AsPhi()->Type()->ToCid() == kSmiCid) {
1949 worklist.Add(use_defn); 1896 worklist.Add(use_defn);
1950 } else if (use_defn->IsBinaryMintOp()) { 1897 } else if (use_defn->IsBinaryMintOp()) {
1951 // BinaryMintOp requires untagging of its inputs. 1898 // BinaryMintOp requires untagging of its inputs.
1952 // Converting kUnboxedInt32 to kUnboxedMint is essentially zero cost 1899 // Converting kUnboxedInt32 to kUnboxedMint is essentially zero cost
1953 // sign extension operation. 1900 // sign extension operation.
1954 gain++; 1901 gain++;
1955 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { 1902 if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
1956 THR_Print("^ [%" Pd "] (u) %s\n", 1903 THR_Print("^ [%" Pd "] (u) %s\n", gain,
1957 gain,
1958 use->instruction()->ToCString()); 1904 use->instruction()->ToCString());
1959 } 1905 }
1960 } else if (defn_loop == loops[instr->GetBlock()->preorder_number()]) { 1906 } else if (defn_loop == loops[instr->GetBlock()->preorder_number()]) {
1961 gain--; 1907 gain--;
1962 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { 1908 if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
1963 THR_Print("v [%" Pd "] (u) %s\n", 1909 THR_Print("v [%" Pd "] (u) %s\n", gain,
1964 gain,
1965 use->instruction()->ToCString()); 1910 use->instruction()->ToCString());
1966 } 1911 }
1967 } 1912 }
1968 } 1913 }
1969 } 1914 }
1970 1915
1971 processed->AddAll(worklist.contains_vector()); 1916 processed->AddAll(worklist.contains_vector());
1972 1917
1973 if (FLAG_support_il_printer && FLAG_trace_smi_widening) { 1918 if (FLAG_support_il_printer && FLAG_trace_smi_widening) {
1974 THR_Print("~ %s gain %" Pd "\n", op->ToCString(), gain); 1919 THR_Print("~ %s gain %" Pd "\n", op->ToCString(), gain);
1975 } 1920 }
1976 1921
1977 if (gain > 0) { 1922 if (gain > 0) {
1978 // We have positive gain from widening. Convert all BinarySmiOpInstr into 1923 // We have positive gain from widening. Convert all BinarySmiOpInstr into
1979 // BinaryInt32OpInstr and set representation of all phis to kUnboxedInt32. 1924 // BinaryInt32OpInstr and set representation of all phis to kUnboxedInt32.
1980 for (intptr_t j = 0; j < worklist.definitions().length(); j++) { 1925 for (intptr_t j = 0; j < worklist.definitions().length(); j++) {
1981 Definition* defn = worklist.definitions()[j]; 1926 Definition* defn = worklist.definitions()[j];
1982 ASSERT(defn->IsPhi() || defn->IsBinarySmiOp()); 1927 ASSERT(defn->IsPhi() || defn->IsBinarySmiOp());
1983 1928
1984 if (defn->IsBinarySmiOp()) { 1929 if (defn->IsBinarySmiOp()) {
1985 BinarySmiOpInstr* smi_op = defn->AsBinarySmiOp(); 1930 BinarySmiOpInstr* smi_op = defn->AsBinarySmiOp();
1986 BinaryInt32OpInstr* int32_op = new(Z) BinaryInt32OpInstr( 1931 BinaryInt32OpInstr* int32_op = new (Z) BinaryInt32OpInstr(
1987 smi_op->op_kind(), 1932 smi_op->op_kind(), smi_op->left()->CopyWithType(),
1988 smi_op->left()->CopyWithType(), 1933 smi_op->right()->CopyWithType(), smi_op->DeoptimizationTarget());
1989 smi_op->right()->CopyWithType(),
1990 smi_op->DeoptimizationTarget());
1991 1934
1992 smi_op->ReplaceWith(int32_op, NULL); 1935 smi_op->ReplaceWith(int32_op, NULL);
1993 } else if (defn->IsPhi()) { 1936 } else if (defn->IsPhi()) {
1994 defn->AsPhi()->set_representation(kUnboxedInt32); 1937 defn->AsPhi()->set_representation(kUnboxedInt32);
1995 ASSERT(defn->Type()->IsInt()); 1938 ASSERT(defn->Type()->IsInt());
1996 } 1939 }
1997 } 1940 }
1998 } 1941 }
1999 } 1942 }
2000 } 1943 }
2001 #else 1944 #else
2002 void FlowGraph::WidenSmiToInt32() { 1945 void FlowGraph::WidenSmiToInt32() {
2003 // TODO(vegorov) ideally on 64-bit platforms we would like to narrow smi 1946 // TODO(vegorov) ideally on 64-bit platforms we would like to narrow smi
2004 // operations to 32-bit where it saves tagging and untagging and allows 1947 // operations to 32-bit where it saves tagging and untagging and allows
2005 // to use shorted (and faster) instructions. But we currently don't 1948 // to use shorted (and faster) instructions. But we currently don't
2006 // save enough range information in the ICData to drive this decision. 1949 // save enough range information in the ICData to drive this decision.
2007 } 1950 }
2008 #endif 1951 #endif
2009 1952
2010 1953
2011 void FlowGraph::EliminateEnvironments() { 1954 void FlowGraph::EliminateEnvironments() {
2012 // After this pass we can no longer perform LICM and hoist instructions 1955 // After this pass we can no longer perform LICM and hoist instructions
2013 // that can deoptimize. 1956 // that can deoptimize.
2014 1957
2015 disallow_licm(); 1958 disallow_licm();
2016 for (BlockIterator block_it = reverse_postorder_iterator(); 1959 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
2017 !block_it.Done();
2018 block_it.Advance()) { 1960 block_it.Advance()) {
2019 BlockEntryInstr* block = block_it.Current(); 1961 BlockEntryInstr* block = block_it.Current();
2020 if (!block->IsCatchBlockEntry()) { 1962 if (!block->IsCatchBlockEntry()) {
2021 block->RemoveEnvironment(); 1963 block->RemoveEnvironment();
2022 } 1964 }
2023 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { 1965 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
2024 Instruction* current = it.Current(); 1966 Instruction* current = it.Current();
2025 if (!current->CanDeoptimize() && 1967 if (!current->CanDeoptimize() &&
2026 (!current->MayThrow() || !current->GetBlock()->InsideTryBlock())) { 1968 (!current->MayThrow() || !current->GetBlock()->InsideTryBlock())) {
2027 // Instructions that can throw need an environment for optimized 1969 // Instructions that can throw need an environment for optimized
2028 // try-catch. 1970 // try-catch.
2029 // TODO(srdjan): --source-lines needs deopt environments to get at 1971 // TODO(srdjan): --source-lines needs deopt environments to get at
2030 // the code for this instruction, however, leaving the environment 1972 // the code for this instruction, however, leaving the environment
2031 // changes code. 1973 // changes code.
2032 current->RemoveEnvironment(); 1974 current->RemoveEnvironment();
2033 } 1975 }
2034 } 1976 }
2035 } 1977 }
2036 } 1978 }
2037 1979
2038 1980
2039 bool FlowGraph::Canonicalize() { 1981 bool FlowGraph::Canonicalize() {
2040 bool changed = false; 1982 bool changed = false;
2041 1983
2042 for (BlockIterator block_it = reverse_postorder_iterator(); 1984 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
2043 !block_it.Done();
2044 block_it.Advance()) { 1985 block_it.Advance()) {
2045 for (ForwardInstructionIterator it(block_it.Current()); 1986 for (ForwardInstructionIterator it(block_it.Current()); !it.Done();
2046 !it.Done();
2047 it.Advance()) { 1987 it.Advance()) {
2048 Instruction* current = it.Current(); 1988 Instruction* current = it.Current();
2049 if (current->HasUnmatchedInputRepresentations()) { 1989 if (current->HasUnmatchedInputRepresentations()) {
2050 // Can't canonicalize this instruction until all conversions for its 1990 // Can't canonicalize this instruction until all conversions for its
2051 // inputs are inserted. 1991 // inputs are inserted.
2052 continue; 1992 continue;
2053 } 1993 }
2054 1994
2055 Instruction* replacement = current->Canonicalize(this); 1995 Instruction* replacement = current->Canonicalize(this);
2056 1996
(...skipping 10 matching lines...) Expand all
2067 } 2007 }
2068 2008
2069 2009
2070 // Optimize (a << b) & c pattern: if c is a positive Smi or zero, then the 2010 // Optimize (a << b) & c pattern: if c is a positive Smi or zero, then the
2071 // shift can be a truncating Smi shift-left and result is always Smi. 2011 // shift can be a truncating Smi shift-left and result is always Smi.
2072 // Merging occurs only per basic-block. 2012 // Merging occurs only per basic-block.
2073 void FlowGraph::TryOptimizePatterns() { 2013 void FlowGraph::TryOptimizePatterns() {
2074 if (!FLAG_truncating_left_shift) return; 2014 if (!FLAG_truncating_left_shift) return;
2075 GrowableArray<BinarySmiOpInstr*> div_mod_merge; 2015 GrowableArray<BinarySmiOpInstr*> div_mod_merge;
2076 GrowableArray<InvokeMathCFunctionInstr*> sin_cos_merge; 2016 GrowableArray<InvokeMathCFunctionInstr*> sin_cos_merge;
2077 for (BlockIterator block_it = reverse_postorder_iterator(); 2017 for (BlockIterator block_it = reverse_postorder_iterator(); !block_it.Done();
2078 !block_it.Done();
2079 block_it.Advance()) { 2018 block_it.Advance()) {
2080 // Merging only per basic-block. 2019 // Merging only per basic-block.
2081 div_mod_merge.Clear(); 2020 div_mod_merge.Clear();
2082 sin_cos_merge.Clear(); 2021 sin_cos_merge.Clear();
2083 ForwardInstructionIterator it(block_it.Current()); 2022 ForwardInstructionIterator it(block_it.Current());
2084 for (; !it.Done(); it.Advance()) { 2023 for (; !it.Done(); it.Advance()) {
2085 if (it.Current()->IsBinarySmiOp()) { 2024 if (it.Current()->IsBinarySmiOp()) {
2086 BinarySmiOpInstr* binop = it.Current()->AsBinarySmiOp(); 2025 BinarySmiOpInstr* binop = it.Current()->AsBinarySmiOp();
2087 if (binop->op_kind() == Token::kBIT_AND) { 2026 if (binop->op_kind() == Token::kBIT_AND) {
2088 OptimizeLeftShiftBitAndSmiOp(&it, 2027 OptimizeLeftShiftBitAndSmiOp(&it, binop, binop->left()->definition(),
2089 binop,
2090 binop->left()->definition(),
2091 binop->right()->definition()); 2028 binop->right()->definition());
2092 } else if ((binop->op_kind() == Token::kTRUNCDIV) || 2029 } else if ((binop->op_kind() == Token::kTRUNCDIV) ||
2093 (binop->op_kind() == Token::kMOD)) { 2030 (binop->op_kind() == Token::kMOD)) {
2094 if (binop->HasUses()) { 2031 if (binop->HasUses()) {
2095 div_mod_merge.Add(binop); 2032 div_mod_merge.Add(binop);
2096 } 2033 }
2097 } 2034 }
2098 } else if (it.Current()->IsBinaryMintOp()) { 2035 } else if (it.Current()->IsBinaryMintOp()) {
2099 BinaryMintOpInstr* mintop = it.Current()->AsBinaryMintOp(); 2036 BinaryMintOpInstr* mintop = it.Current()->AsBinaryMintOp();
2100 if (mintop->op_kind() == Token::kBIT_AND) { 2037 if (mintop->op_kind() == Token::kBIT_AND) {
2101 OptimizeLeftShiftBitAndSmiOp(&it, 2038 OptimizeLeftShiftBitAndSmiOp(&it, mintop,
2102 mintop,
2103 mintop->left()->definition(), 2039 mintop->left()->definition(),
2104 mintop->right()->definition()); 2040 mintop->right()->definition());
2105 } 2041 }
2106 } else if (it.Current()->IsInvokeMathCFunction()) { 2042 } else if (it.Current()->IsInvokeMathCFunction()) {
2107 InvokeMathCFunctionInstr* math_unary = 2043 InvokeMathCFunctionInstr* math_unary =
2108 it.Current()->AsInvokeMathCFunction(); 2044 it.Current()->AsInvokeMathCFunction();
2109 if ((math_unary->recognized_kind() == MethodRecognizer::kMathSin) || 2045 if ((math_unary->recognized_kind() == MethodRecognizer::kMathSin) ||
2110 (math_unary->recognized_kind() == MethodRecognizer::kMathCos)) { 2046 (math_unary->recognized_kind() == MethodRecognizer::kMathCos)) {
2111 if (math_unary->HasUses()) { 2047 if (math_unary->HasUses()) {
2112 sin_cos_merge.Add(math_unary); 2048 sin_cos_merge.Add(math_unary);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2160 if ((smi_shift_left == NULL) && (bit_and_instr->InputAt(1)->IsSingleUse())) { 2096 if ((smi_shift_left == NULL) && (bit_and_instr->InputAt(1)->IsSingleUse())) {
2161 smi_shift_left = AsSmiShiftLeftInstruction(right_instr); 2097 smi_shift_left = AsSmiShiftLeftInstruction(right_instr);
2162 } 2098 }
2163 if (smi_shift_left == NULL) return; 2099 if (smi_shift_left == NULL) return;
2164 2100
2165 // Pattern recognized. 2101 // Pattern recognized.
2166 smi_shift_left->mark_truncating(); 2102 smi_shift_left->mark_truncating();
2167 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp()); 2103 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp());
2168 if (bit_and_instr->IsBinaryMintOp()) { 2104 if (bit_and_instr->IsBinaryMintOp()) {
2169 // Replace Mint op with Smi op. 2105 // Replace Mint op with Smi op.
2170 BinarySmiOpInstr* smi_op = new(Z) BinarySmiOpInstr( 2106 BinarySmiOpInstr* smi_op = new (Z) BinarySmiOpInstr(
2171 Token::kBIT_AND, 2107 Token::kBIT_AND, new (Z) Value(left_instr), new (Z) Value(right_instr),
2172 new(Z) Value(left_instr),
2173 new(Z) Value(right_instr),
2174 Thread::kNoDeoptId); // BIT_AND cannot deoptimize. 2108 Thread::kNoDeoptId); // BIT_AND cannot deoptimize.
2175 bit_and_instr->ReplaceWith(smi_op, current_iterator); 2109 bit_and_instr->ReplaceWith(smi_op, current_iterator);
2176 } 2110 }
2177 } 2111 }
2178 2112
2179 2113
2180 // Dart: 2114 // Dart:
2181 // var x = d % 10; 2115 // var x = d % 10;
2182 // var y = d ~/ 10; 2116 // var y = d ~/ 10;
2183 // var z = x + y; 2117 // var z = x + y;
(...skipping 18 matching lines...) Expand all
2202 } 2136 }
2203 for (intptr_t i = 0; i < merge_candidates->length(); i++) { 2137 for (intptr_t i = 0; i < merge_candidates->length(); i++) {
2204 BinarySmiOpInstr* curr_instr = (*merge_candidates)[i]; 2138 BinarySmiOpInstr* curr_instr = (*merge_candidates)[i];
2205 if (curr_instr == NULL) { 2139 if (curr_instr == NULL) {
2206 // Instruction was merged already. 2140 // Instruction was merged already.
2207 continue; 2141 continue;
2208 } 2142 }
2209 ASSERT((curr_instr->op_kind() == Token::kTRUNCDIV) || 2143 ASSERT((curr_instr->op_kind() == Token::kTRUNCDIV) ||
2210 (curr_instr->op_kind() == Token::kMOD)); 2144 (curr_instr->op_kind() == Token::kMOD));
2211 // Check if there is kMOD/kTRUNDIV binop with same inputs. 2145 // Check if there is kMOD/kTRUNDIV binop with same inputs.
2212 const Token::Kind other_kind = (curr_instr->op_kind() == Token::kTRUNCDIV) ? 2146 const Token::Kind other_kind = (curr_instr->op_kind() == Token::kTRUNCDIV)
2213 Token::kMOD : Token::kTRUNCDIV; 2147 ? Token::kMOD
2148 : Token::kTRUNCDIV;
2214 Definition* left_def = curr_instr->left()->definition(); 2149 Definition* left_def = curr_instr->left()->definition();
2215 Definition* right_def = curr_instr->right()->definition(); 2150 Definition* right_def = curr_instr->right()->definition();
2216 for (intptr_t k = i + 1; k < merge_candidates->length(); k++) { 2151 for (intptr_t k = i + 1; k < merge_candidates->length(); k++) {
2217 BinarySmiOpInstr* other_binop = (*merge_candidates)[k]; 2152 BinarySmiOpInstr* other_binop = (*merge_candidates)[k];
2218 // 'other_binop' can be NULL if it was already merged. 2153 // 'other_binop' can be NULL if it was already merged.
2219 if ((other_binop != NULL) && 2154 if ((other_binop != NULL) && (other_binop->op_kind() == other_kind) &&
2220 (other_binop->op_kind() == other_kind) &&
2221 (other_binop->left()->definition() == left_def) && 2155 (other_binop->left()->definition() == left_def) &&
2222 (other_binop->right()->definition() == right_def)) { 2156 (other_binop->right()->definition() == right_def)) {
2223 (*merge_candidates)[k] = NULL; // Clear it. 2157 (*merge_candidates)[k] = NULL; // Clear it.
2224 ASSERT(curr_instr->HasUses()); 2158 ASSERT(curr_instr->HasUses());
2225 AppendExtractNthOutputForMerged( 2159 AppendExtractNthOutputForMerged(
2226 curr_instr, 2160 curr_instr, MergedMathInstr::OutputIndexOf(curr_instr->op_kind()),
2227 MergedMathInstr::OutputIndexOf(curr_instr->op_kind()),
2228 kTagged, kSmiCid); 2161 kTagged, kSmiCid);
2229 ASSERT(other_binop->HasUses()); 2162 ASSERT(other_binop->HasUses());
2230 AppendExtractNthOutputForMerged( 2163 AppendExtractNthOutputForMerged(
2231 other_binop, 2164 other_binop, MergedMathInstr::OutputIndexOf(other_binop->op_kind()),
2232 MergedMathInstr::OutputIndexOf(other_binop->op_kind()),
2233 kTagged, kSmiCid); 2165 kTagged, kSmiCid);
2234 2166
2235 ZoneGrowableArray<Value*>* args = new(Z) ZoneGrowableArray<Value*>(2); 2167 ZoneGrowableArray<Value*>* args = new (Z) ZoneGrowableArray<Value*>(2);
2236 args->Add(new(Z) Value(curr_instr->left()->definition())); 2168 args->Add(new (Z) Value(curr_instr->left()->definition()));
2237 args->Add(new(Z) Value(curr_instr->right()->definition())); 2169 args->Add(new (Z) Value(curr_instr->right()->definition()));
2238 2170
2239 // Replace with TruncDivMod. 2171 // Replace with TruncDivMod.
2240 MergedMathInstr* div_mod = new(Z) MergedMathInstr( 2172 MergedMathInstr* div_mod = new (Z) MergedMathInstr(
2241 args, 2173 args, curr_instr->deopt_id(), MergedMathInstr::kTruncDivMod);
2242 curr_instr->deopt_id(),
2243 MergedMathInstr::kTruncDivMod);
2244 curr_instr->ReplaceWith(div_mod, NULL); 2174 curr_instr->ReplaceWith(div_mod, NULL);
2245 other_binop->ReplaceUsesWith(div_mod); 2175 other_binop->ReplaceUsesWith(div_mod);
2246 other_binop->RemoveFromGraph(); 2176 other_binop->RemoveFromGraph();
2247 // Only one merge possible. Because canonicalization happens later, 2177 // Only one merge possible. Because canonicalization happens later,
2248 // more candidates are possible. 2178 // more candidates are possible.
2249 // TODO(srdjan): Allow merging of trunc-div/mod into truncDivMod. 2179 // TODO(srdjan): Allow merging of trunc-div/mod into truncDivMod.
2250 break; 2180 break;
2251 } 2181 }
2252 } 2182 }
2253 } 2183 }
(...skipping 15 matching lines...) Expand all
2269 InvokeMathCFunctionInstr* curr_instr = (*merge_candidates)[i]; 2199 InvokeMathCFunctionInstr* curr_instr = (*merge_candidates)[i];
2270 if (curr_instr == NULL) { 2200 if (curr_instr == NULL) {
2271 // Instruction was merged already. 2201 // Instruction was merged already.
2272 continue; 2202 continue;
2273 } 2203 }
2274 const MethodRecognizer::Kind kind = curr_instr->recognized_kind(); 2204 const MethodRecognizer::Kind kind = curr_instr->recognized_kind();
2275 ASSERT((kind == MethodRecognizer::kMathSin) || 2205 ASSERT((kind == MethodRecognizer::kMathSin) ||
2276 (kind == MethodRecognizer::kMathCos)); 2206 (kind == MethodRecognizer::kMathCos));
2277 // Check if there is sin/cos binop with same inputs. 2207 // Check if there is sin/cos binop with same inputs.
2278 const MethodRecognizer::Kind other_kind = 2208 const MethodRecognizer::Kind other_kind =
2279 (kind == MethodRecognizer::kMathSin) 2209 (kind == MethodRecognizer::kMathSin) ? MethodRecognizer::kMathCos
2280 ? MethodRecognizer::kMathCos : MethodRecognizer::kMathSin; 2210 : MethodRecognizer::kMathSin;
2281 Definition* def = curr_instr->InputAt(0)->definition(); 2211 Definition* def = curr_instr->InputAt(0)->definition();
2282 for (intptr_t k = i + 1; k < merge_candidates->length(); k++) { 2212 for (intptr_t k = i + 1; k < merge_candidates->length(); k++) {
2283 InvokeMathCFunctionInstr* other_op = (*merge_candidates)[k]; 2213 InvokeMathCFunctionInstr* other_op = (*merge_candidates)[k];
2284 // 'other_op' can be NULL if it was already merged. 2214 // 'other_op' can be NULL if it was already merged.
2285 if ((other_op != NULL) && (other_op->recognized_kind() == other_kind) && 2215 if ((other_op != NULL) && (other_op->recognized_kind() == other_kind) &&
2286 (other_op->InputAt(0)->definition() == def)) { 2216 (other_op->InputAt(0)->definition() == def)) {
2287 (*merge_candidates)[k] = NULL; // Clear it. 2217 (*merge_candidates)[k] = NULL; // Clear it.
2288 ASSERT(curr_instr->HasUses()); 2218 ASSERT(curr_instr->HasUses());
2289 AppendExtractNthOutputForMerged(curr_instr, 2219 AppendExtractNthOutputForMerged(curr_instr,
2290 MergedMathInstr::OutputIndexOf(kind), 2220 MergedMathInstr::OutputIndexOf(kind),
2291 kUnboxedDouble, kDoubleCid); 2221 kUnboxedDouble, kDoubleCid);
2292 ASSERT(other_op->HasUses()); 2222 ASSERT(other_op->HasUses());
2293 AppendExtractNthOutputForMerged( 2223 AppendExtractNthOutputForMerged(
2294 other_op, 2224 other_op, MergedMathInstr::OutputIndexOf(other_kind),
2295 MergedMathInstr::OutputIndexOf(other_kind),
2296 kUnboxedDouble, kDoubleCid); 2225 kUnboxedDouble, kDoubleCid);
2297 ZoneGrowableArray<Value*>* args = new(Z) ZoneGrowableArray<Value*>(1); 2226 ZoneGrowableArray<Value*>* args = new (Z) ZoneGrowableArray<Value*>(1);
2298 args->Add(new(Z) Value(curr_instr->InputAt(0)->definition())); 2227 args->Add(new (Z) Value(curr_instr->InputAt(0)->definition()));
2299 // Replace with SinCos. 2228 // Replace with SinCos.
2300 MergedMathInstr* sin_cos = 2229 MergedMathInstr* sin_cos = new (Z) MergedMathInstr(
2301 new(Z) MergedMathInstr(args, 2230 args, curr_instr->DeoptimizationTarget(), MergedMathInstr::kSinCos);
2302 curr_instr->DeoptimizationTarget(),
2303 MergedMathInstr::kSinCos);
2304 curr_instr->ReplaceWith(sin_cos, NULL); 2231 curr_instr->ReplaceWith(sin_cos, NULL);
2305 other_op->ReplaceUsesWith(sin_cos); 2232 other_op->ReplaceUsesWith(sin_cos);
2306 other_op->RemoveFromGraph(); 2233 other_op->RemoveFromGraph();
2307 // Only one merge possible. Because canonicalization happens later, 2234 // Only one merge possible. Because canonicalization happens later,
2308 // more candidates are possible. 2235 // more candidates are possible.
2309 // TODO(srdjan): Allow merging of sin/cos into sincos. 2236 // TODO(srdjan): Allow merging of sin/cos into sincos.
2310 break; 2237 break;
2311 } 2238 }
2312 } 2239 }
2313 } 2240 }
2314 } 2241 }
2315 2242
2316 2243
2317 void FlowGraph::AppendExtractNthOutputForMerged(Definition* instr, 2244 void FlowGraph::AppendExtractNthOutputForMerged(Definition* instr,
2318 intptr_t index, 2245 intptr_t index,
2319 Representation rep, 2246 Representation rep,
2320 intptr_t cid) { 2247 intptr_t cid) {
2321 ExtractNthOutputInstr* extract = 2248 ExtractNthOutputInstr* extract =
2322 new(Z) ExtractNthOutputInstr(new(Z) Value(instr), index, rep, cid); 2249 new (Z) ExtractNthOutputInstr(new (Z) Value(instr), index, rep, cid);
2323 instr->ReplaceUsesWith(extract); 2250 instr->ReplaceUsesWith(extract);
2324 InsertAfter(instr, extract, NULL, FlowGraph::kValue); 2251 InsertAfter(instr, extract, NULL, FlowGraph::kValue);
2325 } 2252 }
2326 2253
2327 2254
2328
2329
2330 } // namespace dart 2255 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph.h ('k') | runtime/vm/flow_graph_allocator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698