| 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_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_builder.h" | 10 #include "vm/flow_graph.h" |
| 11 #include "vm/flow_graph_compiler.h" | 11 #include "vm/flow_graph_compiler.h" |
| 12 #include "vm/parser.h" | 12 #include "vm/parser.h" |
| 13 | 13 |
| 14 namespace dart { | 14 namespace dart { |
| 15 | 15 |
| 16 DEFINE_FLAG(bool, print_ssa_liveness, false, | 16 DEFINE_FLAG(bool, print_ssa_liveness, false, |
| 17 "Print liveness for ssa variables."); | 17 "Print liveness for ssa variables."); |
| 18 DEFINE_FLAG(bool, trace_ssa_allocator, false, | 18 DEFINE_FLAG(bool, trace_ssa_allocator, false, |
| 19 "Trace register allocation over SSA."); | 19 "Trace register allocation over SSA."); |
| 20 DEFINE_FLAG(bool, print_ssa_liveranges, false, | 20 DEFINE_FLAG(bool, print_ssa_liveranges, false, |
| (...skipping 28 matching lines...) Expand all Loading... |
| 49 static bool IsInstructionEndPosition(intptr_t pos) { | 49 static bool IsInstructionEndPosition(intptr_t pos) { |
| 50 return (pos & 1) == 1; | 50 return (pos & 1) == 1; |
| 51 } | 51 } |
| 52 | 52 |
| 53 | 53 |
| 54 static intptr_t ToInstructionStart(intptr_t pos) { | 54 static intptr_t ToInstructionStart(intptr_t pos) { |
| 55 return (pos & ~1); | 55 return (pos & ~1); |
| 56 } | 56 } |
| 57 | 57 |
| 58 | 58 |
| 59 FlowGraphAllocator::FlowGraphAllocator( | 59 FlowGraphAllocator::FlowGraphAllocator(const FlowGraph& flow_graph) |
| 60 const GrowableArray<BlockEntryInstr*>& block_order, | 60 : flow_graph_(flow_graph), |
| 61 FlowGraphBuilder* builder) | 61 block_order_(flow_graph.reverse_postorder()), |
| 62 : builder_(builder), | 62 postorder_(flow_graph.postorder()), |
| 63 block_order_(block_order), | 63 live_out_(block_order_.length()), |
| 64 postorder_(builder->postorder_block_entries()), | 64 kill_(block_order_.length()), |
| 65 live_out_(block_order.length()), | 65 live_in_(block_order_.length()), |
| 66 kill_(block_order.length()), | 66 vreg_count_(flow_graph.max_virtual_register_number()), |
| 67 live_in_(block_order.length()), | 67 live_ranges_(flow_graph.max_virtual_register_number()), |
| 68 vreg_count_(builder->current_ssa_temp_index()), | |
| 69 live_ranges_(builder->current_ssa_temp_index()), | |
| 70 cpu_regs_(), | 68 cpu_regs_(), |
| 71 blocked_cpu_regs_() { | 69 blocked_cpu_regs_() { |
| 72 for (intptr_t i = 0; i < vreg_count_; i++) live_ranges_.Add(NULL); | 70 for (intptr_t i = 0; i < vreg_count_; i++) live_ranges_.Add(NULL); |
| 73 | 71 |
| 74 blocked_cpu_regs_[CTX] = true; | 72 blocked_cpu_regs_[CTX] = true; |
| 75 if (TMP != kNoRegister) { | 73 if (TMP != kNoRegister) { |
| 76 blocked_cpu_regs_[TMP] = true; | 74 blocked_cpu_regs_[TMP] = true; |
| 77 } | 75 } |
| 78 blocked_cpu_regs_[SPREG] = true; | 76 blocked_cpu_regs_[SPREG] = true; |
| 79 blocked_cpu_regs_[FPREG] = true; | 77 blocked_cpu_regs_[FPREG] = true; |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 // Skip parallel moves that we insert while processing instructions. | 496 // Skip parallel moves that we insert while processing instructions. |
| 499 if (!current->IsParallelMove()) { | 497 if (!current->IsParallelMove()) { |
| 500 ProcessOneInstruction(block, current); | 498 ProcessOneInstruction(block, current); |
| 501 } | 499 } |
| 502 current = current->previous(); | 500 current = current->previous(); |
| 503 } | 501 } |
| 504 | 502 |
| 505 ConnectIncomingPhiMoves(block); | 503 ConnectIncomingPhiMoves(block); |
| 506 } | 504 } |
| 507 | 505 |
| 508 const bool copied = builder_->copied_parameter_count() > 0; | |
| 509 | |
| 510 // Process incoming parameters. Do this after all other instructions so | 506 // Process incoming parameters. Do this after all other instructions so |
| 511 // that safepoints for all calls have already been found. | 507 // that safepoints for all calls have already been found. |
| 512 const intptr_t fixed_parameters_count = | |
| 513 builder_->parsed_function().function().num_fixed_parameters(); | |
| 514 | |
| 515 GraphEntryInstr* graph_entry = postorder_[block_count - 1]->AsGraphEntry(); | 508 GraphEntryInstr* graph_entry = postorder_[block_count - 1]->AsGraphEntry(); |
| 516 for (intptr_t i = 0; i < graph_entry->start_env()->values().length(); i++) { | 509 for (intptr_t i = 0; i < graph_entry->start_env()->values().length(); i++) { |
| 517 Value* val = graph_entry->start_env()->values()[i]; | 510 Value* val = graph_entry->start_env()->values()[i]; |
| 518 if (val->IsUse()) { | 511 if (val->IsUse()) { |
| 519 ParameterInstr* param = val->AsUse()->definition()->AsParameter(); | 512 ParameterInstr* param = val->AsUse()->definition()->AsParameter(); |
| 520 | 513 |
| 521 LiveRange* range = GetLiveRange(param->ssa_temp_index()); | 514 LiveRange* range = GetLiveRange(param->ssa_temp_index()); |
| 522 range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos()); | 515 range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos()); |
| 523 range->DefineAt(graph_entry->start_pos()); | 516 range->DefineAt(graph_entry->start_pos()); |
| 524 | 517 |
| 518 // Assert that copied and non-copied parameters are mutually exclusive. |
| 519 // This might change in the future and, if so, the index will be wrong. |
| 520 ASSERT(flow_graph_.copied_parameter_count() == 0 || |
| 521 flow_graph_.non_copied_parameter_count() == 0); |
| 525 // Slot index for the leftmost copied parameter is 0. | 522 // Slot index for the leftmost copied parameter is 0. |
| 526 intptr_t slot_index = param->index(); | 523 intptr_t slot_index = param->index(); |
| 527 if (!copied) { | 524 // Slot index for the rightmost fixed parameter is -1. |
| 528 // Slot index for the rightmost fixed parameter is -1. | 525 slot_index -= flow_graph_.non_copied_parameter_count(); |
| 529 slot_index -= fixed_parameters_count; | |
| 530 } | |
| 531 | 526 |
| 532 range->set_assigned_location(Location::StackSlot(slot_index)); | 527 range->set_assigned_location(Location::StackSlot(slot_index)); |
| 533 range->set_spill_slot(Location::StackSlot(slot_index)); | 528 range->set_spill_slot(Location::StackSlot(slot_index)); |
| 534 if (copied) { | 529 if (flow_graph_.copied_parameter_count() > 0) { |
| 535 ASSERT(spill_slots_.length() == slot_index); | 530 ASSERT(spill_slots_.length() == slot_index); |
| 536 spill_slots_.Add(range->End()); | 531 spill_slots_.Add(range->End()); |
| 537 } | 532 } |
| 538 | 533 |
| 539 AssignSafepoints(range); | 534 AssignSafepoints(range); |
| 540 | 535 |
| 541 range->finger()->Initialize(range); | 536 range->finger()->Initialize(range); |
| 542 UsePosition* use = range->finger()->FirstRegisterBeneficialUse( | 537 UsePosition* use = range->finger()->FirstRegisterBeneficialUse( |
| 543 graph_entry->start_pos()); | 538 graph_entry->start_pos()); |
| 544 if (use != NULL) { | 539 if (use != NULL) { |
| 545 LiveRange* tail = SplitBetween(range, | 540 LiveRange* tail = SplitBetween(range, |
| 546 graph_entry->start_pos(), | 541 graph_entry->start_pos(), |
| 547 use->pos()); | 542 use->pos()); |
| 548 AddToUnallocated(tail); | 543 AddToUnallocated(tail); |
| 549 } | 544 } |
| 550 ConvertAllUses(range); | 545 ConvertAllUses(range); |
| 551 if (copied) MarkAsObjectAtSafepoints(range); | 546 if (flow_graph_.copied_parameter_count() > 0) { |
| 547 MarkAsObjectAtSafepoints(range); |
| 548 } |
| 552 } | 549 } |
| 553 } | 550 } |
| 554 } | 551 } |
| 555 | 552 |
| 556 // | 553 // |
| 557 // When describing shape of live ranges in comments below we are going to use | 554 // When describing shape of live ranges in comments below we are going to use |
| 558 // the following notation: | 555 // the following notation: |
| 559 // | 556 // |
| 560 // B block entry | 557 // B block entry |
| 561 // g g' start and end of goto instruction | 558 // g g' start and end of goto instruction |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 739 // temporaries and output. | 736 // temporaries and output. |
| 740 void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block, | 737 void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block, |
| 741 Instruction* current) { | 738 Instruction* current) { |
| 742 const intptr_t pos = current->lifetime_position(); | 739 const intptr_t pos = current->lifetime_position(); |
| 743 ASSERT(IsInstructionStartPosition(pos)); | 740 ASSERT(IsInstructionStartPosition(pos)); |
| 744 | 741 |
| 745 LocationSummary* locs = current->locs(); | 742 LocationSummary* locs = current->locs(); |
| 746 | 743 |
| 747 // TODO(vegorov): number of inputs must match number of input locations. | 744 // TODO(vegorov): number of inputs must match number of input locations. |
| 748 if (locs->input_count() != current->InputCount()) { | 745 if (locs->input_count() != current->InputCount()) { |
| 749 builder_->Bailout("ssa allocator: number of input locations mismatch"); | 746 flow_graph_.Bailout("ssa allocator: number of input locations mismatch"); |
| 750 } | 747 } |
| 751 | 748 |
| 752 // Normalize same-as-first-input output if input is specified as | 749 // Normalize same-as-first-input output if input is specified as |
| 753 // fixed register. | 750 // fixed register. |
| 754 if (locs->out().IsUnallocated() && | 751 if (locs->out().IsUnallocated() && |
| 755 (locs->out().policy() == Location::kSameAsFirstInput) && | 752 (locs->out().policy() == Location::kSameAsFirstInput) && |
| 756 (locs->in(0).IsRegister())) { | 753 (locs->in(0).IsRegister())) { |
| 757 locs->set_out(locs->in(0)); | 754 locs->set_out(locs->in(0)); |
| 758 } | 755 } |
| 759 | 756 |
| (...skipping 1235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1995 | 1992 |
| 1996 DiscoverLoops(); | 1993 DiscoverLoops(); |
| 1997 | 1994 |
| 1998 BuildLiveRanges(); | 1995 BuildLiveRanges(); |
| 1999 | 1996 |
| 2000 if (FLAG_print_ssa_liveness) { | 1997 if (FLAG_print_ssa_liveness) { |
| 2001 DumpLiveness(); | 1998 DumpLiveness(); |
| 2002 } | 1999 } |
| 2003 | 2000 |
| 2004 if (FLAG_print_ssa_liveranges) { | 2001 if (FLAG_print_ssa_liveranges) { |
| 2005 const Function& function = builder_->parsed_function().function(); | 2002 const Function& function = flow_graph_.parsed_function().function(); |
| 2006 | 2003 |
| 2007 OS::Print("-- [before ssa allocator] ranges [%s] ---------\n", | 2004 OS::Print("-- [before ssa allocator] ranges [%s] ---------\n", |
| 2008 function.ToFullyQualifiedCString()); | 2005 function.ToFullyQualifiedCString()); |
| 2009 PrintLiveRanges(); | 2006 PrintLiveRanges(); |
| 2010 OS::Print("----------------------------------------------\n"); | 2007 OS::Print("----------------------------------------------\n"); |
| 2011 | 2008 |
| 2012 OS::Print("-- [before ssa allocator] ir [%s] -------------\n", | 2009 OS::Print("-- [before ssa allocator] ir [%s] -------------\n", |
| 2013 function.ToFullyQualifiedCString()); | 2010 function.ToFullyQualifiedCString()); |
| 2014 FlowGraphPrinter printer(Function::Handle(), block_order_, true); | 2011 FlowGraphPrinter printer(flow_graph_, true); |
| 2015 printer.PrintBlocks(); | 2012 printer.PrintBlocks(); |
| 2016 OS::Print("----------------------------------------------\n"); | 2013 OS::Print("----------------------------------------------\n"); |
| 2017 } | 2014 } |
| 2018 | 2015 |
| 2019 AllocateCPURegisters(); | 2016 AllocateCPURegisters(); |
| 2020 | 2017 |
| 2021 ResolveControlFlow(); | 2018 ResolveControlFlow(); |
| 2022 | 2019 |
| 2023 GraphEntryInstr* entry = block_order_[0]->AsGraphEntry(); | 2020 GraphEntryInstr* entry = block_order_[0]->AsGraphEntry(); |
| 2024 ASSERT(entry != NULL); | 2021 ASSERT(entry != NULL); |
| 2025 entry->set_spill_slot_count(spill_slots_.length()); | 2022 entry->set_spill_slot_count(spill_slots_.length()); |
| 2026 | 2023 |
| 2027 if (FLAG_print_ssa_liveranges) { | 2024 if (FLAG_print_ssa_liveranges) { |
| 2028 const Function& function = builder_->parsed_function().function(); | 2025 const Function& function = flow_graph_.parsed_function().function(); |
| 2029 | 2026 |
| 2030 OS::Print("-- [after ssa allocator] ranges [%s] ---------\n", | 2027 OS::Print("-- [after ssa allocator] ranges [%s] ---------\n", |
| 2031 function.ToFullyQualifiedCString()); | 2028 function.ToFullyQualifiedCString()); |
| 2032 PrintLiveRanges(); | 2029 PrintLiveRanges(); |
| 2033 OS::Print("----------------------------------------------\n"); | 2030 OS::Print("----------------------------------------------\n"); |
| 2034 | 2031 |
| 2035 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", | 2032 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", |
| 2036 function.ToFullyQualifiedCString()); | 2033 function.ToFullyQualifiedCString()); |
| 2037 FlowGraphPrinter printer(Function::Handle(), block_order_, true); | 2034 FlowGraphPrinter printer(flow_graph_, true); |
| 2038 printer.PrintBlocks(); | 2035 printer.PrintBlocks(); |
| 2039 OS::Print("----------------------------------------------\n"); | 2036 OS::Print("----------------------------------------------\n"); |
| 2040 } | 2037 } |
| 2041 } | 2038 } |
| 2042 | 2039 |
| 2043 | 2040 |
| 2044 } // namespace dart | 2041 } // namespace dart |
| OLD | NEW |