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

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

Issue 10894034: Make constants computations instead of values. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 3 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
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_allocator.h" 5 #include "vm/flow_graph_allocator.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 #include "vm/il_printer.h" 9 #include "vm/il_printer.h"
10 #include "vm/flow_graph.h" 10 #include "vm/flow_graph.h"
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 blocked_cpu_registers_[FPREG] = true; 83 blocked_cpu_registers_[FPREG] = true;
84 84
85 // XMM0 is used as scratch by optimized code and parallel move resolver. 85 // XMM0 is used as scratch by optimized code and parallel move resolver.
86 blocked_xmm_registers_[XMM0] = true; 86 blocked_xmm_registers_[XMM0] = true;
87 } 87 }
88 88
89 89
90 // Remove environments from the instructions which can't deoptimize. 90 // Remove environments from the instructions which can't deoptimize.
91 // Replace dead phis uses with null values in environments. 91 // Replace dead phis uses with null values in environments.
92 void FlowGraphAllocator::EliminateEnvironmentUses() { 92 void FlowGraphAllocator::EliminateEnvironmentUses() {
93 ConstantVal* null_value = new ConstantVal(Object::ZoneHandle()); 93 Definition* constant_null =
94 94 postorder_.Last()->AsGraphEntry()->constant_null();
95 for (intptr_t i = 0; i < block_order_.length(); ++i) { 95 for (intptr_t i = 0; i < block_order_.length(); ++i) {
96 BlockEntryInstr* block = block_order_[i]; 96 BlockEntryInstr* block = block_order_[i];
97
98 if (block->IsJoinEntry()) block->AsJoinEntry()->RemoveDeadPhis(); 97 if (block->IsJoinEntry()) block->AsJoinEntry()->RemoveDeadPhis();
99
100 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { 98 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
101 Instruction* current = it.Current(); 99 Instruction* current = it.Current();
102 if (current->CanDeoptimize()) { 100 if (current->CanDeoptimize()) {
103 ASSERT(current->env() != NULL); 101 ASSERT(current->env() != NULL);
104 GrowableArray<Value*>* values = current->env()->values_ptr(); 102 GrowableArray<Value*>* values = current->env()->values_ptr();
105
106 for (intptr_t i = 0; i < values->length(); i++) { 103 for (intptr_t i = 0; i < values->length(); i++) {
107 UseVal* use = (*values)[i]->AsUse(); 104 UseVal* use = (*values)[i]->AsUse();
108 if (use == NULL) continue; 105 if (use == NULL) continue;
109 106
110 Definition* def = use->definition(); 107 Definition* def = use->definition();
111
112 PushArgumentInstr* push_argument = def->AsPushArgument(); 108 PushArgumentInstr* push_argument = def->AsPushArgument();
113 if ((push_argument != NULL) && push_argument->WasEliminated()) { 109 if ((push_argument != NULL) && push_argument->WasEliminated()) {
114 (*values)[i] = push_argument->value()->CopyValue(); 110 (*values)[i] = push_argument->value()->CopyValue();
115 continue; 111 continue;
116 } 112 }
117 113
118 PhiInstr* phi = def->AsPhi(); 114 PhiInstr* phi = def->AsPhi();
119 if ((phi != NULL) && !phi->is_alive()) { 115 if ((phi != NULL) && !phi->is_alive()) {
120 (*values)[i] = null_value; 116 (*values)[i] = new UseVal(constant_null);
121 continue; 117 continue;
122 } 118 }
123 } 119 }
124 } else { 120 } else {
125 current->set_env(NULL); 121 current->set_env(NULL);
126 } 122 }
127 } 123 }
128 } 124 }
129 } 125 }
130 126
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 live_in_[pred->postorder_number()]->Add(use); 187 live_in_[pred->postorder_number()]->Add(use);
192 } 188 }
193 } 189 }
194 } 190 }
195 } 191 }
196 } 192 }
197 } 193 }
198 } 194 }
199 195
200 // Process incoming parameters. 196 // Process incoming parameters.
201 GraphEntryInstr* graph_entry = postorder_[block_count - 1]->AsGraphEntry(); 197 GraphEntryInstr* graph_entry = postorder_.Last()->AsGraphEntry();
202 for (intptr_t i = 0; i < graph_entry->start_env()->values().length(); i++) { 198 for (intptr_t i = 0; i < graph_entry->start_env()->values().length(); i++) {
203 Value* val = graph_entry->start_env()->values()[i]; 199 Value* val = graph_entry->start_env()->values()[i];
204 if (val->IsUse()) { 200 if (val->IsUse()) {
205 const intptr_t vreg = val->AsUse()->definition()->ssa_temp_index(); 201 intptr_t vreg = val->AsUse()->definition()->ssa_temp_index();
206 kill_[graph_entry->postorder_number()]->Add(vreg); 202 kill_[graph_entry->postorder_number()]->Add(vreg);
207 live_in_[graph_entry->postorder_number()]->Remove(vreg); 203 live_in_[graph_entry->postorder_number()]->Remove(vreg);
208 } 204 }
209 } 205 }
210 206
207 // Process global constants.
208 intptr_t vreg = graph_entry->constant_null()->ssa_temp_index();
209 kill_[graph_entry->postorder_number()]->Add(vreg);
210 live_in_[graph_entry->postorder_number()]->Remove(vreg);
211
211 // Update initial live_in sets to match live_out sets. Has to be 212 // Update initial live_in sets to match live_out sets. Has to be
212 // done in a separate path because of backwards branches. 213 // done in a separate path because of backwards branches.
213 for (intptr_t i = 0; i < block_count; i++) { 214 for (intptr_t i = 0; i < block_count; i++) {
214 UpdateLiveIn(*postorder_[i]); 215 UpdateLiveIn(*postorder_[i]);
215 } 216 }
216 } 217 }
217 218
218 219
219 bool FlowGraphAllocator::UpdateLiveOut(const BlockEntryInstr& instr) { 220 bool FlowGraphAllocator::UpdateLiveOut(const BlockEntryInstr& instr) {
220 BitVector* live_out = live_out_[instr.postorder_number()]; 221 BitVector* live_out = live_out_[instr.postorder_number()];
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
492 for (intptr_t i = 0; i < live_ranges_.length(); i++) { 493 for (intptr_t i = 0; i < live_ranges_.length(); i++) {
493 if (live_ranges_[i] != NULL) { 494 if (live_ranges_[i] != NULL) {
494 live_ranges_[i]->Print(); 495 live_ranges_[i]->Print();
495 } 496 }
496 } 497 }
497 } 498 }
498 499
499 500
500 void FlowGraphAllocator::BuildLiveRanges() { 501 void FlowGraphAllocator::BuildLiveRanges() {
501 const intptr_t block_count = postorder_.length(); 502 const intptr_t block_count = postorder_.length();
502 ASSERT(postorder_[block_count - 1]->IsGraphEntry()); 503 ASSERT(postorder_.Last()->IsGraphEntry());
503 for (intptr_t i = 0; i < (block_count - 1); i++) { 504 for (intptr_t i = 0; i < (block_count - 1); i++) {
504 BlockEntryInstr* block = postorder_[i]; 505 BlockEntryInstr* block = postorder_[i];
505 506
506 // For every SSA value that is live out of this block, create an interval 507 // For every SSA value that is live out of this block, create an interval
507 // that covers the whole block. It will be shortened if we encounter a 508 // that covers the whole block. It will be shortened if we encounter a
508 // definition of this value in this block. 509 // definition of this value in this block.
509 for (BitVector::Iterator it(live_out_[i]); !it.Done(); it.Advance()) { 510 for (BitVector::Iterator it(live_out_[i]); !it.Done(); it.Advance()) {
510 LiveRange* range = GetLiveRange(it.Current()); 511 LiveRange* range = GetLiveRange(it.Current());
511 range->AddUseInterval(block->start_pos(), block->end_pos()); 512 range->AddUseInterval(block->start_pos(), block->end_pos());
512 } 513 }
513 514
514 // Connect outgoing phi-moves that were created in NumberInstructions 515 // Connect outgoing phi-moves that were created in NumberInstructions
515 // and find last instruction that contributes to liveness. 516 // and find last instruction that contributes to liveness.
516 Instruction* current = ConnectOutgoingPhiMoves(block); 517 Instruction* current = ConnectOutgoingPhiMoves(block);
517 518
518 // Now process all instructions in reverse order. 519 // Now process all instructions in reverse order.
519 while (current != block) { 520 while (current != block) {
520 // Skip parallel moves that we insert while processing instructions. 521 // Skip parallel moves that we insert while processing instructions.
521 if (!current->IsParallelMove()) { 522 if (!current->IsParallelMove()) {
522 ProcessOneInstruction(block, current); 523 ProcessOneInstruction(block, current);
523 } 524 }
524 current = current->previous(); 525 current = current->previous();
525 } 526 }
526 527
527 ConnectIncomingPhiMoves(block); 528 ConnectIncomingPhiMoves(block);
528 } 529 }
529 530
530 // Process incoming parameters. Do this after all other instructions so 531 // Process incoming parameters. Do this after all other instructions so
531 // that safepoints for all calls have already been found. 532 // that safepoints for all calls have already been found.
532 GraphEntryInstr* graph_entry = postorder_[block_count - 1]->AsGraphEntry(); 533 GraphEntryInstr* graph_entry = postorder_.Last()->AsGraphEntry();
533 for (intptr_t i = 0; i < graph_entry->start_env()->values().length(); i++) { 534 for (intptr_t i = 0; i < graph_entry->start_env()->values().length(); i++) {
534 Value* val = graph_entry->start_env()->values()[i]; 535 Value* val = graph_entry->start_env()->values()[i];
535 if (val->IsUse()) { 536 ASSERT(val->IsUse());
536 ParameterInstr* param = val->AsUse()->definition()->AsParameter(); 537 ParameterInstr* param = val->AsUse()->definition()->AsParameter();
538 if (param == NULL) continue;
537 539
538 LiveRange* range = GetLiveRange(param->ssa_temp_index()); 540 // Handle the parameters specially. They are spilled on entry.
539 range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos()); 541 LiveRange* range = GetLiveRange(param->ssa_temp_index());
540 range->DefineAt(graph_entry->start_pos()); 542 range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos());
543 range->DefineAt(graph_entry->start_pos());
541 544
542 // Assert that copied and non-copied parameters are mutually exclusive. 545 // Assert that copied and non-copied parameters are mutually exclusive.
543 // This might change in the future and, if so, the index will be wrong. 546 // This might change in the future and, if so, the index will be wrong.
544 ASSERT(flow_graph_.copied_parameter_count() == 0 || 547 ASSERT(flow_graph_.copied_parameter_count() == 0 ||
545 flow_graph_.non_copied_parameter_count() == 0); 548 flow_graph_.non_copied_parameter_count() == 0);
546 // Slot index for the leftmost copied parameter is 0. 549 // Slot index for the leftmost copied parameter is 0.
547 intptr_t slot_index = param->index(); 550 intptr_t slot_index = param->index();
548 // Slot index for the rightmost fixed parameter is -1. 551 // Slot index for the rightmost fixed parameter is -1.
549 slot_index -= flow_graph_.non_copied_parameter_count(); 552 slot_index -= flow_graph_.non_copied_parameter_count();
550 553
551 range->set_assigned_location(Location::StackSlot(slot_index)); 554 range->set_assigned_location(Location::StackSlot(slot_index));
552 range->set_spill_slot(Location::StackSlot(slot_index)); 555 range->set_spill_slot(Location::StackSlot(slot_index));
553 if (flow_graph_.copied_parameter_count() > 0) { 556 if (flow_graph_.copied_parameter_count() > 0) {
554 ASSERT(spill_slots_.length() == slot_index); 557 ASSERT(spill_slots_.length() == slot_index);
555 spill_slots_.Add(range->End()); 558 spill_slots_.Add(range->End());
556 } 559 }
557 560
558 AssignSafepoints(range); 561 AssignSafepoints(range);
559 562
560 range->finger()->Initialize(range); 563 range->finger()->Initialize(range);
561 UsePosition* use = range->finger()->FirstRegisterBeneficialUse( 564 UsePosition* use =
562 graph_entry->start_pos()); 565 range->finger()->FirstRegisterBeneficialUse(graph_entry->start_pos());
563 if (use != NULL) { 566 if (use != NULL) {
564 LiveRange* tail = SplitBetween(range, 567 LiveRange* tail =
565 graph_entry->start_pos(), 568 SplitBetween(range, graph_entry->start_pos(), use->pos());
566 use->pos()); 569 // All incoming parameters are tagged.
567 570 CompleteRange(tail, Location::kRegister);
568 // All incomming parameters are tagged. 571 }
569 CompleteRange(tail, Location::kRegister); 572 ConvertAllUses(range);
570 } 573 if (flow_graph_.copied_parameter_count() > 0) {
571 ConvertAllUses(range); 574 MarkAsObjectAtSafepoints(range);
572 if (flow_graph_.copied_parameter_count() > 0) {
573 MarkAsObjectAtSafepoints(range);
574 }
575 } 575 }
576 } 576 }
577
578 // Process global constants.
579 BindInstr* null_defn = graph_entry->constant_null()->AsBind();
580 LiveRange* range = GetLiveRange(null_defn->ssa_temp_index());
581 range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos());
582 range->DefineAt(graph_entry->start_pos());
583 range->set_assigned_location(
584 Location::Constant(null_defn->computation()->AsConstant()->value()));
585 range->finger()->Initialize(range);
586 UsePosition* use =
587 range->finger()->FirstRegisterBeneficialUse(graph_entry->start_pos());
588 if (use != NULL) {
589 LiveRange* tail = SplitBetween(range, graph_entry->start_pos(), use->pos());
590 CompleteRange(tail, Location::kRegister);
591 }
592 ConvertAllUses(range);
577 } 593 }
578 594
595
579 // 596 //
580 // When describing shape of live ranges in comments below we are going to use 597 // When describing shape of live ranges in comments below we are going to use
581 // the following notation: 598 // the following notation:
582 // 599 //
583 // B block entry 600 // B block entry
584 // g g' start and end of goto instruction 601 // g g' start and end of goto instruction
585 // i i' start and end of any other instruction 602 // i i' start and end of any other instruction
586 // j j' start and end of any other instruction 603 // j j' start and end of any other instruction
587 604
588 // - body of a use interval 605 // - body of a use interval
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
626 643
627 // Record the corresponding phi input use for each phi. 644 // Record the corresponding phi input use for each phi.
628 ZoneGrowableArray<PhiInstr*>* phis = join->phis(); 645 ZoneGrowableArray<PhiInstr*>* phis = join->phis();
629 intptr_t move_idx = 0; 646 intptr_t move_idx = 0;
630 for (intptr_t phi_idx = 0; phi_idx < phis->length(); phi_idx++) { 647 for (intptr_t phi_idx = 0; phi_idx < phis->length(); phi_idx++) {
631 PhiInstr* phi = (*phis)[phi_idx]; 648 PhiInstr* phi = (*phis)[phi_idx];
632 if (phi == NULL) continue; 649 if (phi == NULL) continue;
633 650
634 Value* val = phi->InputAt(pred_idx); 651 Value* val = phi->InputAt(pred_idx);
635 MoveOperands* move = parallel_move->MoveOperandsAt(move_idx); 652 MoveOperands* move = parallel_move->MoveOperandsAt(move_idx);
636 if (val->IsUse()) { 653 ASSERT(val->IsUse());
637 // Expected shape of live ranges: 654 // Expected shape of live ranges:
638 // 655 //
639 // g g' 656 // g g'
640 // value --* 657 // value --*
641 // 658 //
642 659
643 LiveRange* range = GetLiveRange( 660 LiveRange* range =
644 val->AsUse()->definition()->ssa_temp_index()); 661 GetLiveRange(val->AsUse()->definition()->ssa_temp_index());
645 662
646 range->AddUseInterval(block->start_pos(), pos); 663 range->AddUseInterval(block->start_pos(), pos);
647 range->AddHintedUse(pos, move->src_slot(), move->dest_slot()); 664 range->AddHintedUse(pos, move->src_slot(), move->dest_slot());
648 665
649 move->set_src(Location::PrefersRegister()); 666 move->set_src(Location::PrefersRegister());
650 } else {
651 ASSERT(val->IsConstant());
652 move->set_src(Location::Constant(val->AsConstant()->value()));
653 }
654 move_idx++; 667 move_idx++;
655 } 668 }
656 669
657 // Begin backward iteration with the instruction before the parallel 670 // Begin backward iteration with the instruction before the parallel
658 // move. 671 // move.
659 return goto_instr->previous(); 672 return goto_instr->previous();
660 } 673 }
661 674
662 675
663 void FlowGraphAllocator::ConnectIncomingPhiMoves(BlockEntryInstr* block) { 676 void FlowGraphAllocator::ConnectIncomingPhiMoves(BlockEntryInstr* block) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 if (values.length() == 0) return; 742 if (values.length() == 0) return;
730 743
731 const intptr_t block_start_pos = block->start_pos(); 744 const intptr_t block_start_pos = block->start_pos();
732 const intptr_t use_pos = current->lifetime_position() + 1; 745 const intptr_t use_pos = current->lifetime_position() + 1;
733 746
734 Location* locations = 747 Location* locations =
735 Isolate::Current()->current_zone()->Alloc<Location>(values.length()); 748 Isolate::Current()->current_zone()->Alloc<Location>(values.length());
736 749
737 for (intptr_t i = 0; i < values.length(); ++i) { 750 for (intptr_t i = 0; i < values.length(); ++i) {
738 Value* value = values[i]; 751 Value* value = values[i];
739 if (value->IsUse()) { 752 ASSERT(value->IsUse());
740 locations[i] = Location::Any(); 753 locations[i] = Location::Any();
741 Definition* def = value->AsUse()->definition(); 754 Definition* def = value->AsUse()->definition();
742 755
743 if (def->IsPushArgument()) { 756 if (def->IsPushArgument()) {
744 // Frame size is unknown until after allocation. 757 // Frame size is unknown until after allocation.
745 locations[i] = Location::NoLocation(); 758 locations[i] = Location::NoLocation();
746 continue; 759 continue;
747 } 760 }
748 761
749 const intptr_t vreg = def->ssa_temp_index(); 762 const intptr_t vreg = def->ssa_temp_index();
750 LiveRange* range = GetLiveRange(vreg); 763 LiveRange* range = GetLiveRange(vreg);
751 range->AddUseInterval(block_start_pos, use_pos); 764 range->AddUseInterval(block_start_pos, use_pos);
752 range->AddUse(use_pos, &locations[i]); 765 range->AddUse(use_pos, &locations[i]);
753 } else {
754 ASSERT(value->IsConstant());
755 locations[i] = Location::NoLocation();
756 }
757 } 766 }
758 767
759 env->set_locations(locations); 768 env->set_locations(locations);
760 } 769 }
761 770
762 771
763 static Location::Kind RegisterKindFromPolicy(Location loc) { 772 static Location::Kind RegisterKindFromPolicy(Location loc) {
764 if (loc.policy() == Location::kRequiresXmmRegister) { 773 if (loc.policy() == Location::kRequiresXmmRegister) {
765 return Location::kXmmRegister; 774 return Location::kXmmRegister;
766 } else { 775 } else {
(...skipping 1380 matching lines...) Expand 10 before | Expand all | Expand 10 after
2147 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", 2156 OS::Print("-- [after ssa allocator] ir [%s] -------------\n",
2148 function.ToFullyQualifiedCString()); 2157 function.ToFullyQualifiedCString());
2149 FlowGraphPrinter printer(flow_graph_, true); 2158 FlowGraphPrinter printer(flow_graph_, true);
2150 printer.PrintBlocks(); 2159 printer.PrintBlocks();
2151 OS::Print("----------------------------------------------\n"); 2160 OS::Print("----------------------------------------------\n");
2152 } 2161 }
2153 } 2162 }
2154 2163
2155 2164
2156 } // namespace dart 2165 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698