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

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

Powered by Google App Engine
This is Rietveld 408576698