OLD | NEW |
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" |
(...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 | 545 |
546 // 2a. Handle uses: | 546 // 2a. Handle uses: |
547 // Update expression stack environment for each use. | 547 // Update expression stack environment for each use. |
548 // For each use of a LoadLocal or StoreLocal: Replace it with the value | 548 // For each use of a LoadLocal or StoreLocal: Replace it with the value |
549 // from the environment. | 549 // from the environment. |
550 for (intptr_t i = current->InputCount() - 1; i >= 0; --i) { | 550 for (intptr_t i = current->InputCount() - 1; i >= 0; --i) { |
551 Value* v = current->InputAt(i); | 551 Value* v = current->InputAt(i); |
552 // Update expression stack. | 552 // Update expression stack. |
553 ASSERT(env->length() > variable_count()); | 553 ASSERT(env->length() > variable_count()); |
554 | 554 |
555 Definition* reaching_defn = env->Last(); | 555 Definition* input_defn = env->Last(); |
556 env->RemoveLast(); | 556 env->RemoveLast(); |
557 | 557 |
558 Definition* input_defn = v->definition(); | 558 BindInstr* as_bind = v->definition()->AsBind(); |
559 if (input_defn->IsLoadLocal() || input_defn->IsStoreLocal()) { | 559 if ((as_bind != NULL) && |
| 560 (as_bind->computation()->IsLoadLocal() || |
| 561 as_bind->computation()->IsStoreLocal())) { |
560 // Remove the load/store from the graph. | 562 // Remove the load/store from the graph. |
561 input_defn->RemoveFromGraph(); | 563 as_bind->RemoveFromGraph(); |
562 // Assert we are not referencing nulls in the initial environment. | 564 // Assert we are not referencing nulls in the initial environment. |
563 ASSERT(reaching_defn->ssa_temp_index() != -1); | 565 ASSERT(input_defn->ssa_temp_index() != -1); |
564 current->SetInputAt(i, new Value(reaching_defn)); | 566 current->SetInputAt(i, new Value(input_defn)); |
565 } | 567 } |
566 } | 568 } |
567 | 569 |
568 // Drop pushed arguments for calls. | 570 // Drop pushed arguments for calls. |
569 for (intptr_t j = 0; j < current->ArgumentCount(); j++) { | 571 for (intptr_t j = 0; j < current->ArgumentCount(); j++) { |
570 env->RemoveLast(); | 572 env->RemoveLast(); |
571 } | 573 } |
572 | 574 |
573 // 2b. Handle LoadLocal and StoreLocal. | 575 // 2b. Handle LoadLocal and StoreLocal. |
574 // For each LoadLocal: Remove it from the graph. | 576 // For each LoadLocal: Remove it from the graph. |
575 // For each StoreLocal: Remove it from the graph and update the environment. | 577 // For each StoreLocal: Remove it from the graph and update the environment. |
576 Definition* definition = current->AsDefinition(); | 578 BindInstr* bind = current->AsBind(); |
577 if (definition != NULL) { | 579 if (bind != NULL) { |
578 LoadLocalInstr* load = definition->AsLoadLocal(); | 580 LoadLocalComp* load = bind->computation()->AsLoadLocal(); |
579 StoreLocalInstr* store = definition->AsStoreLocal(); | 581 StoreLocalComp* store = bind->computation()->AsStoreLocal(); |
580 if ((load != NULL) || (store != NULL)) { | 582 if ((load != NULL) || (store != NULL)) { |
581 intptr_t index; | 583 intptr_t index; |
582 if (store != NULL) { | 584 if (store != NULL) { |
583 index = store->local().BitIndexIn(non_copied_parameter_count_); | 585 index = store->local().BitIndexIn(non_copied_parameter_count_); |
584 // Update renaming environment. | 586 // Update renaming environment. |
585 (*env)[index] = store->value()->definition(); | 587 (*env)[index] = store->value()->definition(); |
586 } else { | 588 } else { |
587 // The graph construction ensures we do not have an unused LoadLocal | 589 // The graph construction ensures we do not have an unused LoadLocal |
588 // computation. | 590 // computation. |
589 ASSERT(definition->is_used()); | 591 ASSERT(bind->is_used()); |
590 index = load->local().BitIndexIn(non_copied_parameter_count_); | 592 index = load->local().BitIndexIn(non_copied_parameter_count_); |
591 | 593 |
592 PhiInstr* phi = (*env)[index]->AsPhi(); | 594 PhiInstr* phi = (*env)[index]->AsPhi(); |
593 if ((phi != NULL) && !phi->is_alive()) { | 595 if ((phi != NULL) && !phi->is_alive()) { |
594 phi->mark_alive(); | 596 phi->mark_alive(); |
595 live_phis->Add(phi); | 597 live_phis->Add(phi); |
596 } | 598 } |
597 } | 599 } |
598 // Update expression stack or remove from graph. | 600 // Update expression stack or remove from graph. |
599 if (definition->is_used()) { | 601 if (bind->is_used()) { |
600 env->Add((*env)[index]); | 602 env->Add((*env)[index]); |
601 // We remove load/store instructions when we find their use in 2a. | 603 // We remove load/store instructions when we find their use in 2a. |
602 } else { | 604 } else { |
603 it.RemoveCurrentFromGraph(); | 605 it.RemoveCurrentFromGraph(); |
604 } | 606 } |
605 } else { | 607 } else { |
606 // Not a load or store. | 608 // Not a load or store. |
607 if (definition->is_used()) { | 609 if (bind->is_used()) { |
608 // Assign fresh SSA temporary and update expression stack. | 610 // Assign fresh SSA temporary and update expression stack. |
609 definition->set_ssa_temp_index(alloc_ssa_temp_index()); | 611 bind->set_ssa_temp_index(alloc_ssa_temp_index()); |
610 env->Add(definition); | 612 env->Add(bind); |
611 } | 613 } |
612 } | 614 } |
613 } | 615 } |
614 | 616 |
615 // 2c. Handle pushed argument. | 617 // 2c. Handle pushed argument. |
616 PushArgumentInstr* push = current->AsPushArgument(); | 618 PushArgumentInstr* push = current->AsPushArgument(); |
617 if (push != NULL) { | 619 if (push != NULL) { |
618 env->Add(push); | 620 env->Add(push); |
619 } | 621 } |
620 } | 622 } |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
692 | 694 |
693 | 695 |
694 // Inline a flow graph at a call site. | 696 // Inline a flow graph at a call site. |
695 // | 697 // |
696 // Assumes the callee graph was computed with BuildGraphForInlining and | 698 // Assumes the callee graph was computed with BuildGraphForInlining and |
697 // transformed to SSA with ComputeSSAForInlining, and that the use lists have | 699 // transformed to SSA with ComputeSSAForInlining, and that the use lists have |
698 // been correctly computed. | 700 // been correctly computed. |
699 // | 701 // |
700 // After inlining the caller graph will correctly have adjusted the pre/post | 702 // After inlining the caller graph will correctly have adjusted the pre/post |
701 // orders, the dominator tree and the use lists. | 703 // orders, the dominator tree and the use lists. |
702 void FlowGraph::InlineCall(StaticCallInstr* call, FlowGraph* callee_graph) { | 704 void FlowGraph::InlineCall(BindInstr* caller_instr, |
| 705 StaticCallComp* caller_comp, |
| 706 FlowGraph* callee_graph) { |
703 ASSERT(callee_graph->exits() != NULL); | 707 ASSERT(callee_graph->exits() != NULL); |
704 ASSERT(callee_graph->graph_entry()->SuccessorCount() == 1); | 708 ASSERT(callee_graph->graph_entry()->SuccessorCount() == 1); |
705 ASSERT(callee_graph->max_virtual_register_number() > | 709 ASSERT(callee_graph->max_virtual_register_number() > |
706 max_virtual_register_number()); | 710 max_virtual_register_number()); |
707 | 711 |
708 // TODO(zerny): Implement support for callee graphs with control flow. | 712 // TODO(zerny): Implement support for callee graphs with control flow. |
709 ASSERT(callee_graph->preorder().length() == 2); | 713 ASSERT(callee_graph->preorder().length() == 2); |
710 | 714 |
711 // Adjust the SSA temp index by the callee graph's index. | 715 // Adjust the SSA temp index by the callee graph's index. |
712 current_ssa_temp_index_ = callee_graph->max_virtual_register_number(); | 716 current_ssa_temp_index_ = callee_graph->max_virtual_register_number(); |
713 | 717 |
714 TargetEntryInstr* callee_entry = callee_graph->graph_entry()->normal_entry(); | 718 TargetEntryInstr* callee_entry = callee_graph->graph_entry()->normal_entry(); |
715 ZoneGrowableArray<ReturnInstr*>* callee_exits = callee_graph->exits(); | 719 ZoneGrowableArray<ReturnInstr*>* callee_exits = callee_graph->exits(); |
716 | 720 |
717 // 1. Insert the callee graph into the caller graph. | 721 // 1. Insert the callee graph into the caller graph. |
718 if (callee_exits->length() == 1) { | 722 if (callee_exits->length() == 1) { |
719 ReturnInstr* exit = (*callee_exits)[0]; | 723 ReturnInstr* exit = (*callee_exits)[0]; |
720 // TODO(zerny): Support one exit graph containing control flow. | 724 // TODO(zerny): Support one exit graph containing control flow. |
721 ASSERT(callee_entry == GetBlockEntry(exit)); | 725 ASSERT(callee_entry == GetBlockEntry(exit)); |
722 // For just one exit, replace the uses and remove the call from the graph. | 726 // For just one exit, replace the uses and remove the call from the graph. |
723 call->ReplaceUsesWith(exit->value()->definition()); | 727 caller_instr->ReplaceUsesWith(exit->value()->definition()); |
724 Link(call->previous(), callee_entry->next()); | 728 Link(caller_instr->previous(), callee_entry->next()); |
725 Link(exit->previous(), call->next()); | 729 Link(exit->previous(), caller_instr->next()); |
726 } else { | 730 } else { |
727 // TODO(zerny): Support multiple exits. | 731 // TODO(zerny): Support multiple exits. |
728 UNREACHABLE(); | 732 UNREACHABLE(); |
729 } | 733 } |
730 | 734 |
731 // TODO(zerny): Adjust pre/post orders. | 735 // TODO(zerny): Adjust pre/post orders. |
732 // TODO(zerny): Update dominator tree. | 736 // TODO(zerny): Update dominator tree. |
733 | 737 |
734 // Remove original arguments to the call. | 738 // Remove original arguments to the call. |
735 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | 739 for (intptr_t i = 0; i < caller_comp->ArgumentCount(); ++i) { |
736 PushArgumentInstr* push = call->ArgumentAt(i); | 740 PushArgumentInstr* push = caller_comp->ArgumentAt(i); |
737 push->ReplaceUsesWith(push->value()->definition()); | 741 push->ReplaceUsesWith(push->value()->definition()); |
738 push->RemoveFromGraph(); | 742 push->RemoveFromGraph(); |
739 } | 743 } |
740 } | 744 } |
741 | 745 |
742 | 746 |
743 } // namespace dart | 747 } // namespace dart |
OLD | NEW |