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

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

Issue 10875030: Add support for XMM registers in SSA code generation pipeline. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698