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