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

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

Issue 14682020: Optimize functions containing try-catch. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: rebased Created 7 years, 7 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_allocator.h ('k') | runtime/vm/flow_graph_builder.cc » ('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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/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 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 Value* val = phi->InputAt(k); 171 Value* val = phi->InputAt(k);
172 if (val->BindsToConstant()) continue; 172 if (val->BindsToConstant()) continue;
173 173
174 BlockEntryInstr* pred = block->PredecessorAt(k); 174 BlockEntryInstr* pred = block->PredecessorAt(k);
175 const intptr_t use = val->definition()->ssa_temp_index(); 175 const intptr_t use = val->definition()->ssa_temp_index();
176 if (!kill_[pred->postorder_number()]->Contains(use)) { 176 if (!kill_[pred->postorder_number()]->Contains(use)) {
177 live_in_[pred->postorder_number()]->Add(use); 177 live_in_[pred->postorder_number()]->Add(use);
178 } 178 }
179 } 179 }
180 } 180 }
181 } else if (block->IsCatchBlockEntry()) {
182 // Process initial definitions.
183 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry();
184 for (intptr_t i = 0;
185 i < catch_entry->initial_definitions()->length();
186 i++) {
187 intptr_t vreg =
188 (*catch_entry->initial_definitions())[i]->ssa_temp_index();
189 kill_[catch_entry->postorder_number()]->Add(vreg);
190 live_in_[catch_entry->postorder_number()]->Remove(vreg);
191 }
181 } 192 }
182 } 193 }
183 194
184 // Process initial definitions, ie, constants and incoming parameters. 195 // Process initial definitions, ie, constants and incoming parameters.
185 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); i++) { 196 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); i++) {
186 intptr_t vreg = (*graph_entry_->initial_definitions())[i]->ssa_temp_index(); 197 intptr_t vreg = (*graph_entry_->initial_definitions())[i]->ssa_temp_index();
187 kill_[graph_entry_->postorder_number()]->Add(vreg); 198 kill_[graph_entry_->postorder_number()]->Add(vreg);
188 live_in_[graph_entry_->postorder_number()]->Remove(vreg); 199 live_in_[graph_entry_->postorder_number()]->Remove(vreg);
189 } 200 }
190 201
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 ASSERT(hint != NULL); 245 ASSERT(hint != NULL);
235 AddUse(pos, location_slot); 246 AddUse(pos, location_slot);
236 uses_->set_hint(hint); 247 uses_->set_hint(hint);
237 } 248 }
238 249
239 250
240 void LiveRange::AddUseInterval(intptr_t start, intptr_t end) { 251 void LiveRange::AddUseInterval(intptr_t start, intptr_t end) {
241 ASSERT(start < end); 252 ASSERT(start < end);
242 253
243 // Live ranges are being build by visiting instructions in post-order. 254 // Live ranges are being build by visiting instructions in post-order.
244 // This implies that use intervals will be perpended in a monotonically 255 // This implies that use intervals will be prepended in a monotonically
245 // decreasing order. 256 // decreasing order.
246 if (first_use_interval() != NULL) { 257 if (first_use_interval() != NULL) {
247 // If the first use interval and the use interval we are adding 258 // If the first use interval and the use interval we are adding
248 // touch then we can just extend the first interval to cover their 259 // touch then we can just extend the first interval to cover their
249 // union. 260 // union.
250 if (start >= first_use_interval()->start()) { 261 if (start >= first_use_interval()->start()) {
251 // The only case when we can add intervals with start greater than 262 // The only case when we can add intervals with start greater than
252 // start of an already created interval is BlockLocation. 263 // start of an already created interval is BlockLocation.
253 ASSERT((start == first_use_interval()->start()) || 264 ASSERT((start == first_use_interval()->start()) ||
254 (vreg() == kNoVirtualRegister)); 265 (vreg() == kNoVirtualRegister));
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 for (BitVector::Iterator it(liveness_.GetLiveInSetAt(i)); 492 for (BitVector::Iterator it(liveness_.GetLiveInSetAt(i));
482 !it.Done(); 493 !it.Done();
483 it.Advance()) { 494 it.Advance()) {
484 LiveRange* range = GetLiveRange(it.Current()); 495 LiveRange* range = GetLiveRange(it.Current());
485 if (HasOnlyUnconstrainedUsesInLoop(range, block_info)) { 496 if (HasOnlyUnconstrainedUsesInLoop(range, block_info)) {
486 range->MarkHasOnlyUnconstrainedUsesInLoop(block_info->loop_id()); 497 range->MarkHasOnlyUnconstrainedUsesInLoop(block_info->loop_id());
487 } 498 }
488 } 499 }
489 } 500 }
490 501
491 ConnectIncomingPhiMoves(block); 502 if (block->IsJoinEntry()) {
503 ConnectIncomingPhiMoves(block->AsJoinEntry());
504 } else if (block->IsCatchBlockEntry()) {
505 // Process initial definitions.
506 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry();
507 for (intptr_t i = 0;
508 i < catch_entry->initial_definitions()->length();
509 i++) {
510 Definition* defn = (*catch_entry->initial_definitions())[i];
511 LiveRange* range = GetLiveRange(defn->ssa_temp_index());
512 range->DefineAt(catch_entry->start_pos()); // Defined at block entry.
513
514 // Save range->End() because it may change in ProcessInitialDefinition.
515 intptr_t range_end = range->End();
516 ProcessInitialDefinition(defn, range, catch_entry);
517 spill_slots_.Add(range_end);
518 quad_spill_slots_.Add(false);
519
520 if (defn->IsParameter() && range->spill_slot().stack_index() >= 0) {
521 MarkAsObjectAtSafepoints(range);
522 }
523 }
524 }
492 } 525 }
493 526
494 // Process incoming parameters and constants. Do this after all other 527 // Process incoming parameters and constants. Do this after all other
495 // instructions so that safepoints for all calls have already been found. 528 // instructions so that safepoints for all calls have already been found.
496 GraphEntryInstr* graph_entry = flow_graph_.graph_entry(); 529 GraphEntryInstr* graph_entry = flow_graph_.graph_entry();
497 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) { 530 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) {
498 Definition* defn = (*graph_entry->initial_definitions())[i]; 531 Definition* defn = (*graph_entry->initial_definitions())[i];
499 LiveRange* range = GetLiveRange(defn->ssa_temp_index()); 532 LiveRange* range = GetLiveRange(defn->ssa_temp_index());
500 range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos()); 533 range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos());
501 range->DefineAt(graph_entry->start_pos()); 534 range->DefineAt(graph_entry->start_pos());
502 if (defn->IsParameter()) {
503 ParameterInstr* param = defn->AsParameter();
504 // Assert that copied and non-copied parameters are mutually exclusive.
505 // This might change in the future and, if so, the index will be wrong.
506 ASSERT((flow_graph_.num_copied_params() == 0) ||
507 (flow_graph_.num_non_copied_params() == 0));
508 // Slot index for the leftmost copied parameter is 0.
509 intptr_t slot_index = param->index();
510 // Slot index for the rightmost fixed parameter is -1.
511 slot_index -= flow_graph_.num_non_copied_params();
512 535
513 range->set_assigned_location(Location::StackSlot(slot_index)); 536 // Save range->End() because it may change in ProcessInitialDefinition.
514 range->set_spill_slot(Location::StackSlot(slot_index)); 537 intptr_t range_end = range->End();
515 if (flow_graph_.num_copied_params() > 0) { 538 ProcessInitialDefinition(defn, range, graph_entry);
516 ASSERT(spill_slots_.length() == slot_index); 539 if (defn->IsParameter() && flow_graph_.num_copied_params() > 0) {
517 spill_slots_.Add(range->End()); 540 spill_slots_.Add(range_end);
518 quad_spill_slots_.Add(false); 541 quad_spill_slots_.Add(false);
519 }
520 } else {
521 ConstantInstr* constant = defn->AsConstant();
522 ASSERT(constant != NULL);
523 range->set_assigned_location(Location::Constant(constant->value()));
524 range->set_spill_slot(Location::Constant(constant->value()));
525 }
526 AssignSafepoints(range);
527 range->finger()->Initialize(range);
528 UsePosition* use =
529 range->finger()->FirstRegisterBeneficialUse(graph_entry->start_pos());
530 if (use != NULL) {
531 LiveRange* tail =
532 SplitBetween(range, graph_entry->start_pos(), use->pos());
533 // Parameters and constants are tagged, so allocated to CPU registers.
534 CompleteRange(tail, Location::kRegister);
535 }
536 ConvertAllUses(range);
537 542
538 if (defn->IsParameter() && flow_graph_.num_copied_params() > 0) {
539 MarkAsObjectAtSafepoints(range); 543 MarkAsObjectAtSafepoints(range);
540 } 544 }
541 } 545 }
542 } 546 }
543 547
544 548
549 void FlowGraphAllocator::ProcessInitialDefinition(Definition* defn,
550 LiveRange* range,
551 BlockEntryInstr* block) {
552 if (defn->IsParameter()) {
553 ParameterInstr* param = defn->AsParameter();
554 // Assert that copied and non-copied parameters are mutually exclusive.
555 // This might change in the future and, if so, the index will be wrong.
556 ASSERT((flow_graph_.num_copied_params() == 0) ||
557 (flow_graph_.num_non_copied_params() == 0));
558 // Slot index for the leftmost copied parameter is 0.
559 intptr_t slot_index = param->index();
560 // Slot index for the rightmost fixed parameter is -1.
561 slot_index -= flow_graph_.num_non_copied_params();
562
563 range->set_assigned_location(Location::StackSlot(slot_index));
564 range->set_spill_slot(Location::StackSlot(slot_index));
565 } else {
566 ConstantInstr* constant = defn->AsConstant();
567 ASSERT(constant != NULL);
568 range->set_assigned_location(Location::Constant(constant->value()));
569 range->set_spill_slot(Location::Constant(constant->value()));
570 }
571 AssignSafepoints(range);
572 range->finger()->Initialize(range);
573 UsePosition* use =
574 range->finger()->FirstRegisterBeneficialUse(block->start_pos());
575 if (use != NULL) {
576 LiveRange* tail =
577 SplitBetween(range, block->start_pos(), use->pos());
578 // Parameters and constants are tagged, so allocated to CPU registers.
579 CompleteRange(tail, Location::kRegister);
580 }
581 ConvertAllUses(range);
582 }
583
584
545 static Location::Kind RegisterKindFromPolicy(Location loc) { 585 static Location::Kind RegisterKindFromPolicy(Location loc) {
546 if (loc.policy() == Location::kRequiresFpuRegister) { 586 if (loc.policy() == Location::kRequiresFpuRegister) {
547 return Location::kFpuRegister; 587 return Location::kFpuRegister;
548 } else { 588 } else {
549 return Location::kRegister; 589 return Location::kRegister;
550 } 590 }
551 } 591 }
552 592
553 593
554 static Location::Kind RegisterKindForResult(Instruction* instr) { 594 static Location::Kind RegisterKindForResult(Instruction* instr) {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
641 move->set_src(Location::PrefersRegister()); 681 move->set_src(Location::PrefersRegister());
642 move_idx++; 682 move_idx++;
643 } 683 }
644 684
645 // Begin backward iteration with the instruction before the parallel 685 // Begin backward iteration with the instruction before the parallel
646 // move. 686 // move.
647 return goto_instr->previous(); 687 return goto_instr->previous();
648 } 688 }
649 689
650 690
651 void FlowGraphAllocator::ConnectIncomingPhiMoves(BlockEntryInstr* block) { 691 void FlowGraphAllocator::ConnectIncomingPhiMoves(JoinEntryInstr* join) {
652 // If this block is a join we need to add destinations of phi 692 // For join blocks we need to add destinations of phi resolution moves
653 // resolution moves to phi's live range so that register allocator will 693 // to phi's live range so that register allocator will fill them with moves.
654 // fill them with moves.
655 JoinEntryInstr* join = block->AsJoinEntry();
656 if (join == NULL) return;
657 694
658 // All uses are recorded at the start position in the block. 695 // All uses are recorded at the start position in the block.
659 const intptr_t pos = join->start_pos(); 696 const intptr_t pos = join->start_pos();
660 const bool is_loop_header = BlockInfoAt(join->start_pos())->is_loop_header(); 697 const bool is_loop_header = BlockInfoAt(join->start_pos())->is_loop_header();
661 intptr_t move_idx = 0; 698 intptr_t move_idx = 0;
662 for (PhiIterator it(join); !it.Done(); it.Advance()) { 699 for (PhiIterator it(join); !it.Done(); it.Advance()) {
663 PhiInstr* phi = it.Current(); 700 PhiInstr* phi = it.Current();
664 ASSERT(phi != NULL); 701 ASSERT(phi != NULL);
665 const intptr_t vreg = phi->ssa_temp_index(); 702 const intptr_t vreg = phi->ssa_temp_index();
666 ASSERT(vreg >= 0); 703 ASSERT(vreg >= 0);
667 704
668 // Expected shape of live range: 705 // Expected shape of live range:
669 // 706 //
670 // B 707 // B
671 // phi [-------- 708 // phi [--------
672 // 709 //
673 LiveRange* range = GetLiveRange(vreg); 710 LiveRange* range = GetLiveRange(vreg);
674 range->DefineAt(pos); // Shorten live range. 711 range->DefineAt(pos); // Shorten live range.
675 712
676 if (is_loop_header) range->mark_loop_phi(); 713 if (is_loop_header) range->mark_loop_phi();
677 714
678 for (intptr_t pred_idx = 0; pred_idx < phi->InputCount(); pred_idx++) { 715 for (intptr_t pred_idx = 0; pred_idx < phi->InputCount(); pred_idx++) {
679 BlockEntryInstr* pred = block->PredecessorAt(pred_idx); 716 BlockEntryInstr* pred = join->PredecessorAt(pred_idx);
680 GotoInstr* goto_instr = pred->last_instruction()->AsGoto(); 717 GotoInstr* goto_instr = pred->last_instruction()->AsGoto();
681 ASSERT((goto_instr != NULL) && (goto_instr->HasParallelMove())); 718 ASSERT((goto_instr != NULL) && (goto_instr->HasParallelMove()));
682 MoveOperands* move = 719 MoveOperands* move =
683 goto_instr->parallel_move()->MoveOperandsAt(move_idx); 720 goto_instr->parallel_move()->MoveOperandsAt(move_idx);
684 move->set_dest(Location::PrefersRegister()); 721 move->set_dest(Location::PrefersRegister());
685 range->AddUse(pos, move->dest_slot()); 722 range->AddUse(pos, move->dest_slot());
686 } 723 }
687 724
688 // All phi resolution moves are connected. Phi's live range is 725 // All phi resolution moves are connected. Phi's live range is
689 // complete. 726 // complete.
(...skipping 861 matching lines...) Expand 10 before | Expand all | Expand 10 after
1551 // Special care is taken to never allocate the same index to both 1588 // Special care is taken to never allocate the same index to both
1552 // double and quad spill slots as it complicates disambiguation during 1589 // double and quad spill slots as it complicates disambiguation during
1553 // parallel move resolution. 1590 // parallel move resolution.
1554 const bool need_quad = (register_kind_ == Location::kFpuRegister) && 1591 const bool need_quad = (register_kind_ == Location::kFpuRegister) &&
1555 ((range->representation() == kUnboxedFloat32x4) || 1592 ((range->representation() == kUnboxedFloat32x4) ||
1556 (range->representation() == kUnboxedUint32x4)); 1593 (range->representation() == kUnboxedUint32x4));
1557 1594
1558 // Search for a free spill slot among allocated: the value in it should be 1595 // Search for a free spill slot among allocated: the value in it should be
1559 // dead and its type should match (e.g. it should not be a part of the quad if 1596 // dead and its type should match (e.g. it should not be a part of the quad if
1560 // we are allocating normal double slot). 1597 // we are allocating normal double slot).
1561 intptr_t idx = 0; 1598 // For CPU registers we need to take reserved slots for try-catch into
1599 // account.
1600 intptr_t idx = register_kind_ == Location::kRegister
1601 ? flow_graph_.graph_entry()->fixed_slot_count()
1602 : 0;
1562 for (; idx < spill_slots_.length(); idx++) { 1603 for (; idx < spill_slots_.length(); idx++) {
1563 if ((need_quad == quad_spill_slots_[idx]) && 1604 if ((need_quad == quad_spill_slots_[idx]) &&
1564 (spill_slots_[idx] <= start)) { 1605 (spill_slots_[idx] <= start)) {
1565 break; 1606 break;
1566 } 1607 }
1567 } 1608 }
1568 1609
1569 if (idx == spill_slots_.length()) { 1610 if (idx == spill_slots_.length()) {
1570 // No free spill slot found. Allocate a new one. 1611 // No free spill slot found. Allocate a new one.
1571 spill_slots_.Add(0); 1612 spill_slots_.Add(0);
(...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after
2443 GraphEntryInstr* graph_entry = flow_graph_.graph_entry(); 2484 GraphEntryInstr* graph_entry = flow_graph_.graph_entry();
2444 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); ++i) { 2485 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); ++i) {
2445 Definition* def = (*graph_entry->initial_definitions())[i]; 2486 Definition* def = (*graph_entry->initial_definitions())[i];
2446 value_representations_[def->ssa_temp_index()] = def->representation(); 2487 value_representations_[def->ssa_temp_index()] = def->representation();
2447 } 2488 }
2448 2489
2449 for (BlockIterator it = flow_graph_.reverse_postorder_iterator(); 2490 for (BlockIterator it = flow_graph_.reverse_postorder_iterator();
2450 !it.Done(); 2491 !it.Done();
2451 it.Advance()) { 2492 it.Advance()) {
2452 BlockEntryInstr* block = it.Current(); 2493 BlockEntryInstr* block = it.Current();
2494
2495 // Catch entry.
2496 if (block->IsCatchBlockEntry()) {
2497 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry();
2498 for (intptr_t i = 0;
2499 i < catch_entry->initial_definitions()->length();
2500 ++i) {
2501 Definition* def = (*catch_entry->initial_definitions())[i];
2502 value_representations_[def->ssa_temp_index()] = def->representation();
2503 }
2504 }
2453 // Phis. 2505 // Phis.
2454 if (block->IsJoinEntry()) { 2506 if (block->IsJoinEntry()) {
2455 JoinEntryInstr* join = block->AsJoinEntry(); 2507 JoinEntryInstr* join = block->AsJoinEntry();
2456 for (PhiIterator it(join); !it.Done(); it.Advance()) { 2508 for (PhiIterator it(join); !it.Done(); it.Advance()) {
2457 PhiInstr* phi = it.Current(); 2509 PhiInstr* phi = it.Current();
2458 if ((phi != NULL) && (phi->ssa_temp_index() >= 0)) { 2510 if ((phi != NULL) && (phi->ssa_temp_index() >= 0)) {
2459 value_representations_[phi->ssa_temp_index()] = phi->representation(); 2511 value_representations_[phi->ssa_temp_index()] = phi->representation();
2460 } 2512 }
2461 } 2513 }
2462 } 2514 }
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2539 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", 2591 OS::Print("-- [after ssa allocator] ir [%s] -------------\n",
2540 function.ToFullyQualifiedCString()); 2592 function.ToFullyQualifiedCString());
2541 FlowGraphPrinter printer(flow_graph_, true); 2593 FlowGraphPrinter printer(flow_graph_, true);
2542 printer.PrintBlocks(); 2594 printer.PrintBlocks();
2543 OS::Print("----------------------------------------------\n"); 2595 OS::Print("----------------------------------------------\n");
2544 } 2596 }
2545 } 2597 }
2546 2598
2547 2599
2548 } // namespace dart 2600 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_allocator.h ('k') | runtime/vm/flow_graph_builder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698