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

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

Issue 12638040: Compute local variable liveness before translation to SSA. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 9 months 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 | Annotate | Revision Log
« 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/flow_graph_builder.h" 8 #include "vm/flow_graph_builder.h"
9 #include "vm/intermediate_language.h" 9 #include "vm/intermediate_language.h"
10 #include "vm/longjump.h" 10 #include "vm/longjump.h"
11 #include "vm/growable_array.h" 11 #include "vm/growable_array.h"
12 12
13 namespace dart { 13 namespace dart {
14 14
15 DECLARE_FLAG(bool, trace_optimization); 15 DECLARE_FLAG(bool, trace_optimization);
16 DECLARE_FLAG(bool, verify_compiler); 16 DECLARE_FLAG(bool, verify_compiler);
17 17
18 FlowGraph::FlowGraph(const FlowGraphBuilder& builder, 18 FlowGraph::FlowGraph(const FlowGraphBuilder& builder,
19 GraphEntryInstr* graph_entry, 19 GraphEntryInstr* graph_entry,
20 intptr_t max_block_id) 20 intptr_t max_block_id)
21 : parent_(), 21 : parent_(),
22 assigned_vars_(),
23 current_ssa_temp_index_(0), 22 current_ssa_temp_index_(0),
24 max_block_id_(max_block_id), 23 max_block_id_(max_block_id),
25 parsed_function_(builder.parsed_function()), 24 parsed_function_(builder.parsed_function()),
26 num_copied_params_(builder.num_copied_params()), 25 num_copied_params_(builder.num_copied_params()),
27 num_non_copied_params_(builder.num_non_copied_params()), 26 num_non_copied_params_(builder.num_non_copied_params()),
28 num_stack_locals_(builder.num_stack_locals()), 27 num_stack_locals_(builder.num_stack_locals()),
29 graph_entry_(graph_entry), 28 graph_entry_(graph_entry),
30 preorder_(), 29 preorder_(),
31 postorder_(), 30 postorder_(),
32 reverse_postorder_(), 31 reverse_postorder_(),
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 if (env != NULL) env->DeepCopyTo(instr); 80 if (env != NULL) env->DeepCopyTo(instr);
82 } 81 }
83 82
84 83
85 void FlowGraph::DiscoverBlocks() { 84 void FlowGraph::DiscoverBlocks() {
86 // Initialize state. 85 // Initialize state.
87 preorder_.Clear(); 86 preorder_.Clear();
88 postorder_.Clear(); 87 postorder_.Clear();
89 reverse_postorder_.Clear(); 88 reverse_postorder_.Clear();
90 parent_.Clear(); 89 parent_.Clear();
91 assigned_vars_.Clear();
92 // Perform a depth-first traversal of the graph to build preorder and 90 // Perform a depth-first traversal of the graph to build preorder and
93 // postorder block orders. 91 // postorder block orders.
94 graph_entry_->DiscoverBlocks(NULL, // Entry block predecessor. 92 graph_entry_->DiscoverBlocks(NULL, // Entry block predecessor.
95 &preorder_, 93 &preorder_,
96 &postorder_, 94 &postorder_,
97 &parent_, 95 &parent_,
98 &assigned_vars_,
99 variable_count(), 96 variable_count(),
100 num_non_copied_params()); 97 num_non_copied_params());
101 // Create an array of blocks in reverse postorder. 98 // Create an array of blocks in reverse postorder.
102 intptr_t block_count = postorder_.length(); 99 intptr_t block_count = postorder_.length();
103 for (intptr_t i = 0; i < block_count; ++i) { 100 for (intptr_t i = 0; i < block_count; ++i) {
104 reverse_postorder_.Add(postorder_[block_count - i - 1]); 101 reverse_postorder_.Add(postorder_[block_count - i - 1]);
105 } 102 }
106 } 103 }
107 104
108 105
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 } 195 }
199 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 196 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
200 VerifyUseListsInInstruction(it.Current()); 197 VerifyUseListsInInstruction(it.Current());
201 } 198 }
202 } 199 }
203 return true; // Return true so we can ASSERT validation. 200 return true; // Return true so we can ASSERT validation.
204 } 201 }
205 #endif // DEBUG 202 #endif // DEBUG
206 203
207 204
205 LivenessAnalysis::LivenessAnalysis(
206 intptr_t variable_count,
207 const GrowableArray<BlockEntryInstr*>& postorder)
208 : variable_count_(variable_count),
209 postorder_(postorder),
210 live_out_(postorder.length()),
211 kill_(postorder.length()),
212 live_in_(postorder.length()) {
213 }
214
215
216 bool LivenessAnalysis::UpdateLiveOut(const BlockEntryInstr& block) {
217 BitVector* live_out = live_out_[block.postorder_number()];
218 bool changed = false;
219 Instruction* last = block.last_instruction();
220 ASSERT(last != NULL);
221 for (intptr_t i = 0; i < last->SuccessorCount(); i++) {
222 BlockEntryInstr* succ = last->SuccessorAt(i);
223 ASSERT(succ != NULL);
224 if (live_out->AddAll(live_in_[succ->postorder_number()])) {
225 changed = true;
226 }
227 }
228 return changed;
229 }
230
231
232 bool LivenessAnalysis::UpdateLiveIn(const BlockEntryInstr& block) {
233 BitVector* live_out = live_out_[block.postorder_number()];
234 BitVector* kill = kill_[block.postorder_number()];
235 BitVector* live_in = live_in_[block.postorder_number()];
236 return live_in->KillAndAdd(kill, live_out);
237 }
238
239
240 void LivenessAnalysis::ComputeLiveInAndLiveOutSets() {
241 const intptr_t block_count = postorder_.length();
242 bool changed;
243 do {
244 changed = false;
245
246 for (intptr_t i = 0; i < block_count; i++) {
247 const BlockEntryInstr& block = *postorder_[i];
248
249 // Live-in set depends only on kill set which does not
250 // change in this loop and live-out set. If live-out
251 // set does not change there is no need to recompute
252 // live-in set.
253 if (UpdateLiveOut(block) && UpdateLiveIn(block)) {
254 changed = true;
255 }
256 }
257 } while (changed);
258 }
259
260
261 void LivenessAnalysis::Analyze() {
262 const intptr_t block_count = postorder_.length();
263 for (intptr_t i = 0; i < block_count; i++) {
264 live_out_.Add(new BitVector(variable_count_));
265 kill_.Add(new BitVector(variable_count_));
266 live_in_.Add(new BitVector(variable_count_));
267 }
268
269 ComputeInitialSets();
270 ComputeLiveInAndLiveOutSets();
271 }
272
273
274 static void PrintBitVector(const char* tag, BitVector* v) {
275 OS::Print("%s:", tag);
276 for (BitVector::Iterator it(v); !it.Done(); it.Advance()) {
277 OS::Print(" %"Pd"", it.Current());
278 }
279 OS::Print("\n");
280 }
281
282
283 void LivenessAnalysis::Dump() {
284 const intptr_t block_count = postorder_.length();
285 for (intptr_t i = 0; i < block_count; i++) {
286 BlockEntryInstr* block = postorder_[i];
287 OS::Print("block @%"Pd" -> ", block->block_id());
288
289 Instruction* last = block->last_instruction();
290 for (intptr_t j = 0; j < last->SuccessorCount(); j++) {
291 BlockEntryInstr* succ = last->SuccessorAt(j);
292 OS::Print(" @%"Pd"", succ->block_id());
293 }
294 OS::Print("\n");
295
296 PrintBitVector(" live out", live_out_[i]);
297 PrintBitVector(" kill", kill_[i]);
298 PrintBitVector(" live in", live_in_[i]);
299 }
300 }
301
302
303 // Computes liveness information for local variables.
304 class VariableLivenessAnalysis : public LivenessAnalysis {
305 public:
306 explicit VariableLivenessAnalysis(FlowGraph* flow_graph)
307 : LivenessAnalysis(flow_graph->variable_count(), flow_graph->postorder()),
308 flow_graph_(flow_graph),
309 num_non_copied_params_(flow_graph->num_non_copied_params()),
310 assigned_vars_() { }
311
312 // For every block (in preorder) compute and return set of variables that
313 // have new assigned values flowing out of that block.
314 const GrowableArray<BitVector*>& ComputeAssignedVars() {
315 // We can't directly return kill_ because it uses postorder numbering while
316 // SSA construction uses preorder numbering internally.
317 // We have to permute postorder into preorder.
318 assigned_vars_.Clear();
319
320 const intptr_t block_count = flow_graph_->preorder().length();
321 for (intptr_t i = 0; i < block_count; i++) {
322 BlockEntryInstr* block = flow_graph_->preorder()[i];
323 BitVector* kill = GetKillSet(block);
324 kill->Intersect(GetLiveOutSet(block));
325 assigned_vars_.Add(kill);
326 }
327
328 return assigned_vars_;
329 }
330
331 // Returns true if the value set by the given store reaches any load from the
332 // same local variable.
333 bool IsStoreAlive(BlockEntryInstr* block, StoreLocalInstr* store) {
334 if (store->is_dead()) {
335 return false;
336 }
337
338 if (store->is_last()) {
339 const intptr_t index = store->local().BitIndexIn(num_non_copied_params_);
340 return GetLiveOutSet(block)->Contains(index);
341 }
342
343 return true;
344 }
345
346 // Returns true if the given load is the last for the local and the value
347 // of the local will not flow into another one.
348 bool IsLastLoad(BlockEntryInstr* block, LoadLocalInstr* load) {
349 const intptr_t index = load->local().BitIndexIn(num_non_copied_params_);
350 return load->is_last() && !GetLiveOutSet(block)->Contains(index);
351 }
352
353 private:
354 virtual void ComputeInitialSets();
355
356 const FlowGraph* flow_graph_;
357 const intptr_t num_non_copied_params_;
358 GrowableArray<BitVector*> assigned_vars_;
359 };
360
361
362 void VariableLivenessAnalysis::ComputeInitialSets() {
363 const intptr_t block_count = postorder_.length();
364
365 BitVector* last_loads = new BitVector(variable_count_);
366 for (intptr_t i = 0; i < block_count; i++) {
367 BlockEntryInstr* block = postorder_[i];
368
369 BitVector* kill = kill_[i];
370 BitVector* live_in = live_in_[i];
371 last_loads->Clear();
372
373 // Iterate backwards starting at the last instruction.
374 for (BackwardInstructionIterator it(block); !it.Done(); it.Advance()) {
375 Instruction* current = it.Current();
376
377 LoadLocalInstr* load = current->AsLoadLocal();
378 if (load != NULL) {
379 const intptr_t index = load->local().BitIndexIn(num_non_copied_params_);
380 live_in->Add(index);
381
382 if (!last_loads->Contains(index)) {
383 last_loads->Add(index);
384 load->mark_last();
385 }
386
387 continue;
388 }
389
390 StoreLocalInstr* store = current->AsStoreLocal();
391 if (store != NULL) {
392 const intptr_t index =
393 store->local().BitIndexIn(num_non_copied_params_);
394 if (kill->Contains(index)) {
395 if (!live_in->Contains(index)) {
396 store->mark_dead();
397 }
398 } else {
399 if (!live_in->Contains(index)) {
400 store->mark_last();
401 }
402 kill->Add(index);
403 }
404 live_in->Remove(index);
405 continue;
406 }
407 }
408 }
409 }
410
411
208 void FlowGraph::ComputeSSA(intptr_t next_virtual_register_number, 412 void FlowGraph::ComputeSSA(intptr_t next_virtual_register_number,
209 GrowableArray<Definition*>* inlining_parameters) { 413 GrowableArray<Definition*>* inlining_parameters) {
210 ASSERT((next_virtual_register_number == 0) || (inlining_parameters != NULL)); 414 ASSERT((next_virtual_register_number == 0) || (inlining_parameters != NULL));
211 current_ssa_temp_index_ = next_virtual_register_number; 415 current_ssa_temp_index_ = next_virtual_register_number;
212 GrowableArray<BitVector*> dominance_frontier; 416 GrowableArray<BitVector*> dominance_frontier;
213 ComputeDominators(&dominance_frontier); 417 ComputeDominators(&dominance_frontier);
214 InsertPhis(preorder_, assigned_vars_, dominance_frontier); 418
419 VariableLivenessAnalysis variable_liveness(this);
420 variable_liveness.Analyze();
421
422 InsertPhis(preorder_,
423 variable_liveness.ComputeAssignedVars(),
424 dominance_frontier);
425
215 GrowableArray<PhiInstr*> live_phis; 426 GrowableArray<PhiInstr*> live_phis;
427
216 // Rename uses to reference inserted phis where appropriate. 428 // Rename uses to reference inserted phis where appropriate.
217 // Collect phis that reach a non-environment use. 429 // Collect phis that reach a non-environment use.
218 Rename(&live_phis, inlining_parameters); 430 Rename(&live_phis, &variable_liveness, inlining_parameters);
431
219 // Propagate alive mark transitively from alive phis and then remove 432 // Propagate alive mark transitively from alive phis and then remove
220 // non-live ones. 433 // non-live ones.
221 RemoveDeadPhis(&live_phis); 434 RemoveDeadPhis(&live_phis);
222 } 435 }
223 436
224 437
225 // Compute immediate dominators and the dominance frontier for each basic 438 // Compute immediate dominators and the dominance frontier for each basic
226 // block. As a side effect of the algorithm, sets the immediate dominator 439 // block. As a side effect of the algorithm, sets the immediate dominator
227 // of each basic block. 440 // of each basic block.
228 // 441 //
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 worklist.Add(block); 603 worklist.Add(block);
391 } 604 }
392 } 605 }
393 } 606 }
394 } 607 }
395 } 608 }
396 } 609 }
397 610
398 611
399 void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis, 612 void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis,
613 VariableLivenessAnalysis* variable_liveness,
400 GrowableArray<Definition*>* inlining_parameters) { 614 GrowableArray<Definition*>* inlining_parameters) {
401 // TODO(fschneider): Support catch-entry. 615 // TODO(fschneider): Support catch-entry.
402 if (graph_entry_->SuccessorCount() > 1) { 616 if (graph_entry_->SuccessorCount() > 1) {
403 Bailout("Catch-entry support in SSA."); 617 Bailout("Catch-entry support in SSA.");
404 } 618 }
405 619
406 // Initial renaming environment. 620 // Initial renaming environment.
407 GrowableArray<Definition*> env(variable_count()); 621 GrowableArray<Definition*> env(variable_count());
408 622
409 // Add global constants to the initial definitions. 623 // Add global constants to the initial definitions.
(...skipping 20 matching lines...) Expand all
430 } 644 }
431 } 645 }
432 646
433 // Initialize all locals with #null in the renaming environment. 647 // Initialize all locals with #null in the renaming environment.
434 for (intptr_t i = parameter_count(); i < variable_count(); ++i) { 648 for (intptr_t i = parameter_count(); i < variable_count(); ++i) {
435 env.Add(constant_null()); 649 env.Add(constant_null());
436 } 650 }
437 651
438 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0); 652 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0);
439 ASSERT(normal_entry != NULL); // Must have entry. 653 ASSERT(normal_entry != NULL); // Must have entry.
440 RenameRecursive(normal_entry, &env, live_phis); 654 RenameRecursive(normal_entry, &env, live_phis, variable_liveness);
441 } 655 }
442 656
443 657
444 void FlowGraph::RenameRecursive(BlockEntryInstr* block_entry, 658 void FlowGraph::RenameRecursive(BlockEntryInstr* block_entry,
445 GrowableArray<Definition*>* env, 659 GrowableArray<Definition*>* env,
446 GrowableArray<PhiInstr*>* live_phis) { 660 GrowableArray<PhiInstr*>* live_phis,
661 VariableLivenessAnalysis* variable_liveness) {
447 // 1. Process phis first. 662 // 1. Process phis first.
448 if (block_entry->IsJoinEntry()) { 663 if (block_entry->IsJoinEntry()) {
449 JoinEntryInstr* join = block_entry->AsJoinEntry(); 664 JoinEntryInstr* join = block_entry->AsJoinEntry();
450 if (join->phis() != NULL) { 665 if (join->phis() != NULL) {
451 for (intptr_t i = 0; i < join->phis()->length(); ++i) { 666 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
452 PhiInstr* phi = (*join->phis())[i]; 667 PhiInstr* phi = (*join->phis())[i];
453 if (phi != NULL) { 668 if (phi != NULL) {
454 (*env)[i] = phi; 669 (*env)[i] = phi;
455 phi->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. 670 phi->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp.
456 } 671 }
457 } 672 }
458 } 673 }
459 } 674 }
460 675
461 // 2. Process normal instructions. 676 // 2. Process normal instructions.
462 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) { 677 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) {
463 Instruction* current = it.Current(); 678 Instruction* current = it.Current();
464 // Attach current environment to the instructions that can deoptimize and 679 // Attach current environment to the instructions that can deoptimize and
465 // at goto instructions. Optimizations like LICM expect an environment at 680 // at goto instructions. Optimizations like LICM expect an environment at
466 // gotos. 681 // gotos.
467 if (current->CanDeoptimize() || current->IsGoto()) { 682 if (current->CanDeoptimize() ||
683 current->IsGoto() ||
684 (current->IsBranch() &&
685 current->AsBranch()->comparison()->IsStrictCompare())) {
468 Environment* deopt_env = 686 Environment* deopt_env =
469 Environment::From(*env, 687 Environment::From(*env,
470 num_non_copied_params_, 688 num_non_copied_params_,
471 parsed_function_.function()); 689 parsed_function_.function());
472 current->SetEnvironment(deopt_env); 690 current->SetEnvironment(deopt_env);
473 for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) { 691 for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) {
474 Value* use = it.CurrentValue(); 692 Value* use = it.CurrentValue();
475 use->definition()->AddEnvUse(use); 693 use->definition()->AddEnvUse(use);
476 } 694 }
477 } 695 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
509 727
510 // 2b. Handle LoadLocal and StoreLocal. 728 // 2b. Handle LoadLocal and StoreLocal.
511 // For each LoadLocal: Remove it from the graph. 729 // For each LoadLocal: Remove it from the graph.
512 // For each StoreLocal: Remove it from the graph and update the environment. 730 // For each StoreLocal: Remove it from the graph and update the environment.
513 Definition* definition = current->AsDefinition(); 731 Definition* definition = current->AsDefinition();
514 if (definition != NULL) { 732 if (definition != NULL) {
515 LoadLocalInstr* load = definition->AsLoadLocal(); 733 LoadLocalInstr* load = definition->AsLoadLocal();
516 StoreLocalInstr* store = definition->AsStoreLocal(); 734 StoreLocalInstr* store = definition->AsStoreLocal();
517 if ((load != NULL) || (store != NULL)) { 735 if ((load != NULL) || (store != NULL)) {
518 intptr_t index; 736 intptr_t index;
737 Definition* result;
519 if (store != NULL) { 738 if (store != NULL) {
739 // Update renaming environment.
520 index = store->local().BitIndexIn(num_non_copied_params_); 740 index = store->local().BitIndexIn(num_non_copied_params_);
521 // Update renaming environment. 741 result = store->value()->definition();
522 (*env)[index] = store->value()->definition(); 742
743 if (variable_liveness->IsStoreAlive(block_entry, store)) {
744 (*env)[index] = result;
745 } else {
746 (*env)[index] = constant_null();
747 }
523 } else { 748 } else {
524 // The graph construction ensures we do not have an unused LoadLocal 749 // The graph construction ensures we do not have an unused LoadLocal
525 // computation. 750 // computation.
526 ASSERT(definition->is_used()); 751 ASSERT(definition->is_used());
527 index = load->local().BitIndexIn(num_non_copied_params_); 752 index = load->local().BitIndexIn(num_non_copied_params_);
753 result = (*env)[index];
528 754
529 PhiInstr* phi = (*env)[index]->AsPhi(); 755 PhiInstr* phi = result->AsPhi();
530 if ((phi != NULL) && !phi->is_alive()) { 756 if ((phi != NULL) && !phi->is_alive()) {
531 phi->mark_alive(); 757 phi->mark_alive();
532 live_phis->Add(phi); 758 live_phis->Add(phi);
533 } 759 }
760
761 if (variable_liveness->IsLastLoad(block_entry, load)) {
762 (*env)[index] = constant_null();
763 }
534 } 764 }
535 // Update expression stack or remove from graph. 765 // Update expression stack or remove from graph.
536 if (definition->is_used()) { 766 if (definition->is_used()) {
537 env->Add((*env)[index]); 767 env->Add(result);
538 // We remove load/store instructions when we find their use in 2a. 768 // We remove load/store instructions when we find their use in 2a.
539 } else { 769 } else {
540 it.RemoveCurrentFromGraph(); 770 it.RemoveCurrentFromGraph();
541 } 771 }
542 } else { 772 } else {
543 // Not a load or store. 773 // Not a load or store.
544 if (definition->is_used()) { 774 if (definition->is_used()) {
545 // Assign fresh SSA temporary and update expression stack. 775 // Assign fresh SSA temporary and update expression stack.
546 definition->set_ssa_temp_index(alloc_ssa_temp_index()); 776 definition->set_ssa_temp_index(alloc_ssa_temp_index());
547 env->Add(definition); 777 env->Add(definition);
548 } 778 }
549 } 779 }
550 } 780 }
551 781
552 // 2c. Handle pushed argument. 782 // 2c. Handle pushed argument.
553 PushArgumentInstr* push = current->AsPushArgument(); 783 PushArgumentInstr* push = current->AsPushArgument();
554 if (push != NULL) { 784 if (push != NULL) {
555 env->Add(push); 785 env->Add(push);
556 } 786 }
557 } 787 }
558 788
559 // 3. Process dominated blocks. 789 // 3. Process dominated blocks.
560 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) { 790 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) {
561 BlockEntryInstr* block = block_entry->dominated_blocks()[i]; 791 BlockEntryInstr* block = block_entry->dominated_blocks()[i];
562 GrowableArray<Definition*> new_env(env->length()); 792 GrowableArray<Definition*> new_env(env->length());
563 new_env.AddArray(*env); 793 new_env.AddArray(*env);
564 RenameRecursive(block, &new_env, live_phis); 794 RenameRecursive(block, &new_env, live_phis, variable_liveness);
565 } 795 }
566 796
567 // 4. Process successor block. We have edge-split form, so that only blocks 797 // 4. Process successor block. We have edge-split form, so that only blocks
568 // with one successor can have a join block as successor. 798 // with one successor can have a join block as successor.
569 if ((block_entry->last_instruction()->SuccessorCount() == 1) && 799 if ((block_entry->last_instruction()->SuccessorCount() == 1) &&
570 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) { 800 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) {
571 JoinEntryInstr* successor = 801 JoinEntryInstr* successor =
572 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry(); 802 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry();
573 intptr_t pred_index = successor->IndexOfPredecessor(block_entry); 803 intptr_t pred_index = successor->IndexOfPredecessor(block_entry);
574 ASSERT(pred_index >= 0); 804 ASSERT(pred_index >= 0);
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
725 if (!found) { 955 if (!found) {
726 result->Add(field); 956 result->Add(field);
727 } 957 }
728 } 958 }
729 } 959 }
730 960
731 return result; 961 return result;
732 } 962 }
733 963
734 } // namespace dart 964 } // 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