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

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: addressed Srdjan's comments 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
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 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
176 Value* val = phi->InputAt(k); 176 Value* val = phi->InputAt(k);
177 if (val->BindsToConstant()) continue; 177 if (val->BindsToConstant()) continue;
178 178
179 BlockEntryInstr* pred = block->PredecessorAt(k); 179 BlockEntryInstr* pred = block->PredecessorAt(k);
180 const intptr_t use = val->definition()->ssa_temp_index(); 180 const intptr_t use = val->definition()->ssa_temp_index();
181 if (!kill_[pred->postorder_number()]->Contains(use)) { 181 if (!kill_[pred->postorder_number()]->Contains(use)) {
182 live_in_[pred->postorder_number()]->Add(use); 182 live_in_[pred->postorder_number()]->Add(use);
183 } 183 }
184 } 184 }
185 } 185 }
186 } else if (block->IsCatchBlockEntry()) {
187 // Process initial definitions.
Kevin Millikin (Google) 2013/05/08 11:42:00 It's disconcerting that locals are treated so diff
Florian Schneider 2013/05/08 17:10:55 This deals with SSA values, similar to the initial
188 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry();
189 for (intptr_t i = 0;
190 i < catch_entry->initial_definitions()->length();
191 i++) {
192 intptr_t vreg =
193 (*catch_entry->initial_definitions())[i]->ssa_temp_index();
194 kill_[catch_entry->postorder_number()]->Add(vreg);
195 live_in_[catch_entry->postorder_number()]->Remove(vreg);
196 }
186 } 197 }
187 } 198 }
188 199
189 // Process initial definitions, ie, constants and incoming parameters. 200 // Process initial definitions, ie, constants and incoming parameters.
190 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); i++) { 201 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); i++) {
191 intptr_t vreg = (*graph_entry_->initial_definitions())[i]->ssa_temp_index(); 202 intptr_t vreg = (*graph_entry_->initial_definitions())[i]->ssa_temp_index();
192 kill_[graph_entry_->postorder_number()]->Add(vreg); 203 kill_[graph_entry_->postorder_number()]->Add(vreg);
193 live_in_[graph_entry_->postorder_number()]->Remove(vreg); 204 live_in_[graph_entry_->postorder_number()]->Remove(vreg);
194 } 205 }
195 206
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 ASSERT(hint != NULL); 250 ASSERT(hint != NULL);
240 AddUse(pos, location_slot); 251 AddUse(pos, location_slot);
241 uses_->set_hint(hint); 252 uses_->set_hint(hint);
242 } 253 }
243 254
244 255
245 void LiveRange::AddUseInterval(intptr_t start, intptr_t end) { 256 void LiveRange::AddUseInterval(intptr_t start, intptr_t end) {
246 ASSERT(start < end); 257 ASSERT(start < end);
247 258
248 // Live ranges are being build by visiting instructions in post-order. 259 // Live ranges are being build by visiting instructions in post-order.
249 // This implies that use intervals will be perpended in a monotonically 260 // This implies that use intervals will be prepended in a monotonically
250 // decreasing order. 261 // decreasing order.
251 if (first_use_interval() != NULL) { 262 if (first_use_interval() != NULL) {
252 // If the first use interval and the use interval we are adding 263 // If the first use interval and the use interval we are adding
253 // touch then we can just extend the first interval to cover their 264 // touch then we can just extend the first interval to cover their
254 // union. 265 // union.
255 if (start >= first_use_interval()->start()) { 266 if (start >= first_use_interval()->start()) {
256 // The only case when we can add intervals with start greater than 267 // The only case when we can add intervals with start greater than
257 // start of an already created interval is BlockLocation. 268 // start of an already created interval is BlockLocation.
258 ASSERT((start == first_use_interval()->start()) || 269 ASSERT((start == first_use_interval()->start()) ||
259 (vreg() == kNoVirtualRegister)); 270 (vreg() == kNoVirtualRegister));
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 for (BitVector::Iterator it(liveness_.GetLiveInSetAt(i)); 497 for (BitVector::Iterator it(liveness_.GetLiveInSetAt(i));
487 !it.Done(); 498 !it.Done();
488 it.Advance()) { 499 it.Advance()) {
489 LiveRange* range = GetLiveRange(it.Current()); 500 LiveRange* range = GetLiveRange(it.Current());
490 if (HasOnlyUnconstrainedUsesInLoop(range, block_info)) { 501 if (HasOnlyUnconstrainedUsesInLoop(range, block_info)) {
491 range->MarkHasOnlyUnconstrainedUsesInLoop(block_info->loop_id()); 502 range->MarkHasOnlyUnconstrainedUsesInLoop(block_info->loop_id());
492 } 503 }
493 } 504 }
494 } 505 }
495 506
496 ConnectIncomingPhiMoves(block); 507 if (block->IsJoinEntry()) {
508 ConnectIncomingPhiMoves(block->AsJoinEntry());
509 } else if (block->IsCatchBlockEntry()) {
510 // Process initial definitions.
511 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry();
512 for (intptr_t i = 0;
513 i < catch_entry->initial_definitions()->length();
514 i++) {
515 Definition* defn = (*catch_entry->initial_definitions())[i];
Kevin Millikin (Google) 2013/05/08 11:42:00 All this code that is duplicated below should be m
Florian Schneider 2013/05/08 17:10:55 Done.
516 LiveRange* range = GetLiveRange(defn->ssa_temp_index());
517 range->DefineAt(catch_entry->start_pos()); // Defined at block entry.
518 if (defn->IsParameter()) {
519 ParameterInstr* param = defn->AsParameter();
520 // Assert that copied and non-copied parameters are mutually
521 // exclusive. This might change in the future and, if so, the
522 // index will be wrong.
523 ASSERT((flow_graph_.num_copied_params() == 0) ||
524 (flow_graph_.num_non_copied_params() == 0));
525 // Slot index for the leftmost copied parameter is 0.
526 intptr_t slot_index = param->index();
527 // Slot index for the rightmost fixed parameter is -1.
528 slot_index -= flow_graph_.num_non_copied_params();
529 range->set_assigned_location(Location::StackSlot(slot_index));
530 range->set_spill_slot(Location::StackSlot(slot_index));
531 } else {
532 ConstantInstr* constant = defn->AsConstant();
533 ASSERT(constant != NULL);
534 range->set_assigned_location(Location::Constant(constant->value()));
535 range->set_spill_slot(Location::Constant(constant->value()));
536 }
537 spill_slots_.Add(range->End());
538 quad_spill_slots_.Add(false);
539 AssignSafepoints(range);
540 range->finger()->Initialize(range);
541 UsePosition* use = range->finger()->FirstRegisterBeneficialUse(
542 catch_entry->start_pos());
543 if (use != NULL) {
544 LiveRange* tail =
545 SplitBetween(range, catch_entry->start_pos(), use->pos());
546 // Parameters and constants are tagged, so allocated to CPU registers.
547 CompleteRange(tail, Location::kRegister);
548 }
549 ConvertAllUses(range);
550 if (defn->IsParameter() && range->spill_slot().stack_index() >= 0) {
551 MarkAsObjectAtSafepoints(range);
552 }
553 }
554 }
497 } 555 }
498 556
499 // Process incoming parameters and constants. Do this after all other 557 // Process incoming parameters and constants. Do this after all other
500 // instructions so that safepoints for all calls have already been found. 558 // instructions so that safepoints for all calls have already been found.
501 GraphEntryInstr* graph_entry = flow_graph_.graph_entry(); 559 GraphEntryInstr* graph_entry = flow_graph_.graph_entry();
502 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) { 560 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) {
503 Definition* defn = (*graph_entry->initial_definitions())[i]; 561 Definition* defn = (*graph_entry->initial_definitions())[i];
504 LiveRange* range = GetLiveRange(defn->ssa_temp_index()); 562 LiveRange* range = GetLiveRange(defn->ssa_temp_index());
505 range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos()); 563 range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos());
506 range->DefineAt(graph_entry->start_pos()); 564 range->DefineAt(graph_entry->start_pos());
507 if (defn->IsParameter()) { 565 if (defn->IsParameter()) {
508 ParameterInstr* param = defn->AsParameter(); 566 ParameterInstr* param = defn->AsParameter();
509 // Assert that copied and non-copied parameters are mutually exclusive. 567 // Assert that copied and non-copied parameters are mutually exclusive.
510 // This might change in the future and, if so, the index will be wrong. 568 // This might change in the future and, if so, the index will be wrong.
511 ASSERT((flow_graph_.num_copied_params() == 0) || 569 ASSERT((flow_graph_.num_copied_params() == 0) ||
512 (flow_graph_.num_non_copied_params() == 0)); 570 (flow_graph_.num_non_copied_params() == 0));
513 // Slot index for the leftmost copied parameter is 0. 571 // Slot index for the leftmost copied parameter is 0.
514 intptr_t slot_index = param->index(); 572 intptr_t slot_index = param->index();
515 // Slot index for the rightmost fixed parameter is -1. 573 // Slot index for the rightmost fixed parameter is -1.
516 slot_index -= flow_graph_.num_non_copied_params(); 574 slot_index -= flow_graph_.num_non_copied_params();
517 575
518 range->set_assigned_location(Location::StackSlot(slot_index)); 576 range->set_assigned_location(Location::StackSlot(slot_index));
519 range->set_spill_slot(Location::StackSlot(slot_index)); 577 range->set_spill_slot(Location::StackSlot(slot_index));
520 if (flow_graph_.num_copied_params() > 0) { 578 if (flow_graph_.num_copied_params() > 0) {
521 ASSERT(spill_slots_.length() == slot_index);
522 spill_slots_.Add(range->End()); 579 spill_slots_.Add(range->End());
523 quad_spill_slots_.Add(false); 580 quad_spill_slots_.Add(false);
524 } 581 }
525 } else { 582 } else {
526 ConstantInstr* constant = defn->AsConstant(); 583 ConstantInstr* constant = defn->AsConstant();
527 ASSERT(constant != NULL); 584 ASSERT(constant != NULL);
528 range->set_assigned_location(Location::Constant(constant->value())); 585 range->set_assigned_location(Location::Constant(constant->value()));
529 range->set_spill_slot(Location::Constant(constant->value())); 586 range->set_spill_slot(Location::Constant(constant->value()));
530 } 587 }
531 AssignSafepoints(range); 588 AssignSafepoints(range);
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 move->set_src(Location::PrefersRegister()); 703 move->set_src(Location::PrefersRegister());
647 move_idx++; 704 move_idx++;
648 } 705 }
649 706
650 // Begin backward iteration with the instruction before the parallel 707 // Begin backward iteration with the instruction before the parallel
651 // move. 708 // move.
652 return goto_instr->previous(); 709 return goto_instr->previous();
653 } 710 }
654 711
655 712
656 void FlowGraphAllocator::ConnectIncomingPhiMoves(BlockEntryInstr* block) { 713 void FlowGraphAllocator::ConnectIncomingPhiMoves(JoinEntryInstr* join) {
657 // If this block is a join we need to add destinations of phi 714 // For join blocks we need to add destinations of phi resolution moves
658 // resolution moves to phi's live range so that register allocator will 715 // to phi's live range so that register allocator will fill them with moves.
659 // fill them with moves.
660 JoinEntryInstr* join = block->AsJoinEntry();
661 if (join == NULL) return;
662 716
663 // All uses are recorded at the start position in the block. 717 // All uses are recorded at the start position in the block.
664 const intptr_t pos = join->start_pos(); 718 const intptr_t pos = join->start_pos();
665 const bool is_loop_header = BlockInfoAt(join->start_pos())->is_loop_header(); 719 const bool is_loop_header = BlockInfoAt(join->start_pos())->is_loop_header();
666 intptr_t move_idx = 0; 720 intptr_t move_idx = 0;
667 for (PhiIterator it(join); !it.Done(); it.Advance()) { 721 for (PhiIterator it(join); !it.Done(); it.Advance()) {
668 PhiInstr* phi = it.Current(); 722 PhiInstr* phi = it.Current();
669 ASSERT(phi != NULL); 723 ASSERT(phi != NULL);
670 const intptr_t vreg = phi->ssa_temp_index(); 724 const intptr_t vreg = phi->ssa_temp_index();
671 ASSERT(vreg >= 0); 725 ASSERT(vreg >= 0);
672 726
673 // Expected shape of live range: 727 // Expected shape of live range:
674 // 728 //
675 // B 729 // B
676 // phi [-------- 730 // phi [--------
677 // 731 //
678 LiveRange* range = GetLiveRange(vreg); 732 LiveRange* range = GetLiveRange(vreg);
679 range->DefineAt(pos); // Shorten live range. 733 range->DefineAt(pos); // Shorten live range.
680 734
681 if (is_loop_header) range->mark_loop_phi(); 735 if (is_loop_header) range->mark_loop_phi();
682 736
683 for (intptr_t pred_idx = 0; pred_idx < phi->InputCount(); pred_idx++) { 737 for (intptr_t pred_idx = 0; pred_idx < phi->InputCount(); pred_idx++) {
684 BlockEntryInstr* pred = block->PredecessorAt(pred_idx); 738 BlockEntryInstr* pred = join->PredecessorAt(pred_idx);
685 GotoInstr* goto_instr = pred->last_instruction()->AsGoto(); 739 GotoInstr* goto_instr = pred->last_instruction()->AsGoto();
686 ASSERT((goto_instr != NULL) && (goto_instr->HasParallelMove())); 740 ASSERT((goto_instr != NULL) && (goto_instr->HasParallelMove()));
687 MoveOperands* move = 741 MoveOperands* move =
688 goto_instr->parallel_move()->MoveOperandsAt(move_idx); 742 goto_instr->parallel_move()->MoveOperandsAt(move_idx);
689 move->set_dest(Location::PrefersRegister()); 743 move->set_dest(Location::PrefersRegister());
690 range->AddUse(pos, move->dest_slot()); 744 range->AddUse(pos, move->dest_slot());
691 } 745 }
692 746
693 // All phi resolution moves are connected. Phi's live range is 747 // All phi resolution moves are connected. Phi's live range is
694 // complete. 748 // complete.
(...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after
1510 // Special care is taken to never allocate the same index to both 1564 // Special care is taken to never allocate the same index to both
1511 // double and quad spill slots as it complicates disambiguation during 1565 // double and quad spill slots as it complicates disambiguation during
1512 // parallel move resolution. 1566 // parallel move resolution.
1513 const bool need_quad = (register_kind_ == Location::kFpuRegister) && 1567 const bool need_quad = (register_kind_ == Location::kFpuRegister) &&
1514 ((range->representation() == kUnboxedFloat32x4) || 1568 ((range->representation() == kUnboxedFloat32x4) ||
1515 (range->representation() == kUnboxedUint32x4)); 1569 (range->representation() == kUnboxedUint32x4));
1516 1570
1517 // Search for a free spill slot among allocated: the value in it should be 1571 // Search for a free spill slot among allocated: the value in it should be
1518 // dead and its type should match (e.g. it should not be a part of the quad if 1572 // dead and its type should match (e.g. it should not be a part of the quad if
1519 // we are allocating normal double slot). 1573 // we are allocating normal double slot).
1520 intptr_t idx = 0; 1574 // For CPU registers we need to take reserved slots for try-catch into
1575 // account.
1576 intptr_t idx = register_kind_ == Location::kRegister
1577 ? flow_graph_.graph_entry()->fixed_slot_count()
1578 : 0;
1521 for (; idx < spill_slots_.length(); idx++) { 1579 for (; idx < spill_slots_.length(); idx++) {
1522 if ((need_quad == quad_spill_slots_[idx]) && 1580 if ((need_quad == quad_spill_slots_[idx]) &&
1523 (spill_slots_[idx] <= start)) { 1581 (spill_slots_[idx] <= start)) {
1524 break; 1582 break;
1525 } 1583 }
1526 } 1584 }
1527 1585
1528 if (idx == spill_slots_.length()) { 1586 if (idx == spill_slots_.length()) {
1529 // No free spill slot found. Allocate a new one. 1587 // No free spill slot found. Allocate a new one.
1530 spill_slots_.Add(0); 1588 spill_slots_.Add(0);
(...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after
2402 GraphEntryInstr* graph_entry = flow_graph_.graph_entry(); 2460 GraphEntryInstr* graph_entry = flow_graph_.graph_entry();
2403 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); ++i) { 2461 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); ++i) {
2404 Definition* def = (*graph_entry->initial_definitions())[i]; 2462 Definition* def = (*graph_entry->initial_definitions())[i];
2405 value_representations_[def->ssa_temp_index()] = def->representation(); 2463 value_representations_[def->ssa_temp_index()] = def->representation();
2406 } 2464 }
2407 2465
2408 for (BlockIterator it = flow_graph_.reverse_postorder_iterator(); 2466 for (BlockIterator it = flow_graph_.reverse_postorder_iterator();
2409 !it.Done(); 2467 !it.Done();
2410 it.Advance()) { 2468 it.Advance()) {
2411 BlockEntryInstr* block = it.Current(); 2469 BlockEntryInstr* block = it.Current();
2470
2471 // Catch entry.
2472 if (block->IsCatchBlockEntry()) {
2473 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry();
2474 for (intptr_t i = 0;
2475 i < catch_entry->initial_definitions()->length();
2476 ++i) {
2477 Definition* def = (*catch_entry->initial_definitions())[i];
2478 value_representations_[def->ssa_temp_index()] = def->representation();
2479 }
2480 }
2412 // Phis. 2481 // Phis.
2413 if (block->IsJoinEntry()) { 2482 if (block->IsJoinEntry()) {
2414 JoinEntryInstr* join = block->AsJoinEntry(); 2483 JoinEntryInstr* join = block->AsJoinEntry();
2415 for (PhiIterator it(join); !it.Done(); it.Advance()) { 2484 for (PhiIterator it(join); !it.Done(); it.Advance()) {
2416 PhiInstr* phi = it.Current(); 2485 PhiInstr* phi = it.Current();
2417 if ((phi != NULL) && (phi->ssa_temp_index() >= 0)) { 2486 if ((phi != NULL) && (phi->ssa_temp_index() >= 0)) {
2418 value_representations_[phi->ssa_temp_index()] = phi->representation(); 2487 value_representations_[phi->ssa_temp_index()] = phi->representation();
2419 } 2488 }
2420 } 2489 }
2421 } 2490 }
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
2500 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", 2569 OS::Print("-- [after ssa allocator] ir [%s] -------------\n",
2501 function.ToFullyQualifiedCString()); 2570 function.ToFullyQualifiedCString());
2502 FlowGraphPrinter printer(flow_graph_, true); 2571 FlowGraphPrinter printer(flow_graph_, true);
2503 printer.PrintBlocks(); 2572 printer.PrintBlocks();
2504 OS::Print("----------------------------------------------\n"); 2573 OS::Print("----------------------------------------------\n");
2505 } 2574 }
2506 } 2575 }
2507 2576
2508 2577
2509 } // namespace dart 2578 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698