| 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.h" | 10 #include "vm/flow_graph.h" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 #else | 28 #else |
| 29 #define TRACE_ALLOC(statement) | 29 #define TRACE_ALLOC(statement) |
| 30 #endif | 30 #endif |
| 31 | 31 |
| 32 | 32 |
| 33 static const intptr_t kNoVirtualRegister = -1; | 33 static const intptr_t kNoVirtualRegister = -1; |
| 34 static const intptr_t kTempVirtualRegister = -2; | 34 static const intptr_t kTempVirtualRegister = -2; |
| 35 static const intptr_t kIllegalPosition = -1; | 35 static const intptr_t kIllegalPosition = -1; |
| 36 static const intptr_t kMaxPosition = 0x7FFFFFFF; | 36 static const intptr_t kMaxPosition = 0x7FFFFFFF; |
| 37 | 37 |
| 38 // Number of stack slots needed for a double spill slot. |
| 39 static const intptr_t kDoubleSpillSlotFactor = kDoubleSize / kWordSize; |
| 40 |
| 38 | 41 |
| 39 static intptr_t MinPosition(intptr_t a, intptr_t b) { | 42 static intptr_t MinPosition(intptr_t a, intptr_t b) { |
| 40 return (a < b) ? a : b; | 43 return (a < b) ? a : b; |
| 41 } | 44 } |
| 42 | 45 |
| 43 | 46 |
| 44 static bool IsInstructionStartPosition(intptr_t pos) { | 47 static bool IsInstructionStartPosition(intptr_t pos) { |
| 45 return (pos & 1) == 0; | 48 return (pos & 1) == 0; |
| 46 } | 49 } |
| 47 | 50 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 59 FlowGraphAllocator::FlowGraphAllocator(const FlowGraph& flow_graph) | 62 FlowGraphAllocator::FlowGraphAllocator(const FlowGraph& flow_graph) |
| 60 : flow_graph_(flow_graph), | 63 : flow_graph_(flow_graph), |
| 61 block_order_(flow_graph.reverse_postorder()), | 64 block_order_(flow_graph.reverse_postorder()), |
| 62 postorder_(flow_graph.postorder()), | 65 postorder_(flow_graph.postorder()), |
| 63 live_out_(block_order_.length()), | 66 live_out_(block_order_.length()), |
| 64 kill_(block_order_.length()), | 67 kill_(block_order_.length()), |
| 65 live_in_(block_order_.length()), | 68 live_in_(block_order_.length()), |
| 66 vreg_count_(flow_graph.max_virtual_register_number()), | 69 vreg_count_(flow_graph.max_virtual_register_number()), |
| 67 live_ranges_(flow_graph.max_virtual_register_number()), | 70 live_ranges_(flow_graph.max_virtual_register_number()), |
| 68 cpu_regs_(), | 71 cpu_regs_(), |
| 69 blocked_cpu_regs_() { | 72 xmm_regs_(), |
| 73 blocked_cpu_registers_(), |
| 74 blocked_xmm_registers_(), |
| 75 cpu_spill_slot_count_(0) { |
| 70 for (intptr_t i = 0; i < vreg_count_; i++) live_ranges_.Add(NULL); | 76 for (intptr_t i = 0; i < vreg_count_; i++) live_ranges_.Add(NULL); |
| 71 | 77 |
| 72 blocked_cpu_regs_[CTX] = true; | 78 blocked_cpu_registers_[CTX] = true; |
| 73 if (TMP != kNoRegister) { | 79 if (TMP != kNoRegister) { |
| 74 blocked_cpu_regs_[TMP] = true; | 80 blocked_cpu_registers_[TMP] = true; |
| 75 } | 81 } |
| 76 blocked_cpu_regs_[SPREG] = true; | 82 blocked_cpu_registers_[SPREG] = true; |
| 77 blocked_cpu_regs_[FPREG] = true; | 83 blocked_cpu_registers_[FPREG] = true; |
| 84 |
| 85 // XMM0 is used as scratch by optimized code and parallel move resolver. |
| 86 blocked_xmm_registers_[XMM0] = true; |
| 78 } | 87 } |
| 79 | 88 |
| 80 | 89 |
| 81 // Remove environments from the instructions which can't deoptimize. | 90 // Remove environments from the instructions which can't deoptimize. |
| 82 // Replace dead phis uses with null values in environments. | 91 // Replace dead phis uses with null values in environments. |
| 83 void FlowGraphAllocator::EliminateEnvironmentUses() { | 92 void FlowGraphAllocator::EliminateEnvironmentUses() { |
| 84 ConstantVal* null_value = new ConstantVal(Object::ZoneHandle()); | 93 ConstantVal* null_value = new ConstantVal(Object::ZoneHandle()); |
| 85 | 94 |
| 86 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 95 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 87 BlockEntryInstr* block = block_order_[i]; | 96 BlockEntryInstr* block = block_order_[i]; |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 OS::Print("\n"); | 297 OS::Print("\n"); |
| 289 | 298 |
| 290 PrintBitVector(" live out", live_out_[i]); | 299 PrintBitVector(" live out", live_out_[i]); |
| 291 PrintBitVector(" kill", kill_[i]); | 300 PrintBitVector(" kill", kill_[i]); |
| 292 PrintBitVector(" live in", live_in_[i]); | 301 PrintBitVector(" live in", live_in_[i]); |
| 293 } | 302 } |
| 294 } | 303 } |
| 295 | 304 |
| 296 | 305 |
| 297 void LiveRange::AddUse(intptr_t pos, Location* location_slot) { | 306 void LiveRange::AddUse(intptr_t pos, Location* location_slot) { |
| 307 ASSERT(location_slot != NULL); |
| 298 ASSERT((first_use_interval_->start_ <= pos) && | 308 ASSERT((first_use_interval_->start_ <= pos) && |
| 299 (pos <= first_use_interval_->end_)); | 309 (pos <= first_use_interval_->end_)); |
| 300 if ((uses_ != NULL) && (uses_->pos() == pos)) { | 310 if ((uses_ != NULL) && |
| 301 if ((location_slot == NULL) || (uses_->location_slot() == location_slot)) { | 311 (uses_->pos() == pos) && |
| 302 return; | 312 (uses_->location_slot() == location_slot)) { |
| 303 } else if (uses_->location_slot() == NULL) { | 313 return; |
| 304 uses_->set_location_slot(location_slot); | |
| 305 return; | |
| 306 } | |
| 307 } | 314 } |
| 308 uses_ = new UsePosition(pos, uses_, location_slot); | 315 uses_ = new UsePosition(pos, uses_, location_slot); |
| 309 } | 316 } |
| 310 | 317 |
| 311 | 318 |
| 312 void LiveRange::AddSafepoint(intptr_t pos, LocationSummary* locs) { | 319 void LiveRange::AddSafepoint(intptr_t pos, LocationSummary* locs) { |
| 313 SafepointPosition* safepoint = new SafepointPosition(pos, locs); | 320 SafepointPosition* safepoint = new SafepointPosition(pos, locs); |
| 314 | 321 |
| 315 if (first_safepoint_ == NULL) { | 322 if (first_safepoint_ == NULL) { |
| 316 ASSERT(last_safepoint_ == NULL); | 323 ASSERT(last_safepoint_ == NULL); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 399 | 406 |
| 400 LiveRange* FlowGraphAllocator::MakeLiveRangeForTemporary() { | 407 LiveRange* FlowGraphAllocator::MakeLiveRangeForTemporary() { |
| 401 LiveRange* range = new LiveRange(kTempVirtualRegister); | 408 LiveRange* range = new LiveRange(kTempVirtualRegister); |
| 402 #if defined(DEBUG) | 409 #if defined(DEBUG) |
| 403 temporaries_.Add(range); | 410 temporaries_.Add(range); |
| 404 #endif | 411 #endif |
| 405 return range; | 412 return range; |
| 406 } | 413 } |
| 407 | 414 |
| 408 | 415 |
| 416 void FlowGraphAllocator::BlockRegisterLocation(Location loc, |
| 417 intptr_t from, |
| 418 intptr_t to, |
| 419 bool* blocked_registers, |
| 420 LiveRange** blocking_ranges) { |
| 421 if (blocked_registers[loc.register_code()]) { |
| 422 return; |
| 423 } |
| 424 |
| 425 if (blocking_ranges[loc.register_code()] == NULL) { |
| 426 LiveRange* range = new LiveRange(kNoVirtualRegister); |
| 427 blocking_ranges[loc.register_code()] = range; |
| 428 range->set_assigned_location(loc); |
| 429 #if defined(DEBUG) |
| 430 temporaries_.Add(range); |
| 431 #endif |
| 432 } |
| 433 |
| 434 blocking_ranges[loc.register_code()]->AddUseInterval(from, to); |
| 435 } |
| 436 |
| 437 |
| 409 // Block location from the start of the instruction to its end. | 438 // Block location from the start of the instruction to its end. |
| 410 void FlowGraphAllocator::BlockLocation(Location loc, | 439 void FlowGraphAllocator::BlockLocation(Location loc, |
| 411 intptr_t from, | 440 intptr_t from, |
| 412 intptr_t to) { | 441 intptr_t to) { |
| 413 ASSERT(loc.IsRegister()); | 442 if (loc.IsRegister()) { |
| 414 const Register reg = loc.reg(); | 443 BlockRegisterLocation(loc, from, to, blocked_cpu_registers_, cpu_regs_); |
| 415 if (blocked_cpu_regs_[reg]) return; | 444 } else if (loc.IsXmmRegister()) { |
| 416 if (cpu_regs_[reg].length() == 0) { | 445 BlockRegisterLocation(loc, from, to, blocked_xmm_registers_, xmm_regs_); |
| 417 LiveRange* range = new LiveRange(kNoVirtualRegister); | 446 } else { |
| 418 cpu_regs_[reg].Add(range); | 447 UNREACHABLE(); |
| 419 range->set_assigned_location(loc); | |
| 420 #if defined(DEBUG) | |
| 421 temporaries_.Add(range); | |
| 422 #endif | |
| 423 } | 448 } |
| 424 cpu_regs_[reg][0]->AddUseInterval(from, to); | |
| 425 } | 449 } |
| 426 | 450 |
| 427 | 451 |
| 428 void LiveRange::Print() { | 452 void LiveRange::Print() { |
| 429 if (first_use_interval() == NULL) { | 453 if (first_use_interval() == NULL) { |
| 430 return; | 454 return; |
| 431 } | 455 } |
| 432 | 456 |
| 433 OS::Print(" live range v%d [%d, %d) in ", vreg(), Start(), End()); | 457 OS::Print(" live range v%d [%d, %d) in ", vreg(), Start(), End()); |
| 434 assigned_location().Print(); | 458 assigned_location().Print(); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 533 | 557 |
| 534 AssignSafepoints(range); | 558 AssignSafepoints(range); |
| 535 | 559 |
| 536 range->finger()->Initialize(range); | 560 range->finger()->Initialize(range); |
| 537 UsePosition* use = range->finger()->FirstRegisterBeneficialUse( | 561 UsePosition* use = range->finger()->FirstRegisterBeneficialUse( |
| 538 graph_entry->start_pos()); | 562 graph_entry->start_pos()); |
| 539 if (use != NULL) { | 563 if (use != NULL) { |
| 540 LiveRange* tail = SplitBetween(range, | 564 LiveRange* tail = SplitBetween(range, |
| 541 graph_entry->start_pos(), | 565 graph_entry->start_pos(), |
| 542 use->pos()); | 566 use->pos()); |
| 543 AddToUnallocated(tail); | 567 |
| 568 // All incomming parameters are tagged. |
| 569 CompleteRange(tail, Location::kRegister); |
| 544 } | 570 } |
| 545 ConvertAllUses(range); | 571 ConvertAllUses(range); |
| 546 if (flow_graph_.copied_parameter_count() > 0) { | 572 if (flow_graph_.copied_parameter_count() > 0) { |
| 547 MarkAsObjectAtSafepoints(range); | 573 MarkAsObjectAtSafepoints(range); |
| 548 } | 574 } |
| 549 } | 575 } |
| 550 } | 576 } |
| 551 } | 577 } |
| 552 | 578 |
| 553 // | 579 // |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 ASSERT((goto_instr != NULL) && (goto_instr->HasParallelMove())); | 694 ASSERT((goto_instr != NULL) && (goto_instr->HasParallelMove())); |
| 669 MoveOperands* move = | 695 MoveOperands* move = |
| 670 goto_instr->parallel_move()->MoveOperandsAt(move_idx); | 696 goto_instr->parallel_move()->MoveOperandsAt(move_idx); |
| 671 move->set_dest(Location::PrefersRegister()); | 697 move->set_dest(Location::PrefersRegister()); |
| 672 range->AddUse(pos, move->dest_slot()); | 698 range->AddUse(pos, move->dest_slot()); |
| 673 } | 699 } |
| 674 | 700 |
| 675 // All phi resolution moves are connected. Phi's live range is | 701 // All phi resolution moves are connected. Phi's live range is |
| 676 // complete. | 702 // complete. |
| 677 AssignSafepoints(range); | 703 AssignSafepoints(range); |
| 678 AddToUnallocated(range); | 704 |
| 705 // TODO(vegorov): unboxed double phis. |
| 706 CompleteRange(range, Location::kRegister); |
| 679 | 707 |
| 680 move_idx++; | 708 move_idx++; |
| 681 } | 709 } |
| 682 } | 710 } |
| 683 } | 711 } |
| 684 | 712 |
| 685 | 713 |
| 686 void FlowGraphAllocator::ProcessEnvironmentUses(BlockEntryInstr* block, | 714 void FlowGraphAllocator::ProcessEnvironmentUses(BlockEntryInstr* block, |
| 687 Instruction* current) { | 715 Instruction* current) { |
| 688 ASSERT(current->env() != NULL); | 716 ASSERT(current->env() != NULL); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 725 } else { | 753 } else { |
| 726 ASSERT(value->IsConstant()); | 754 ASSERT(value->IsConstant()); |
| 727 locations[i] = Location::NoLocation(); | 755 locations[i] = Location::NoLocation(); |
| 728 } | 756 } |
| 729 } | 757 } |
| 730 | 758 |
| 731 env->set_locations(locations); | 759 env->set_locations(locations); |
| 732 } | 760 } |
| 733 | 761 |
| 734 | 762 |
| 763 static Location::Kind RegisterKindFromPolicy(Location loc) { |
| 764 if (loc.policy() == Location::kRequiresXmmRegister) { |
| 765 return Location::kXmmRegister; |
| 766 } else { |
| 767 return Location::kRegister; |
| 768 } |
| 769 } |
| 770 |
| 771 |
| 772 static Location::Kind RegisterKindForResult(Instruction* instr) { |
| 773 if (instr->representation() == kUnboxedDouble) { |
| 774 return Location::kXmmRegister; |
| 775 } else { |
| 776 return Location::kRegister; |
| 777 } |
| 778 } |
| 779 |
| 780 |
| 735 // Create and update live ranges corresponding to instruction's inputs, | 781 // Create and update live ranges corresponding to instruction's inputs, |
| 736 // temporaries and output. | 782 // temporaries and output. |
| 737 void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block, | 783 void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block, |
| 738 Instruction* current) { | 784 Instruction* current) { |
| 739 const intptr_t pos = current->lifetime_position(); | 785 const intptr_t pos = current->lifetime_position(); |
| 740 ASSERT(IsInstructionStartPosition(pos)); | 786 ASSERT(IsInstructionStartPosition(pos)); |
| 741 | 787 |
| 742 LocationSummary* locs = current->locs(); | 788 LocationSummary* locs = current->locs(); |
| 743 | 789 |
| 744 // Number of input locations and number of input operands have to agree. | 790 // Number of input locations and number of input operands have to agree. |
| 745 ASSERT(locs->input_count() == current->InputCount()); | 791 ASSERT(locs->input_count() == current->InputCount()); |
| 746 | 792 |
| 747 // Normalize same-as-first-input output if input is specified as | 793 // Normalize same-as-first-input output if input is specified as |
| 748 // fixed register. | 794 // fixed register. |
| 749 if (locs->out().IsUnallocated() && | 795 if (locs->out().IsUnallocated() && |
| 750 (locs->out().policy() == Location::kSameAsFirstInput) && | 796 (locs->out().policy() == Location::kSameAsFirstInput) && |
| 751 (locs->in(0).IsRegister())) { | 797 (locs->in(0).IsMachineRegister())) { |
| 752 locs->set_out(locs->in(0)); | 798 locs->set_out(locs->in(0)); |
| 753 } | 799 } |
| 754 | 800 |
| 755 const bool output_same_as_first_input = | 801 const bool output_same_as_first_input = |
| 756 locs->out().IsUnallocated() && | 802 locs->out().IsUnallocated() && |
| 757 (locs->out().policy() == Location::kSameAsFirstInput); | 803 (locs->out().policy() == Location::kSameAsFirstInput); |
| 758 | 804 |
| 759 // Add uses from the deoptimization environment. | 805 // Add uses from the deoptimization environment. |
| 760 if (current->env() != NULL) ProcessEnvironmentUses(block, current); | 806 if (current->env() != NULL) ProcessEnvironmentUses(block, current); |
| 761 | 807 |
| 762 // Process inputs. | 808 // Process inputs. |
| 763 // Skip the first input if output is specified with kSameAsFirstInput policy, | 809 // Skip the first input if output is specified with kSameAsFirstInput policy, |
| 764 // they will be processed together at the very end. | 810 // they will be processed together at the very end. |
| 765 for (intptr_t j = output_same_as_first_input ? 1 : 0; | 811 for (intptr_t j = output_same_as_first_input ? 1 : 0; |
| 766 j < current->InputCount(); | 812 j < current->InputCount(); |
| 767 j++) { | 813 j++) { |
| 768 Value* input = current->InputAt(j); | 814 Value* input = current->InputAt(j); |
| 769 ASSERT(input->IsUse()); // Can not be a constant currently. | 815 ASSERT(input->IsUse()); // Can not be a constant currently. |
| 770 const intptr_t vreg = input->AsUse()->definition()->ssa_temp_index(); | 816 const intptr_t vreg = input->AsUse()->definition()->ssa_temp_index(); |
| 771 LiveRange* range = GetLiveRange(vreg); | 817 LiveRange* range = GetLiveRange(vreg); |
| 772 | 818 |
| 773 Location* in_ref = locs->in_slot(j); | 819 Location* in_ref = locs->in_slot(j); |
| 774 | 820 |
| 775 if (in_ref->IsRegister()) { | 821 if (in_ref->IsMachineRegister()) { |
| 776 // Input is expected in a fixed register. Expected shape of | 822 // Input is expected in a fixed register. Expected shape of |
| 777 // live ranges: | 823 // live ranges: |
| 778 // | 824 // |
| 779 // j' i i' | 825 // j' i i' |
| 780 // value --* | 826 // value --* |
| 781 // register [-----) | 827 // register [-----) |
| 782 // | 828 // |
| 783 MoveOperands* move = | 829 MoveOperands* move = |
| 784 AddMoveAt(pos - 1, *in_ref, Location::Any()); | 830 AddMoveAt(pos - 1, *in_ref, Location::Any()); |
| 785 BlockLocation(*in_ref, pos - 1, pos + 1); | 831 BlockLocation(*in_ref, pos - 1, pos + 1); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 800 | 846 |
| 801 // Process temps. | 847 // Process temps. |
| 802 for (intptr_t j = 0; j < locs->temp_count(); j++) { | 848 for (intptr_t j = 0; j < locs->temp_count(); j++) { |
| 803 // Expected shape of live range: | 849 // Expected shape of live range: |
| 804 // | 850 // |
| 805 // i i' | 851 // i i' |
| 806 // [--) | 852 // [--) |
| 807 // | 853 // |
| 808 | 854 |
| 809 Location temp = locs->temp(j); | 855 Location temp = locs->temp(j); |
| 810 if (temp.IsRegister()) { | 856 if (temp.IsMachineRegister()) { |
| 811 BlockLocation(temp, pos, pos + 1); | 857 BlockLocation(temp, pos, pos + 1); |
| 812 } else if (temp.IsUnallocated()) { | 858 } else if (temp.IsUnallocated()) { |
| 813 LiveRange* range = MakeLiveRangeForTemporary(); | 859 LiveRange* range = MakeLiveRangeForTemporary(); |
| 814 range->AddUseInterval(pos, pos + 1); | 860 range->AddUseInterval(pos, pos + 1); |
| 815 range->AddUse(pos, locs->temp_slot(j)); | 861 range->AddUse(pos, locs->temp_slot(j)); |
| 816 AddToUnallocated(range); | 862 CompleteRange(range, RegisterKindFromPolicy(temp)); |
| 817 } else { | 863 } else { |
| 818 UNREACHABLE(); | 864 UNREACHABLE(); |
| 819 } | 865 } |
| 820 } | 866 } |
| 821 | 867 |
| 822 // Block all allocatable registers for calls and record the stack bitmap. | 868 // Block all allocatable registers for calls and record the stack bitmap. |
| 823 if (locs->always_calls()) { | 869 if (locs->always_calls()) { |
| 824 // Expected shape of live range: | 870 // Expected shape of live range: |
| 825 // | 871 // |
| 826 // i i' | 872 // i i' |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 865 } | 911 } |
| 866 | 912 |
| 867 // We might have a definition without use. We do not assign SSA index to | 913 // We might have a definition without use. We do not assign SSA index to |
| 868 // such definitions. | 914 // such definitions. |
| 869 LiveRange* range = (def->ssa_temp_index() >= 0) ? | 915 LiveRange* range = (def->ssa_temp_index() >= 0) ? |
| 870 GetLiveRange(def->ssa_temp_index()) : | 916 GetLiveRange(def->ssa_temp_index()) : |
| 871 MakeLiveRangeForTemporary(); | 917 MakeLiveRangeForTemporary(); |
| 872 Location* out = locs->out_slot(); | 918 Location* out = locs->out_slot(); |
| 873 | 919 |
| 874 // Process output and finalize its liverange. | 920 // Process output and finalize its liverange. |
| 875 if (out->IsRegister()) { | 921 if (out->IsMachineRegister()) { |
| 876 // Fixed output location. Expected shape of live range: | 922 // Fixed output location. Expected shape of live range: |
| 877 // | 923 // |
| 878 // i i' j j' | 924 // i i' j j' |
| 879 // register [--) | 925 // register [--) |
| 880 // output [------- | 926 // output [------- |
| 881 // | 927 // |
| 882 BlockLocation(*out, pos, pos + 1); | 928 BlockLocation(*out, pos, pos + 1); |
| 883 | 929 |
| 884 if (range->vreg() == kTempVirtualRegister) return; | 930 if (range->vreg() == kTempVirtualRegister) return; |
| 885 | 931 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 908 MoveOperands* move = AddMoveAt(pos + 1, Location::Any(), *out); | 954 MoveOperands* move = AddMoveAt(pos + 1, Location::Any(), *out); |
| 909 range->AddHintedUse(pos + 1, move->dest_slot(), out); | 955 range->AddHintedUse(pos + 1, move->dest_slot(), out); |
| 910 } else if (output_same_as_first_input) { | 956 } else if (output_same_as_first_input) { |
| 911 // Output register will contain a value of the first input at instruction's | 957 // Output register will contain a value of the first input at instruction's |
| 912 // start. Expected shape of live ranges: | 958 // start. Expected shape of live ranges: |
| 913 // | 959 // |
| 914 // i i' | 960 // i i' |
| 915 // input #0 --* | 961 // input #0 --* |
| 916 // output [---- | 962 // output [---- |
| 917 // | 963 // |
| 918 ASSERT(locs->in_slot(0)->Equals(Location::RequiresRegister())); | 964 ASSERT(locs->in(0).Equals(Location::RequiresRegister()) || |
| 965 locs->in(0).Equals(Location::RequiresXmmRegister())); |
| 919 | 966 |
| 920 // Create move that will copy value between input and output. | 967 // Create move that will copy value between input and output. |
| 921 locs->set_out(Location::RequiresRegister()); | 968 locs->set_out(Location::RequiresRegister()); |
| 922 MoveOperands* move = AddMoveAt(pos, | 969 MoveOperands* move = AddMoveAt(pos, |
| 923 Location::RequiresRegister(), | 970 Location::RequiresRegister(), |
| 924 Location::Any()); | 971 Location::Any()); |
| 925 | 972 |
| 926 // Add uses to the live range of the input. | 973 // Add uses to the live range of the input. |
| 927 Value* input = current->InputAt(0); | 974 Value* input = current->InputAt(0); |
| 928 ASSERT(input->IsUse()); // Can not be a constant currently. | 975 ASSERT(input->IsUse()); // Can not be a constant currently. |
| 929 LiveRange* input_range = GetLiveRange( | 976 LiveRange* input_range = GetLiveRange( |
| 930 input->AsUse()->definition()->ssa_temp_index()); | 977 input->AsUse()->definition()->ssa_temp_index()); |
| 931 input_range->AddUseInterval(block->start_pos(), pos); | 978 input_range->AddUseInterval(block->start_pos(), pos); |
| 932 input_range->AddUse(pos, move->src_slot()); | 979 input_range->AddUse(pos, move->src_slot()); |
| 933 | 980 |
| 934 // Shorten output live range to the point of definition and add both input | 981 // Shorten output live range to the point of definition and add both input |
| 935 // and output uses slots to be filled by allocator. | 982 // and output uses slots to be filled by allocator. |
| 936 range->DefineAt(pos); | 983 range->DefineAt(pos); |
| 937 range->AddUse(pos, out); | 984 range->AddHintedUse(pos, out, move->src_slot()); |
| 938 range->AddUse(pos, move->dest_slot()); | 985 range->AddUse(pos, move->dest_slot()); |
| 939 range->AddUse(pos, locs->in_slot(0)); | 986 range->AddUse(pos, locs->in_slot(0)); |
| 940 } else { | 987 } else { |
| 941 // Normal unallocated location that requires a register. Expected shape of | 988 // Normal unallocated location that requires a register. Expected shape of |
| 942 // live range: | 989 // live range: |
| 943 // | 990 // |
| 944 // i i' | 991 // i i' |
| 945 // output [------- | 992 // output [------- |
| 946 // | 993 // |
| 947 ASSERT(out->IsUnallocated() && | 994 ASSERT(locs->out().Equals(Location::RequiresRegister()) || |
| 948 (out->policy() == Location::kRequiresRegister)); | 995 locs->out().Equals(Location::RequiresXmmRegister())); |
| 949 | 996 |
| 950 // Shorten live range to the point of definition and add use to be filled by | 997 // Shorten live range to the point of definition and add use to be filled by |
| 951 // allocator. | 998 // allocator. |
| 952 range->DefineAt(pos); | 999 range->DefineAt(pos); |
| 953 range->AddUse(pos, out); | 1000 range->AddUse(pos, out); |
| 954 } | 1001 } |
| 955 | 1002 |
| 956 AssignSafepoints(range); | 1003 AssignSafepoints(range); |
| 957 AddToUnallocated(range); | 1004 CompleteRange(range, RegisterKindForResult(current)); |
| 958 } | 1005 } |
| 959 | 1006 |
| 960 | 1007 |
| 961 static ParallelMoveInstr* CreateParallelMoveBefore(Instruction* instr, | 1008 static ParallelMoveInstr* CreateParallelMoveBefore(Instruction* instr, |
| 962 intptr_t pos) { | 1009 intptr_t pos) { |
| 963 ASSERT(pos > 0); | 1010 ASSERT(pos > 0); |
| 964 Instruction* prev = instr->previous(); | 1011 Instruction* prev = instr->previous(); |
| 965 ParallelMoveInstr* move = prev->AsParallelMove(); | 1012 ParallelMoveInstr* move = prev->AsParallelMove(); |
| 966 if ((move == NULL) || (move->lifetime_position() != pos)) { | 1013 if ((move == NULL) || (move->lifetime_position() != pos)) { |
| 967 move = new ParallelMoveInstr(); | 1014 move = new ParallelMoveInstr(); |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1142 } | 1189 } |
| 1143 return use; | 1190 return use; |
| 1144 } | 1191 } |
| 1145 | 1192 |
| 1146 | 1193 |
| 1147 UsePosition* AllocationFinger::FirstRegisterUse(intptr_t after) { | 1194 UsePosition* AllocationFinger::FirstRegisterUse(intptr_t after) { |
| 1148 for (UsePosition* use = FirstUseAfter(first_register_use_, after); | 1195 for (UsePosition* use = FirstUseAfter(first_register_use_, after); |
| 1149 use != NULL; | 1196 use != NULL; |
| 1150 use = use->next()) { | 1197 use = use->next()) { |
| 1151 Location* loc = use->location_slot(); | 1198 Location* loc = use->location_slot(); |
| 1152 if ((loc != NULL) && | 1199 if (loc->IsUnallocated() && |
| 1153 loc->IsUnallocated() && | |
| 1154 (loc->policy() == Location::kRequiresRegister)) { | 1200 (loc->policy() == Location::kRequiresRegister)) { |
| 1155 first_register_use_ = use; | 1201 first_register_use_ = use; |
| 1156 return use; | 1202 return use; |
| 1157 } | 1203 } |
| 1158 } | 1204 } |
| 1159 return NULL; | 1205 return NULL; |
| 1160 } | 1206 } |
| 1161 | 1207 |
| 1162 | 1208 |
| 1163 UsePosition* AllocationFinger::FirstRegisterBeneficialUse(intptr_t after) { | 1209 UsePosition* AllocationFinger::FirstRegisterBeneficialUse(intptr_t after) { |
| 1164 for (UsePosition* use = FirstUseAfter(first_register_beneficial_use_, after); | 1210 for (UsePosition* use = FirstUseAfter(first_register_beneficial_use_, after); |
| 1165 use != NULL; | 1211 use != NULL; |
| 1166 use = use->next()) { | 1212 use = use->next()) { |
| 1167 Location* loc = use->location_slot(); | 1213 Location* loc = use->location_slot(); |
| 1168 if ((loc != NULL) && | 1214 if (loc->IsUnallocated() && loc->IsRegisterBeneficial()) { |
| 1169 (loc->IsRegister() || | |
| 1170 (loc->IsUnallocated() && loc->IsRegisterBeneficial()))) { | |
| 1171 first_register_beneficial_use_ = use; | 1215 first_register_beneficial_use_ = use; |
| 1172 return use; | 1216 return use; |
| 1173 } | 1217 } |
| 1174 } | 1218 } |
| 1175 return NULL; | 1219 return NULL; |
| 1176 } | 1220 } |
| 1177 | 1221 |
| 1178 | 1222 |
| 1179 void AllocationFinger::UpdateAfterSplit(intptr_t first_use_after_split_pos) { | 1223 void AllocationFinger::UpdateAfterSplit(intptr_t first_use_after_split_pos) { |
| 1180 if ((first_register_use_ != NULL) && | 1224 if ((first_register_use_ != NULL) && |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1389 | 1433 |
| 1390 if (idx == spill_slots_.length()) spill_slots_.Add(0); | 1434 if (idx == spill_slots_.length()) spill_slots_.Add(0); |
| 1391 | 1435 |
| 1392 LiveRange* last_sibling = range; | 1436 LiveRange* last_sibling = range; |
| 1393 while (last_sibling->next_sibling() != NULL) { | 1437 while (last_sibling->next_sibling() != NULL) { |
| 1394 last_sibling = last_sibling->next_sibling(); | 1438 last_sibling = last_sibling->next_sibling(); |
| 1395 } | 1439 } |
| 1396 | 1440 |
| 1397 spill_slots_[idx] = last_sibling->End(); | 1441 spill_slots_[idx] = last_sibling->End(); |
| 1398 | 1442 |
| 1399 range->set_spill_slot(Location::StackSlot(idx)); | 1443 if (register_kind_ == Location::kRegister) { |
| 1444 range->set_spill_slot(Location::StackSlot(idx)); |
| 1445 } else { |
| 1446 range->set_spill_slot( |
| 1447 Location::DoubleStackSlot( |
| 1448 cpu_spill_slot_count_ + idx * kDoubleSpillSlotFactor)); |
| 1449 } |
| 1400 | 1450 |
| 1401 spilled_.Add(range); | 1451 spilled_.Add(range); |
| 1402 } | 1452 } |
| 1403 | 1453 |
| 1404 | 1454 |
| 1405 void FlowGraphAllocator::MarkAsObjectAtSafepoints(LiveRange* range) { | 1455 void FlowGraphAllocator::MarkAsObjectAtSafepoints(LiveRange* range) { |
| 1406 intptr_t stack_index = range->spill_slot().stack_index(); | 1456 intptr_t stack_index = range->spill_slot().stack_index(); |
| 1407 ASSERT(stack_index >= 0); | 1457 ASSERT(stack_index >= 0); |
| 1408 | 1458 |
| 1409 while (range != NULL) { | 1459 while (range != NULL) { |
| 1410 for (SafepointPosition* safepoint = range->first_safepoint(); | 1460 for (SafepointPosition* safepoint = range->first_safepoint(); |
| 1411 safepoint != NULL; | 1461 safepoint != NULL; |
| 1412 safepoint = safepoint->next()) { | 1462 safepoint = safepoint->next()) { |
| 1413 safepoint->locs()->stack_bitmap()->Set(stack_index, true); | 1463 safepoint->locs()->stack_bitmap()->Set(stack_index, true); |
| 1414 } | 1464 } |
| 1415 range = range->next_sibling(); | 1465 range = range->next_sibling(); |
| 1416 } | 1466 } |
| 1417 } | 1467 } |
| 1418 | 1468 |
| 1419 | 1469 |
| 1420 void FlowGraphAllocator::Spill(LiveRange* range) { | 1470 void FlowGraphAllocator::Spill(LiveRange* range) { |
| 1421 LiveRange* parent = GetLiveRange(range->vreg()); | 1471 LiveRange* parent = GetLiveRange(range->vreg()); |
| 1422 if (parent->spill_slot().IsInvalid()) { | 1472 if (parent->spill_slot().IsInvalid()) { |
| 1423 AllocateSpillSlotFor(parent); | 1473 AllocateSpillSlotFor(parent); |
| 1424 MarkAsObjectAtSafepoints(parent); | 1474 if (register_kind_ == Location::kRegister) { |
| 1475 MarkAsObjectAtSafepoints(parent); |
| 1476 } |
| 1425 } | 1477 } |
| 1426 range->set_assigned_location(parent->spill_slot()); | 1478 range->set_assigned_location(parent->spill_slot()); |
| 1427 ConvertAllUses(range); | 1479 ConvertAllUses(range); |
| 1428 } | 1480 } |
| 1429 | 1481 |
| 1430 | 1482 |
| 1431 intptr_t FlowGraphAllocator::FirstIntersectionWithAllocated( | 1483 intptr_t FlowGraphAllocator::FirstIntersectionWithAllocated( |
| 1432 Register reg, LiveRange* unallocated) { | 1484 intptr_t reg, LiveRange* unallocated) { |
| 1433 intptr_t intersection = kMaxPosition; | 1485 intptr_t intersection = kMaxPosition; |
| 1434 for (intptr_t i = 0; i < cpu_regs_[reg].length(); i++) { | 1486 for (intptr_t i = 0; i < registers_[reg].length(); i++) { |
| 1435 LiveRange* allocated = cpu_regs_[reg][i]; | 1487 LiveRange* allocated = registers_[reg][i]; |
| 1436 if (allocated == NULL) continue; | 1488 if (allocated == NULL) continue; |
| 1437 | 1489 |
| 1438 UseInterval* allocated_head = | 1490 UseInterval* allocated_head = |
| 1439 allocated->finger()->first_pending_use_interval(); | 1491 allocated->finger()->first_pending_use_interval(); |
| 1440 if (allocated_head->start() >= intersection) continue; | 1492 if (allocated_head->start() >= intersection) continue; |
| 1441 | 1493 |
| 1442 const intptr_t pos = FirstIntersection( | 1494 const intptr_t pos = FirstIntersection( |
| 1443 unallocated->finger()->first_pending_use_interval(), | 1495 unallocated->finger()->first_pending_use_interval(), |
| 1444 allocated_head); | 1496 allocated_head); |
| 1445 if (pos < intersection) intersection = pos; | 1497 if (pos < intersection) intersection = pos; |
| 1446 } | 1498 } |
| 1447 return intersection; | 1499 return intersection; |
| 1448 } | 1500 } |
| 1449 | 1501 |
| 1450 | 1502 |
| 1451 | |
| 1452 bool FlowGraphAllocator::AllocateFreeRegister(LiveRange* unallocated) { | 1503 bool FlowGraphAllocator::AllocateFreeRegister(LiveRange* unallocated) { |
| 1453 Register candidate = kNoRegister; | 1504 intptr_t candidate = kNoRegister; |
| 1454 intptr_t free_until = 0; | 1505 intptr_t free_until = 0; |
| 1455 | 1506 |
| 1456 // If hint is available try hint first. | 1507 // If hint is available try hint first. |
| 1457 // TODO(vegorov): ensure that phis are hinted on the back edge. | 1508 // TODO(vegorov): ensure that phis are hinted on the back edge. |
| 1458 Location hint = unallocated->finger()->FirstHint(); | 1509 Location hint = unallocated->finger()->FirstHint(); |
| 1459 if (hint.IsRegister()) { | 1510 if (hint.IsMachineRegister()) { |
| 1460 if (!blocked_cpu_regs_[hint.reg()]) { | 1511 if (!blocked_registers_[hint.register_code()]) { |
| 1461 free_until = FirstIntersectionWithAllocated(hint.reg(), unallocated); | 1512 free_until = FirstIntersectionWithAllocated(hint.register_code(), |
| 1462 candidate = hint.reg(); | 1513 unallocated); |
| 1514 candidate = hint.register_code(); |
| 1463 } | 1515 } |
| 1464 | 1516 |
| 1465 TRACE_ALLOC(OS::Print("found hint ")); | 1517 TRACE_ALLOC(OS::Print("found hint ")); |
| 1466 TRACE_ALLOC(hint.Print()); | 1518 TRACE_ALLOC(hint.Print()); |
| 1467 TRACE_ALLOC(OS::Print(" for %d: free until %d\n", | 1519 TRACE_ALLOC(OS::Print(" for %d: free until %d\n", |
| 1468 unallocated->vreg(), free_until)); | 1520 unallocated->vreg(), free_until)); |
| 1469 } else if (free_until != kMaxPosition) { | 1521 } else if (free_until != kMaxPosition) { |
| 1470 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; ++reg) { | 1522 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) { |
| 1471 if (!blocked_cpu_regs_[reg] && cpu_regs_[reg].length() == 0) { | 1523 if (!blocked_registers_[reg] && (registers_[reg].length() == 0)) { |
| 1472 candidate = static_cast<Register>(reg); | 1524 candidate = reg; |
| 1473 free_until = kMaxPosition; | 1525 free_until = kMaxPosition; |
| 1474 break; | 1526 break; |
| 1475 } | 1527 } |
| 1476 } | 1528 } |
| 1477 } | 1529 } |
| 1478 | 1530 |
| 1479 ASSERT(0 <= kMaxPosition); | 1531 ASSERT(0 <= kMaxPosition); |
| 1480 if (free_until != kMaxPosition) { | 1532 if (free_until != kMaxPosition) { |
| 1481 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; ++reg) { | 1533 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) { |
| 1482 if (blocked_cpu_regs_[reg] || (reg == candidate)) continue; | 1534 if (blocked_registers_[reg] || (reg == candidate)) continue; |
| 1483 const intptr_t intersection = | 1535 const intptr_t intersection = |
| 1484 FirstIntersectionWithAllocated(static_cast<Register>(reg), | 1536 FirstIntersectionWithAllocated(reg, unallocated); |
| 1485 unallocated); | |
| 1486 if (intersection > free_until) { | 1537 if (intersection > free_until) { |
| 1487 candidate = static_cast<Register>(reg); | 1538 candidate = reg; |
| 1488 free_until = intersection; | 1539 free_until = intersection; |
| 1489 if (free_until == kMaxPosition) break; | 1540 if (free_until == kMaxPosition) break; |
| 1490 } | 1541 } |
| 1491 } | 1542 } |
| 1492 } | 1543 } |
| 1493 | 1544 |
| 1494 // All registers are blocked by active ranges. | 1545 // All registers are blocked by active ranges. |
| 1495 if (free_until <= unallocated->Start()) return false; | 1546 if (free_until <= unallocated->Start()) return false; |
| 1496 | 1547 |
| 1497 TRACE_ALLOC(OS::Print("assigning free register ")); | 1548 TRACE_ALLOC(OS::Print("assigning free register ")); |
| 1498 TRACE_ALLOC(Location::RegisterLocation(candidate).Print()); | 1549 TRACE_ALLOC(MakeRegisterLocation(candidate).Print()); |
| 1499 TRACE_ALLOC(OS::Print(" to %d\n", unallocated->vreg())); | 1550 TRACE_ALLOC(OS::Print(" to %d\n", unallocated->vreg())); |
| 1500 | 1551 |
| 1501 if (free_until != kMaxPosition) { | 1552 if (free_until != kMaxPosition) { |
| 1502 // There was an intersection. Split unallocated. | 1553 // There was an intersection. Split unallocated. |
| 1503 TRACE_ALLOC(OS::Print(" splitting at %d\n", free_until)); | 1554 TRACE_ALLOC(OS::Print(" splitting at %d\n", free_until)); |
| 1504 LiveRange* tail = unallocated->SplitAt(free_until); | 1555 LiveRange* tail = unallocated->SplitAt(free_until); |
| 1505 AddToUnallocated(tail); | 1556 AddToUnallocated(tail); |
| 1506 } | 1557 } |
| 1507 | 1558 |
| 1508 cpu_regs_[candidate].Add(unallocated); | 1559 registers_[candidate].Add(unallocated); |
| 1509 unallocated->set_assigned_location(Location::RegisterLocation(candidate)); | 1560 unallocated->set_assigned_location(MakeRegisterLocation(candidate)); |
| 1510 | 1561 |
| 1511 return true; | 1562 return true; |
| 1512 } | 1563 } |
| 1513 | 1564 |
| 1514 | 1565 |
| 1515 void FlowGraphAllocator::AllocateAnyRegister(LiveRange* unallocated) { | 1566 void FlowGraphAllocator::AllocateAnyRegister(LiveRange* unallocated) { |
| 1516 UsePosition* register_use = | 1567 UsePosition* register_use = |
| 1517 unallocated->finger()->FirstRegisterUse(unallocated->Start()); | 1568 unallocated->finger()->FirstRegisterUse(unallocated->Start()); |
| 1518 if (register_use == NULL) { | 1569 if (register_use == NULL) { |
| 1519 Spill(unallocated); | 1570 Spill(unallocated); |
| 1520 return; | 1571 return; |
| 1521 } | 1572 } |
| 1522 | 1573 |
| 1523 Register candidate = kNoRegister; | 1574 intptr_t candidate = kNoRegister; |
| 1524 intptr_t free_until = 0; | 1575 intptr_t free_until = 0; |
| 1525 intptr_t blocked_at = kMaxPosition; | 1576 intptr_t blocked_at = kMaxPosition; |
| 1526 | 1577 |
| 1527 for (int reg = 0; reg < kNumberOfCpuRegisters; ++reg) { | 1578 for (int reg = 0; reg < NumberOfRegisters(); ++reg) { |
| 1528 if (blocked_cpu_regs_[reg]) continue; | 1579 if (blocked_registers_[reg]) continue; |
| 1529 if (UpdateFreeUntil(static_cast<Register>(reg), | 1580 if (UpdateFreeUntil(reg, unallocated, &free_until, &blocked_at)) { |
| 1530 unallocated, | 1581 candidate = reg; |
| 1531 &free_until, | |
| 1532 &blocked_at)) { | |
| 1533 candidate = static_cast<Register>(reg); | |
| 1534 } | 1582 } |
| 1535 } | 1583 } |
| 1536 | 1584 |
| 1537 if (free_until < register_use->pos()) { | 1585 if (free_until < register_use->pos()) { |
| 1538 // Can't acquire free register. Spill until we really need one. | 1586 // Can't acquire free register. Spill until we really need one. |
| 1539 ASSERT(unallocated->Start() < ToInstructionStart(register_use->pos())); | 1587 ASSERT(unallocated->Start() < ToInstructionStart(register_use->pos())); |
| 1540 SpillBetween(unallocated, unallocated->Start(), register_use->pos()); | 1588 SpillBetween(unallocated, unallocated->Start(), register_use->pos()); |
| 1541 return; | 1589 return; |
| 1542 } | 1590 } |
| 1543 | 1591 |
| 1544 TRACE_ALLOC(OS::Print("assigning blocked register ")); | 1592 TRACE_ALLOC(OS::Print("assigning blocked register ")); |
| 1545 TRACE_ALLOC(Location::RegisterLocation(candidate).Print()); | 1593 TRACE_ALLOC(MakeRegisterLocation(candidate).Print()); |
| 1546 TRACE_ALLOC(OS::Print(" to live range %d until %d\n", | 1594 TRACE_ALLOC(OS::Print(" to live range %d until %d\n", |
| 1547 unallocated->vreg(), blocked_at)); | 1595 unallocated->vreg(), blocked_at)); |
| 1548 | 1596 |
| 1549 if (blocked_at < unallocated->End()) { | 1597 if (blocked_at < unallocated->End()) { |
| 1550 // Register is blocked before the end of the live range. Split the range | 1598 // Register is blocked before the end of the live range. Split the range |
| 1551 // at latest at blocked_at position. | 1599 // at latest at blocked_at position. |
| 1552 LiveRange* tail = SplitBetween(unallocated, | 1600 LiveRange* tail = SplitBetween(unallocated, |
| 1553 unallocated->Start(), | 1601 unallocated->Start(), |
| 1554 blocked_at + 1); | 1602 blocked_at + 1); |
| 1555 AddToUnallocated(tail); | 1603 AddToUnallocated(tail); |
| 1556 } | 1604 } |
| 1557 | 1605 |
| 1558 AssignNonFreeRegister(unallocated, candidate); | 1606 AssignNonFreeRegister(unallocated, candidate); |
| 1559 } | 1607 } |
| 1560 | 1608 |
| 1561 | 1609 |
| 1562 bool FlowGraphAllocator::UpdateFreeUntil(Register reg, | 1610 bool FlowGraphAllocator::UpdateFreeUntil(intptr_t reg, |
| 1563 LiveRange* unallocated, | 1611 LiveRange* unallocated, |
| 1564 intptr_t* cur_free_until, | 1612 intptr_t* cur_free_until, |
| 1565 intptr_t* cur_blocked_at) { | 1613 intptr_t* cur_blocked_at) { |
| 1566 intptr_t free_until = kMaxPosition; | 1614 intptr_t free_until = kMaxPosition; |
| 1567 intptr_t blocked_at = kMaxPosition; | 1615 intptr_t blocked_at = kMaxPosition; |
| 1568 const intptr_t start = unallocated->Start(); | 1616 const intptr_t start = unallocated->Start(); |
| 1569 | 1617 |
| 1570 for (intptr_t i = 0; i < cpu_regs_[reg].length(); i++) { | 1618 for (intptr_t i = 0; i < registers_[reg].length(); i++) { |
| 1571 LiveRange* allocated = cpu_regs_[reg][i]; | 1619 LiveRange* allocated = registers_[reg][i]; |
| 1572 | 1620 |
| 1573 UseInterval* first_pending_use_interval = | 1621 UseInterval* first_pending_use_interval = |
| 1574 allocated->finger()->first_pending_use_interval(); | 1622 allocated->finger()->first_pending_use_interval(); |
| 1575 if (first_pending_use_interval->Contains(start)) { | 1623 if (first_pending_use_interval->Contains(start)) { |
| 1576 // This is an active interval. | 1624 // This is an active interval. |
| 1577 if (allocated->vreg() < 0) { | 1625 if (allocated->vreg() < 0) { |
| 1578 // This register blocked by an interval that | 1626 // This register blocked by an interval that |
| 1579 // can't be spilled. | 1627 // can't be spilled. |
| 1580 return false; | 1628 return false; |
| 1581 } | 1629 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1609 } | 1657 } |
| 1610 } | 1658 } |
| 1611 | 1659 |
| 1612 ASSERT(free_until > *cur_free_until); | 1660 ASSERT(free_until > *cur_free_until); |
| 1613 *cur_free_until = free_until; | 1661 *cur_free_until = free_until; |
| 1614 *cur_blocked_at = blocked_at; | 1662 *cur_blocked_at = blocked_at; |
| 1615 return true; | 1663 return true; |
| 1616 } | 1664 } |
| 1617 | 1665 |
| 1618 | 1666 |
| 1619 void FlowGraphAllocator::RemoveEvicted(Register reg, intptr_t first_evicted) { | 1667 void FlowGraphAllocator::RemoveEvicted(intptr_t reg, intptr_t first_evicted) { |
| 1620 intptr_t to = first_evicted; | 1668 intptr_t to = first_evicted; |
| 1621 intptr_t from = first_evicted + 1; | 1669 intptr_t from = first_evicted + 1; |
| 1622 while (from < cpu_regs_[reg].length()) { | 1670 while (from < registers_[reg].length()) { |
| 1623 LiveRange* allocated = cpu_regs_[reg][from++]; | 1671 LiveRange* allocated = registers_[reg][from++]; |
| 1624 if (allocated != NULL) cpu_regs_[reg][to++] = allocated; | 1672 if (allocated != NULL) registers_[reg][to++] = allocated; |
| 1625 } | 1673 } |
| 1626 cpu_regs_[reg].TruncateTo(to); | 1674 registers_[reg].TruncateTo(to); |
| 1627 } | 1675 } |
| 1628 | 1676 |
| 1629 | 1677 |
| 1630 void FlowGraphAllocator::AssignNonFreeRegister(LiveRange* unallocated, | 1678 void FlowGraphAllocator::AssignNonFreeRegister(LiveRange* unallocated, |
| 1631 Register reg) { | 1679 intptr_t reg) { |
| 1632 intptr_t first_evicted = -1; | 1680 intptr_t first_evicted = -1; |
| 1633 for (intptr_t i = cpu_regs_[reg].length() - 1; i >= 0; i--) { | 1681 for (intptr_t i = registers_[reg].length() - 1; i >= 0; i--) { |
| 1634 LiveRange* allocated = cpu_regs_[reg][i]; | 1682 LiveRange* allocated = registers_[reg][i]; |
| 1635 if (allocated->vreg() < 0) continue; // Can't be evicted. | 1683 if (allocated->vreg() < 0) continue; // Can't be evicted. |
| 1636 if (EvictIntersection(allocated, unallocated)) { | 1684 if (EvictIntersection(allocated, unallocated)) { |
| 1637 // If allocated was not spilled convert all pending uses. | 1685 // If allocated was not spilled convert all pending uses. |
| 1638 if (allocated->assigned_location().IsRegister()) { | 1686 if (allocated->assigned_location().IsRegister()) { |
| 1639 ASSERT(allocated->End() <= unallocated->Start()); | 1687 ASSERT(allocated->End() <= unallocated->Start()); |
| 1640 ConvertAllUses(allocated); | 1688 ConvertAllUses(allocated); |
| 1641 } | 1689 } |
| 1642 cpu_regs_[reg][i] = NULL; | 1690 registers_[reg][i] = NULL; |
| 1643 first_evicted = i; | 1691 first_evicted = i; |
| 1644 } | 1692 } |
| 1645 } | 1693 } |
| 1646 | 1694 |
| 1647 // Remove evicted ranges from the array. | 1695 // Remove evicted ranges from the array. |
| 1648 if (first_evicted != -1) RemoveEvicted(reg, first_evicted); | 1696 if (first_evicted != -1) RemoveEvicted(reg, first_evicted); |
| 1649 | 1697 |
| 1650 cpu_regs_[reg].Add(unallocated); | 1698 registers_[reg].Add(unallocated); |
| 1651 unallocated->set_assigned_location(Location::RegisterLocation(reg)); | 1699 unallocated->set_assigned_location(MakeRegisterLocation(reg)); |
| 1652 } | 1700 } |
| 1653 | 1701 |
| 1654 | 1702 |
| 1655 bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated, | 1703 bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated, |
| 1656 LiveRange* unallocated) { | 1704 LiveRange* unallocated) { |
| 1657 UseInterval* first_unallocated = | 1705 UseInterval* first_unallocated = |
| 1658 unallocated->finger()->first_pending_use_interval(); | 1706 unallocated->finger()->first_pending_use_interval(); |
| 1659 const intptr_t intersection = FirstIntersection( | 1707 const intptr_t intersection = FirstIntersection( |
| 1660 allocated->finger()->first_pending_use_interval(), | 1708 allocated->finger()->first_pending_use_interval(), |
| 1661 first_unallocated); | 1709 first_unallocated); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1693 } | 1741 } |
| 1694 | 1742 |
| 1695 return parallel_move->AddMove(to, from); | 1743 return parallel_move->AddMove(to, from); |
| 1696 } | 1744 } |
| 1697 | 1745 |
| 1698 | 1746 |
| 1699 void FlowGraphAllocator::ConvertUseTo(UsePosition* use, Location loc) { | 1747 void FlowGraphAllocator::ConvertUseTo(UsePosition* use, Location loc) { |
| 1700 ASSERT(use->location_slot() != NULL); | 1748 ASSERT(use->location_slot() != NULL); |
| 1701 Location* slot = use->location_slot(); | 1749 Location* slot = use->location_slot(); |
| 1702 ASSERT(slot->IsUnallocated()); | 1750 ASSERT(slot->IsUnallocated()); |
| 1703 ASSERT((slot->policy() == Location::kRequiresRegister) || | |
| 1704 (slot->policy() == Location::kPrefersRegister) || | |
| 1705 (slot->policy() == Location::kAny)); | |
| 1706 TRACE_ALLOC(OS::Print(" use at %d converted to ", use->pos())); | 1751 TRACE_ALLOC(OS::Print(" use at %d converted to ", use->pos())); |
| 1707 TRACE_ALLOC(loc.Print()); | 1752 TRACE_ALLOC(loc.Print()); |
| 1708 TRACE_ALLOC(OS::Print("\n")); | 1753 TRACE_ALLOC(OS::Print("\n")); |
| 1709 *slot = loc; | 1754 *slot = loc; |
| 1710 } | 1755 } |
| 1711 | 1756 |
| 1712 | 1757 |
| 1713 void FlowGraphAllocator::ConvertAllUses(LiveRange* range) { | 1758 void FlowGraphAllocator::ConvertAllUses(LiveRange* range) { |
| 1714 if (range->vreg() == kNoVirtualRegister) return; | 1759 if (range->vreg() == kNoVirtualRegister) return; |
| 1760 |
| 1761 const Location loc = range->assigned_location(); |
| 1762 ASSERT(!loc.IsInvalid()); |
| 1763 |
| 1715 TRACE_ALLOC(OS::Print("range [%d, %d) for v%d has been allocated to ", | 1764 TRACE_ALLOC(OS::Print("range [%d, %d) for v%d has been allocated to ", |
| 1716 range->Start(), range->End(), range->vreg())); | 1765 range->Start(), range->End(), range->vreg())); |
| 1717 TRACE_ALLOC(range->assigned_location().Print()); | 1766 TRACE_ALLOC(loc.Print()); |
| 1718 TRACE_ALLOC(OS::Print(":\n")); | 1767 TRACE_ALLOC(OS::Print(":\n")); |
| 1719 ASSERT(!range->assigned_location().IsInvalid()); | 1768 |
| 1720 const Location loc = range->assigned_location(); | |
| 1721 for (UsePosition* use = range->first_use(); use != NULL; use = use->next()) { | 1769 for (UsePosition* use = range->first_use(); use != NULL; use = use->next()) { |
| 1722 ConvertUseTo(use, loc); | 1770 ConvertUseTo(use, loc); |
| 1723 } | 1771 } |
| 1724 | 1772 |
| 1725 if (range->assigned_location().IsRegister()) { | 1773 if (loc.IsMachineRegister()) { |
| 1726 Register reg = range->assigned_location().reg(); | |
| 1727 for (SafepointPosition* safepoint = range->first_safepoint(); | 1774 for (SafepointPosition* safepoint = range->first_safepoint(); |
| 1728 safepoint != NULL; | 1775 safepoint != NULL; |
| 1729 safepoint = safepoint->next()) { | 1776 safepoint = safepoint->next()) { |
| 1730 safepoint->locs()->live_registers()->Add(reg); | 1777 safepoint->locs()->live_registers()->Add(loc); |
| 1731 } | 1778 } |
| 1732 } | 1779 } |
| 1733 } | 1780 } |
| 1734 | 1781 |
| 1735 | 1782 |
| 1736 void FlowGraphAllocator::AdvanceActiveIntervals(const intptr_t start) { | 1783 void FlowGraphAllocator::AdvanceActiveIntervals(const intptr_t start) { |
| 1737 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { | 1784 for (intptr_t reg = 0; reg < NumberOfRegisters(); reg++) { |
| 1738 if (cpu_regs_[reg].is_empty()) continue; | 1785 if (registers_[reg].is_empty()) continue; |
| 1739 | 1786 |
| 1740 intptr_t first_evicted = -1; | 1787 intptr_t first_evicted = -1; |
| 1741 for (intptr_t i = cpu_regs_[reg].length() - 1; i >= 0; i--) { | 1788 for (intptr_t i = registers_[reg].length() - 1; i >= 0; i--) { |
| 1742 LiveRange* range = cpu_regs_[reg][i]; | 1789 LiveRange* range = registers_[reg][i]; |
| 1743 if (range->finger()->Advance(start)) { | 1790 if (range->finger()->Advance(start)) { |
| 1744 ConvertAllUses(range); | 1791 ConvertAllUses(range); |
| 1745 cpu_regs_[reg][i] = NULL; | 1792 registers_[reg][i] = NULL; |
| 1746 first_evicted = i; | 1793 first_evicted = i; |
| 1747 } | 1794 } |
| 1748 } | 1795 } |
| 1749 | 1796 |
| 1750 if (first_evicted != -1) { | 1797 if (first_evicted != -1) RemoveEvicted(reg, first_evicted); |
| 1751 RemoveEvicted(static_cast<Register>(reg), first_evicted); | |
| 1752 } | |
| 1753 } | 1798 } |
| 1754 } | 1799 } |
| 1755 | 1800 |
| 1756 | 1801 |
| 1757 static inline bool ShouldBeAllocatedBefore(LiveRange* a, LiveRange* b) { | |
| 1758 return a->Start() <= b->Start(); | |
| 1759 } | |
| 1760 | |
| 1761 | |
| 1762 bool LiveRange::Contains(intptr_t pos) const { | 1802 bool LiveRange::Contains(intptr_t pos) const { |
| 1763 if (!CanCover(pos)) return false; | 1803 if (!CanCover(pos)) return false; |
| 1764 | 1804 |
| 1765 for (UseInterval* interval = first_use_interval_; | 1805 for (UseInterval* interval = first_use_interval_; |
| 1766 interval != NULL; | 1806 interval != NULL; |
| 1767 interval = interval->next()) { | 1807 interval = interval->next()) { |
| 1768 if (interval->Contains(pos)) { | 1808 if (interval->Contains(pos)) { |
| 1769 return true; | 1809 return true; |
| 1770 } | 1810 } |
| 1771 } | 1811 } |
| 1772 | 1812 |
| 1773 return false; | 1813 return false; |
| 1774 } | 1814 } |
| 1775 | 1815 |
| 1776 | 1816 |
| 1777 void FlowGraphAllocator::AssignSafepoints(LiveRange* range) { | 1817 void FlowGraphAllocator::AssignSafepoints(LiveRange* range) { |
| 1778 for (intptr_t i = safepoints_.length() - 1; i >= 0; i--) { | 1818 for (intptr_t i = safepoints_.length() - 1; i >= 0; i--) { |
| 1779 Instruction* instr = safepoints_[i]; | 1819 Instruction* instr = safepoints_[i]; |
| 1780 | 1820 |
| 1781 const intptr_t pos = instr->lifetime_position(); | 1821 const intptr_t pos = instr->lifetime_position(); |
| 1782 if (range->End() <= pos) break; | 1822 if (range->End() <= pos) break; |
| 1783 | 1823 |
| 1784 if (range->Contains(pos)) range->AddSafepoint(pos, instr->locs()); | 1824 if (range->Contains(pos)) range->AddSafepoint(pos, instr->locs()); |
| 1785 } | 1825 } |
| 1786 } | 1826 } |
| 1787 | 1827 |
| 1788 | 1828 |
| 1829 static inline bool ShouldBeAllocatedBefore(LiveRange* a, LiveRange* b) { |
| 1830 // TODO(vegorov): consider first hint position when ordering live ranges. |
| 1831 return a->Start() <= b->Start(); |
| 1832 } |
| 1833 |
| 1834 |
| 1835 static void AddToSortedListOfRanges(GrowableArray<LiveRange*>* list, |
| 1836 LiveRange* range) { |
| 1837 range->finger()->Initialize(range); |
| 1838 |
| 1839 if (list->is_empty()) { |
| 1840 list->Add(range); |
| 1841 return; |
| 1842 } |
| 1843 |
| 1844 for (intptr_t i = list->length() - 1; i >= 0; i--) { |
| 1845 if (ShouldBeAllocatedBefore(range, (*list)[i])) { |
| 1846 list->InsertAt(i + 1, range); |
| 1847 return; |
| 1848 } |
| 1849 } |
| 1850 list->InsertAt(0, range); |
| 1851 } |
| 1852 |
| 1853 |
| 1789 void FlowGraphAllocator::AddToUnallocated(LiveRange* range) { | 1854 void FlowGraphAllocator::AddToUnallocated(LiveRange* range) { |
| 1790 range->finger()->Initialize(range); | 1855 AddToSortedListOfRanges(&unallocated_, range); |
| 1791 | |
| 1792 if (unallocated_.is_empty()) { | |
| 1793 unallocated_.Add(range); | |
| 1794 return; | |
| 1795 } | |
| 1796 | |
| 1797 for (intptr_t i = unallocated_.length() - 1; i >= 0; i--) { | |
| 1798 if (ShouldBeAllocatedBefore(range, unallocated_[i])) { | |
| 1799 unallocated_.InsertAt(i + 1, range); | |
| 1800 return; | |
| 1801 } | |
| 1802 } | |
| 1803 unallocated_.InsertAt(0, range); | |
| 1804 } | 1856 } |
| 1805 | 1857 |
| 1806 | 1858 |
| 1859 void FlowGraphAllocator::CompleteRange(LiveRange* range, Location::Kind kind) { |
| 1860 switch (kind) { |
| 1861 case Location::kRegister: |
| 1862 AddToSortedListOfRanges(&unallocated_cpu_, range); |
| 1863 break; |
| 1864 |
| 1865 case Location::kXmmRegister: |
| 1866 AddToSortedListOfRanges(&unallocated_xmm_, range); |
| 1867 break; |
| 1868 |
| 1869 default: |
| 1870 UNREACHABLE(); |
| 1871 } |
| 1872 } |
| 1873 |
| 1874 |
| 1807 #if defined(DEBUG) | 1875 #if defined(DEBUG) |
| 1808 bool FlowGraphAllocator::UnallocatedIsSorted() { | 1876 bool FlowGraphAllocator::UnallocatedIsSorted() { |
| 1809 for (intptr_t i = unallocated_.length() - 1; i >= 1; i--) { | 1877 for (intptr_t i = unallocated_.length() - 1; i >= 1; i--) { |
| 1810 LiveRange* a = unallocated_[i]; | 1878 LiveRange* a = unallocated_[i]; |
| 1811 LiveRange* b = unallocated_[i - 1]; | 1879 LiveRange* b = unallocated_[i - 1]; |
| 1812 if (!ShouldBeAllocatedBefore(a, b)) return false; | 1880 if (!ShouldBeAllocatedBefore(a, b)) return false; |
| 1813 } | 1881 } |
| 1814 return true; | 1882 return true; |
| 1815 } | 1883 } |
| 1816 #endif | 1884 #endif |
| 1817 | 1885 |
| 1818 | 1886 |
| 1819 void FlowGraphAllocator::AllocateCPURegisters() { | 1887 void FlowGraphAllocator::PrepareForAllocation( |
| 1888 Location::Kind register_kind, |
| 1889 intptr_t number_of_registers, |
| 1890 const GrowableArray<LiveRange*>& unallocated, |
| 1891 LiveRange** blocking_ranges, |
| 1892 bool* blocked_registers) { |
| 1893 register_kind_ = register_kind; |
| 1894 number_of_registers_ = number_of_registers; |
| 1895 |
| 1896 ASSERT(unallocated_.is_empty()); |
| 1897 unallocated_.AddArray(unallocated); |
| 1898 |
| 1899 for (intptr_t reg = 0; reg < number_of_registers; reg++) { |
| 1900 blocked_registers_[reg] = blocked_registers[reg]; |
| 1901 ASSERT(registers_[reg].is_empty()); |
| 1902 |
| 1903 LiveRange* range = blocking_ranges[reg]; |
| 1904 if (range != NULL) { |
| 1905 range->finger()->Initialize(range); |
| 1906 registers_[reg].Add(range); |
| 1907 } |
| 1908 } |
| 1909 } |
| 1910 |
| 1911 |
| 1912 void FlowGraphAllocator::AllocateUnallocatedRanges() { |
| 1820 #if defined(DEBUG) | 1913 #if defined(DEBUG) |
| 1821 ASSERT(UnallocatedIsSorted()); | 1914 ASSERT(UnallocatedIsSorted()); |
| 1822 #endif | 1915 #endif |
| 1823 | 1916 |
| 1824 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) { | |
| 1825 if (cpu_regs_[i].length() == 1) { | |
| 1826 LiveRange* range = cpu_regs_[i][0]; | |
| 1827 range->finger()->Initialize(range); | |
| 1828 } | |
| 1829 } | |
| 1830 | |
| 1831 while (!unallocated_.is_empty()) { | 1917 while (!unallocated_.is_empty()) { |
| 1832 LiveRange* range = unallocated_.Last(); | 1918 LiveRange* range = unallocated_.Last(); |
| 1833 unallocated_.RemoveLast(); | 1919 unallocated_.RemoveLast(); |
| 1834 const intptr_t start = range->Start(); | 1920 const intptr_t start = range->Start(); |
| 1835 TRACE_ALLOC(OS::Print("Processing live range for vreg %d starting at %d\n", | 1921 TRACE_ALLOC(OS::Print("Processing live range for vreg %d starting at %d\n", |
| 1836 range->vreg(), | 1922 range->vreg(), |
| 1837 start)); | 1923 start)); |
| 1838 | 1924 |
| 1839 // TODO(vegorov): eagerly spill liveranges without register uses. | 1925 // TODO(vegorov): eagerly spill liveranges without register uses. |
| 1840 AdvanceActiveIntervals(start); | 1926 AdvanceActiveIntervals(start); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1903 TRACE_ALLOC(source.Print()); | 1989 TRACE_ALLOC(source.Print()); |
| 1904 TRACE_ALLOC(OS::Print("] to [%d, %d) [", | 1990 TRACE_ALLOC(OS::Print("] to [%d, %d) [", |
| 1905 target_cover->Start(), target_cover->End())); | 1991 target_cover->Start(), target_cover->End())); |
| 1906 TRACE_ALLOC(target.Print()); | 1992 TRACE_ALLOC(target.Print()); |
| 1907 TRACE_ALLOC(OS::Print("]\n")); | 1993 TRACE_ALLOC(OS::Print("]\n")); |
| 1908 | 1994 |
| 1909 // Siblings were allocated to the same register. | 1995 // Siblings were allocated to the same register. |
| 1910 if (source.Equals(target)) return; | 1996 if (source.Equals(target)) return; |
| 1911 | 1997 |
| 1912 // Values are eagerly spilled. Spill slot already contains appropriate value. | 1998 // Values are eagerly spilled. Spill slot already contains appropriate value. |
| 1913 if (target.IsStackSlot()) { | 1999 if (target.IsStackSlot() || target.IsDoubleStackSlot()) { |
| 1914 ASSERT(parent->spill_slot().Equals(target)); | 2000 ASSERT(parent->spill_slot().Equals(target)); |
| 1915 return; | 2001 return; |
| 1916 } | 2002 } |
| 1917 | 2003 |
| 1918 Instruction* last = source_block->last_instruction(); | 2004 Instruction* last = source_block->last_instruction(); |
| 1919 if ((last->SuccessorCount() == 1) && !source_block->IsGraphEntry()) { | 2005 if ((last->SuccessorCount() == 1) && !source_block->IsGraphEntry()) { |
| 1920 ASSERT(last->IsGoto()); | 2006 ASSERT(last->IsGoto()); |
| 1921 last->AsGoto()->GetParallelMove()->AddMove(target, source); | 2007 last->AsGoto()->GetParallelMove()->AddMove(target, source); |
| 1922 } else { | 2008 } else { |
| 1923 target_block->GetParallelMove()->AddMove(target, source); | 2009 target_block->GetParallelMove()->AddMove(target, source); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1936 LiveRange* sibling = range->next_sibling(); | 2022 LiveRange* sibling = range->next_sibling(); |
| 1937 TRACE_ALLOC(OS::Print("connecting [%d, %d) [", | 2023 TRACE_ALLOC(OS::Print("connecting [%d, %d) [", |
| 1938 range->Start(), range->End())); | 2024 range->Start(), range->End())); |
| 1939 TRACE_ALLOC(range->assigned_location().Print()); | 2025 TRACE_ALLOC(range->assigned_location().Print()); |
| 1940 TRACE_ALLOC(OS::Print("] to [%d, %d) [", | 2026 TRACE_ALLOC(OS::Print("] to [%d, %d) [", |
| 1941 sibling->Start(), sibling->End())); | 2027 sibling->Start(), sibling->End())); |
| 1942 TRACE_ALLOC(sibling->assigned_location().Print()); | 2028 TRACE_ALLOC(sibling->assigned_location().Print()); |
| 1943 TRACE_ALLOC(OS::Print("]\n")); | 2029 TRACE_ALLOC(OS::Print("]\n")); |
| 1944 if ((range->End() == sibling->Start()) && | 2030 if ((range->End() == sibling->Start()) && |
| 1945 !sibling->assigned_location().IsStackSlot() && | 2031 !sibling->assigned_location().IsStackSlot() && |
| 2032 !sibling->assigned_location().IsDoubleStackSlot() && |
| 1946 !range->assigned_location().Equals(sibling->assigned_location()) && | 2033 !range->assigned_location().Equals(sibling->assigned_location()) && |
| 1947 !IsBlockEntry(range->End())) { | 2034 !IsBlockEntry(range->End())) { |
| 1948 AddMoveAt(sibling->Start(), | 2035 AddMoveAt(sibling->Start(), |
| 1949 sibling->assigned_location(), | 2036 sibling->assigned_location(), |
| 1950 range->assigned_location()); | 2037 range->assigned_location()); |
| 1951 } | 2038 } |
| 1952 range = sibling; | 2039 range = sibling; |
| 1953 } | 2040 } |
| 1954 } | 2041 } |
| 1955 | 2042 |
| 1956 // Resolve non-linear control flow across branches. | 2043 // Resolve non-linear control flow across branches. |
| 1957 for (intptr_t i = 1; i < block_order_.length(); i++) { | 2044 for (intptr_t i = 1; i < block_order_.length(); i++) { |
| 1958 BlockEntryInstr* block = block_order_[i]; | 2045 BlockEntryInstr* block = block_order_[i]; |
| 1959 BitVector* live = live_in_[block->postorder_number()]; | 2046 BitVector* live = live_in_[block->postorder_number()]; |
| 1960 for (BitVector::Iterator it(live); !it.Done(); it.Advance()) { | 2047 for (BitVector::Iterator it(live); !it.Done(); it.Advance()) { |
| 1961 LiveRange* range = GetLiveRange(it.Current()); | 2048 LiveRange* range = GetLiveRange(it.Current()); |
| 1962 for (intptr_t j = 0; j < block->PredecessorCount(); j++) { | 2049 for (intptr_t j = 0; j < block->PredecessorCount(); j++) { |
| 1963 ConnectSplitSiblings(range, block->PredecessorAt(j), block); | 2050 ConnectSplitSiblings(range, block->PredecessorAt(j), block); |
| 1964 } | 2051 } |
| 1965 } | 2052 } |
| 1966 } | 2053 } |
| 1967 | 2054 |
| 1968 // Eagerly spill values. | 2055 // Eagerly spill values. |
| 1969 // TODO(vegorov): if value is spilled on the cold path (e.g. by the call) | 2056 // TODO(vegorov): if value is spilled on the cold path (e.g. by the call) |
| 1970 // this will cause spilling to occur on the fast path (at the definition). | 2057 // this will cause spilling to occur on the fast path (at the definition). |
| 1971 for (intptr_t i = 0; i < spilled_.length(); i++) { | 2058 for (intptr_t i = 0; i < spilled_.length(); i++) { |
| 1972 LiveRange* range = spilled_[i]; | 2059 LiveRange* range = spilled_[i]; |
| 1973 if (range->assigned_location().IsStackSlot()) { | 2060 if (range->assigned_location().IsStackSlot() || |
| 2061 range->assigned_location().IsDoubleStackSlot()) { |
| 1974 ASSERT(range->assigned_location().Equals(range->spill_slot())); | 2062 ASSERT(range->assigned_location().Equals(range->spill_slot())); |
| 1975 } else { | 2063 } else { |
| 1976 AddMoveAt(range->Start() + 1, | 2064 AddMoveAt(range->Start() + 1, |
| 1977 range->spill_slot(), | 2065 range->spill_slot(), |
| 1978 range->assigned_location()); | 2066 range->assigned_location()); |
| 1979 } | 2067 } |
| 1980 } | 2068 } |
| 1981 } | 2069 } |
| 1982 | 2070 |
| 1983 | 2071 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2004 PrintLiveRanges(); | 2092 PrintLiveRanges(); |
| 2005 OS::Print("----------------------------------------------\n"); | 2093 OS::Print("----------------------------------------------\n"); |
| 2006 | 2094 |
| 2007 OS::Print("-- [before ssa allocator] ir [%s] -------------\n", | 2095 OS::Print("-- [before ssa allocator] ir [%s] -------------\n", |
| 2008 function.ToFullyQualifiedCString()); | 2096 function.ToFullyQualifiedCString()); |
| 2009 FlowGraphPrinter printer(flow_graph_, true); | 2097 FlowGraphPrinter printer(flow_graph_, true); |
| 2010 printer.PrintBlocks(); | 2098 printer.PrintBlocks(); |
| 2011 OS::Print("----------------------------------------------\n"); | 2099 OS::Print("----------------------------------------------\n"); |
| 2012 } | 2100 } |
| 2013 | 2101 |
| 2014 AllocateCPURegisters(); | 2102 PrepareForAllocation(Location::kRegister, |
| 2103 kNumberOfCpuRegisters, |
| 2104 unallocated_cpu_, |
| 2105 cpu_regs_, |
| 2106 blocked_cpu_registers_); |
| 2107 AllocateUnallocatedRanges(); |
| 2108 |
| 2109 cpu_spill_slot_count_ = spill_slots_.length(); |
| 2110 spill_slots_.Clear(); |
| 2111 |
| 2112 PrepareForAllocation(Location::kXmmRegister, |
| 2113 kNumberOfXmmRegisters, |
| 2114 unallocated_xmm_, |
| 2115 xmm_regs_, |
| 2116 blocked_xmm_registers_); |
| 2117 AllocateUnallocatedRanges(); |
| 2015 | 2118 |
| 2016 ResolveControlFlow(); | 2119 ResolveControlFlow(); |
| 2017 | 2120 |
| 2121 // Reserve spill slots for XMM registers alive across slow path code. |
| 2122 // TODO(vegorov): remove this code when safepoints with registers are |
| 2123 // implemented. |
| 2124 intptr_t deferred_xmm_spills = 0; |
| 2125 for (intptr_t i = 0; i < safepoints_.length(); i++) { |
| 2126 if (!safepoints_[i]->locs()->always_calls()) { |
| 2127 const intptr_t count = |
| 2128 safepoints_[i]->locs()->live_registers()->xmm_regs_count(); |
| 2129 if (count > deferred_xmm_spills) deferred_xmm_spills = count; |
| 2130 } |
| 2131 } |
| 2132 |
| 2018 GraphEntryInstr* entry = block_order_[0]->AsGraphEntry(); | 2133 GraphEntryInstr* entry = block_order_[0]->AsGraphEntry(); |
| 2019 ASSERT(entry != NULL); | 2134 ASSERT(entry != NULL); |
| 2020 entry->set_spill_slot_count(spill_slots_.length()); | 2135 entry->set_spill_slot_count( |
| 2136 (deferred_xmm_spills + spill_slots_.length()) * kDoubleSpillSlotFactor + |
| 2137 cpu_spill_slot_count_); |
| 2021 | 2138 |
| 2022 if (FLAG_print_ssa_liveranges) { | 2139 if (FLAG_print_ssa_liveranges) { |
| 2023 const Function& function = flow_graph_.parsed_function().function(); | 2140 const Function& function = flow_graph_.parsed_function().function(); |
| 2024 | 2141 |
| 2025 OS::Print("-- [after ssa allocator] ranges [%s] ---------\n", | 2142 OS::Print("-- [after ssa allocator] ranges [%s] ---------\n", |
| 2026 function.ToFullyQualifiedCString()); | 2143 function.ToFullyQualifiedCString()); |
| 2027 PrintLiveRanges(); | 2144 PrintLiveRanges(); |
| 2028 OS::Print("----------------------------------------------\n"); | 2145 OS::Print("----------------------------------------------\n"); |
| 2029 | 2146 |
| 2030 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", | 2147 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", |
| 2031 function.ToFullyQualifiedCString()); | 2148 function.ToFullyQualifiedCString()); |
| 2032 FlowGraphPrinter printer(flow_graph_, true); | 2149 FlowGraphPrinter printer(flow_graph_, true); |
| 2033 printer.PrintBlocks(); | 2150 printer.PrintBlocks(); |
| 2034 OS::Print("----------------------------------------------\n"); | 2151 OS::Print("----------------------------------------------\n"); |
| 2035 } | 2152 } |
| 2036 } | 2153 } |
| 2037 | 2154 |
| 2038 | 2155 |
| 2039 } // namespace dart | 2156 } // namespace dart |
| OLD | NEW |