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

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

Issue 252333002: Use GPRs for mints (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 7 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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 UNREACHABLE(); 391 UNREACHABLE();
392 } 392 }
393 } 393 }
394 394
395 395
396 void LiveRange::Print() { 396 void LiveRange::Print() {
397 if (first_use_interval() == NULL) { 397 if (first_use_interval() == NULL) {
398 return; 398 return;
399 } 399 }
400 400
401 OS::Print(" live range v%" Pd " [%" Pd ", %" Pd ") in ", 401 OS::Print(" live range v%" Pd " [%" Pd ", %" Pd ") in ", vreg(),
402 vreg(), Start(), End()); 402 Start(),
403 End());
403 assigned_location().Print(); 404 assigned_location().Print();
405 if (spill_slot_.HasStackIndex()) {
406 intptr_t stack_slot = spill_slot_.stack_index();
407 OS::Print(" allocated spill slot: %" Pd "", stack_slot);
408 }
404 OS::Print("\n"); 409 OS::Print("\n");
405 410
411 SafepointPosition* safepoint = first_safepoint();
412 while (safepoint != NULL) {
413 OS::Print(" Safepoint [%" Pd "]: ", safepoint->pos());
414 safepoint->locs()->stack_bitmap()->Print();
415 OS::Print("\n");
416 safepoint = safepoint->next();
417 }
418
406 UsePosition* use_pos = uses_; 419 UsePosition* use_pos = uses_;
407 for (UseInterval* interval = first_use_interval_; 420 for (UseInterval* interval = first_use_interval_;
408 interval != NULL; 421 interval != NULL;
409 interval = interval->next()) { 422 interval = interval->next()) {
410 OS::Print(" use interval [%" Pd ", %" Pd ")\n", 423 OS::Print(" use interval [%" Pd ", %" Pd ")\n",
411 interval->start(), 424 interval->start(),
412 interval->end()); 425 interval->end());
413 while ((use_pos != NULL) && (use_pos->pos() <= interval->end())) { 426 while ((use_pos != NULL) && (use_pos->pos() <= interval->end())) {
414 OS::Print(" use at %" Pd "", use_pos->pos()); 427 OS::Print(" use at %" Pd "", use_pos->pos());
415 if (use_pos->location_slot() != NULL) { 428 if (use_pos->location_slot() != NULL) {
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 start, 570 start,
558 ToInstructionEnd(start)); 571 ToInstructionEnd(start));
559 } 572 }
560 } 573 }
561 574
562 // Process incoming parameters and constants. Do this after all other 575 // Process incoming parameters and constants. Do this after all other
563 // instructions so that safepoints for all calls have already been found. 576 // instructions so that safepoints for all calls have already been found.
564 GraphEntryInstr* graph_entry = flow_graph_.graph_entry(); 577 GraphEntryInstr* graph_entry = flow_graph_.graph_entry();
565 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) { 578 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) {
566 Definition* defn = (*graph_entry->initial_definitions())[i]; 579 Definition* defn = (*graph_entry->initial_definitions())[i];
580 ASSERT(!defn->HasPairRepresentation());
567 LiveRange* range = GetLiveRange(defn->ssa_temp_index()); 581 LiveRange* range = GetLiveRange(defn->ssa_temp_index());
568 range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos()); 582 range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos());
569 range->DefineAt(graph_entry->start_pos()); 583 range->DefineAt(graph_entry->start_pos());
570 ProcessInitialDefinition(defn, range, graph_entry); 584 ProcessInitialDefinition(defn, range, graph_entry);
571 } 585 }
572 } 586 }
573 587
574 588
575 void FlowGraphAllocator::ProcessInitialDefinition(Definition* defn, 589 void FlowGraphAllocator::ProcessInitialDefinition(Definition* defn,
576 LiveRange* range, 590 LiveRange* range,
(...skipping 28 matching lines...) Expand all
605 SplitBetween(range, block->start_pos(), use->pos()); 619 SplitBetween(range, block->start_pos(), use->pos());
606 // Parameters and constants are tagged, so allocated to CPU registers. 620 // Parameters and constants are tagged, so allocated to CPU registers.
607 CompleteRange(tail, Location::kRegister); 621 CompleteRange(tail, Location::kRegister);
608 } 622 }
609 ConvertAllUses(range); 623 ConvertAllUses(range);
610 if (defn->IsParameter() && (range->spill_slot().stack_index() >= 0)) { 624 if (defn->IsParameter() && (range->spill_slot().stack_index() >= 0)) {
611 // Parameters above the frame pointer consume spill slots and are marked 625 // Parameters above the frame pointer consume spill slots and are marked
612 // in stack maps. 626 // in stack maps.
613 spill_slots_.Add(range_end); 627 spill_slots_.Add(range_end);
614 quad_spill_slots_.Add(false); 628 quad_spill_slots_.Add(false);
629 untagged_spill_slots_.Add(false);
630 // Note, all incoming parameters are assumed to be tagged.
615 MarkAsObjectAtSafepoints(range); 631 MarkAsObjectAtSafepoints(range);
616 } else if (defn->IsConstant() && block->IsCatchBlockEntry()) { 632 } else if (defn->IsConstant() && block->IsCatchBlockEntry()) {
617 // Constants at catch block entries consume spill slots. 633 // Constants at catch block entries consume spill slots.
618 spill_slots_.Add(range_end); 634 spill_slots_.Add(range_end);
619 quad_spill_slots_.Add(false); 635 quad_spill_slots_.Add(false);
636 untagged_spill_slots_.Add(false);
620 } 637 }
621 } 638 }
622 639
623 640
624 static Location::Kind RegisterKindFromPolicy(Location loc) { 641 static Location::Kind RegisterKindFromPolicy(Location loc) {
625 if (loc.policy() == Location::kRequiresFpuRegister) { 642 if (loc.policy() == Location::kRequiresFpuRegister) {
626 return Location::kFpuRegister; 643 return Location::kFpuRegister;
627 } else { 644 } else {
628 return Location::kRegister; 645 return Location::kRegister;
629 } 646 }
630 } 647 }
631 648
632 649
633 static Location::Kind RegisterKindForResult(Instruction* instr) { 650 static Location::Kind RegisterKindForResult(Instruction* instr) {
634 if ((instr->representation() == kUnboxedDouble) || 651 if ((instr->representation() == kUnboxedDouble) ||
635 (instr->representation() == kUnboxedMint) ||
636 (instr->representation() == kUnboxedFloat32x4) || 652 (instr->representation() == kUnboxedFloat32x4) ||
637 (instr->representation() == kUnboxedInt32x4) || 653 (instr->representation() == kUnboxedInt32x4) ||
638 (instr->representation() == kUnboxedFloat64x2) || 654 (instr->representation() == kUnboxedFloat64x2) ||
639 (instr->representation() == kPairOfUnboxedDouble)) { 655 (instr->representation() == kPairOfUnboxedDouble)) {
640 return Location::kFpuRegister; 656 return Location::kFpuRegister;
641 } else { 657 } else {
642 return Location::kRegister; 658 return Location::kRegister;
643 } 659 }
644 } 660 }
645 661
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
795 } 811 }
796 812
797 const intptr_t block_start_pos = block->start_pos(); 813 const intptr_t block_start_pos = block->start_pos();
798 const intptr_t use_pos = current->lifetime_position() + 1; 814 const intptr_t use_pos = current->lifetime_position() + 1;
799 815
800 Location* locations = 816 Location* locations =
801 Isolate::Current()->current_zone()->Alloc<Location>(env->Length()); 817 Isolate::Current()->current_zone()->Alloc<Location>(env->Length());
802 818
803 for (intptr_t i = 0; i < env->Length(); ++i) { 819 for (intptr_t i = 0; i < env->Length(); ++i) {
804 Value* value = env->ValueAt(i); 820 Value* value = env->ValueAt(i);
805 locations[i] = Location::Any();
806 Definition* def = value->definition(); 821 Definition* def = value->definition();
822 if (def->HasPairRepresentation()) {
823 locations[i] = Location::Pair(Location::Any(), Location::Any());
824 } else {
825 locations[i] = Location::Any();
826 }
807 827
808 if (def->IsPushArgument()) { 828 if (def->IsPushArgument()) {
809 // Frame size is unknown until after allocation. 829 // Frame size is unknown until after allocation.
810 locations[i] = Location::NoLocation(); 830 locations[i] = Location::NoLocation();
811 continue; 831 continue;
812 } 832 }
813 833
814 ConstantInstr* constant = def->AsConstant(); 834 ConstantInstr* constant = def->AsConstant();
815 if (constant != NULL) { 835 if (constant != NULL) {
816 locations[i] = Location::Constant(constant->value()); 836 locations[i] = Location::Constant(constant->value());
817 continue; 837 continue;
818 } 838 }
819 839
820 MaterializeObjectInstr* mat = def->AsMaterializeObject(); 840 MaterializeObjectInstr* mat = def->AsMaterializeObject();
821 if (mat != NULL) { 841 if (mat != NULL) {
822 // MaterializeObject itself produces no value. But its uses 842 // MaterializeObject itself produces no value. But its uses
823 // are treated as part of the environment: allocated locations 843 // are treated as part of the environment: allocated locations
824 // will be used when building deoptimization data. 844 // will be used when building deoptimization data.
825 locations[i] = Location::NoLocation(); 845 locations[i] = Location::NoLocation();
826 ProcessMaterializationUses(block, block_start_pos, use_pos, mat); 846 ProcessMaterializationUses(block, block_start_pos, use_pos, mat);
827 continue; 847 continue;
828 } 848 }
829 849
830 LiveRange* range = GetLiveRange(def->ssa_temp_index());
831 range->AddUseInterval(block_start_pos, use_pos);
832 range->AddUse(use_pos, &locations[i]);
833
834 if (def->HasPairRepresentation()) { 850 if (def->HasPairRepresentation()) {
835 LiveRange* range = 851 PairLocation* location_pair = locations[i].AsPairLocation();
852 {
853 // First live range.
854 LiveRange* range = GetLiveRange(def->ssa_temp_index());
855 range->AddUseInterval(block_start_pos, use_pos);
856 range->AddUse(use_pos, location_pair->SlotAt(0));
857 }
858 {
859 // Second live range.
860 LiveRange* range =
836 GetLiveRange(ToSecondPairVreg(def->ssa_temp_index())); 861 GetLiveRange(ToSecondPairVreg(def->ssa_temp_index()));
862 range->AddUseInterval(block_start_pos, use_pos);
863 range->AddUse(use_pos, location_pair->SlotAt(1));
864 }
865 } else {
866 LiveRange* range = GetLiveRange(def->ssa_temp_index());
837 range->AddUseInterval(block_start_pos, use_pos); 867 range->AddUseInterval(block_start_pos, use_pos);
838 range->AddUse(use_pos, &locations[i]); 868 range->AddUse(use_pos, &locations[i]);
839 } 869 }
840 } 870 }
841 871
842 env->set_locations(locations); 872 env->set_locations(locations);
843 env = env->outer(); 873 env = env->outer();
844 } 874 }
845 } 875 }
846 876
(...skipping 15 matching lines...) Expand all
862 892
863 for (intptr_t i = 0; i < mat->InputCount(); ++i) { 893 for (intptr_t i = 0; i < mat->InputCount(); ++i) {
864 Definition* def = mat->InputAt(i)->definition(); 894 Definition* def = mat->InputAt(i)->definition();
865 895
866 ConstantInstr* constant = def->AsConstant(); 896 ConstantInstr* constant = def->AsConstant();
867 if (constant != NULL) { 897 if (constant != NULL) {
868 locations[i] = Location::Constant(constant->value()); 898 locations[i] = Location::Constant(constant->value());
869 continue; 899 continue;
870 } 900 }
871 901
872 locations[i] = Location::Any();
873
874 LiveRange* range = GetLiveRange(def->ssa_temp_index());
875 range->AddUseInterval(block_start_pos, use_pos);
876 range->AddUse(use_pos, &locations[i]);
877 if (def->HasPairRepresentation()) { 902 if (def->HasPairRepresentation()) {
878 LiveRange* range = GetLiveRange(ToSecondPairVreg(def->ssa_temp_index())); 903 locations[i] = Location::Pair(Location::Any(), Location::Any());
904 PairLocation* location_pair = locations[i].AsPairLocation();
905 {
906 // First live range.
907 LiveRange* range = GetLiveRange(def->ssa_temp_index());
908 range->AddUseInterval(block_start_pos, use_pos);
909 range->AddUse(use_pos, location_pair->SlotAt(0));
910 }
911 {
912 // Second live range.
913 LiveRange* range =
914 GetLiveRange(ToSecondPairVreg(def->ssa_temp_index()));
915 range->AddUseInterval(block_start_pos, use_pos);
916 range->AddUse(use_pos, location_pair->SlotAt(1));
917 }
918 } else {
919 locations[i] = Location::Any();
920 LiveRange* range = GetLiveRange(def->ssa_temp_index());
879 range->AddUseInterval(block_start_pos, use_pos); 921 range->AddUseInterval(block_start_pos, use_pos);
880 range->AddUse(use_pos, &locations[i]); 922 range->AddUse(use_pos, &locations[i]);
881 } 923 }
882 } 924 }
883 925
884 mat->set_locations(locations); 926 mat->set_locations(locations);
885 } 927 }
886 928
887 929
888 void FlowGraphAllocator::ProcessOneInput(BlockEntryInstr* block, 930 void FlowGraphAllocator::ProcessOneInput(BlockEntryInstr* block,
889 intptr_t pos, 931 intptr_t pos,
890 Location* in_ref, 932 Location* in_ref,
891 Value* input, 933 Value* input,
892 intptr_t vreg) { 934 intptr_t vreg,
935 RegisterSet* live_registers) {
893 ASSERT(in_ref != NULL); 936 ASSERT(in_ref != NULL);
894 ASSERT(!in_ref->IsPairLocation()); 937 ASSERT(!in_ref->IsPairLocation());
895 ASSERT(input != NULL); 938 ASSERT(input != NULL);
896 ASSERT(block != NULL); 939 ASSERT(block != NULL);
897 LiveRange* range = GetLiveRange(vreg); 940 LiveRange* range = GetLiveRange(vreg);
898 if (in_ref->IsMachineRegister()) { 941 if (in_ref->IsMachineRegister()) {
899 // Input is expected in a fixed register. Expected shape of 942 // Input is expected in a fixed register. Expected shape of
900 // live ranges: 943 // live ranges:
901 // 944 //
902 // j' i i' 945 // j' i i'
903 // value --* 946 // value --*
904 // register [-----) 947 // register [-----)
905 // 948 //
949 if (live_registers != NULL) {
950 live_registers->Add(*in_ref, range->representation());
951 }
906 MoveOperands* move = 952 MoveOperands* move =
907 AddMoveAt(pos - 1, *in_ref, Location::Any()); 953 AddMoveAt(pos - 1, *in_ref, Location::Any());
908 BlockLocation(*in_ref, pos - 1, pos + 1); 954 BlockLocation(*in_ref, pos - 1, pos + 1);
909 range->AddUseInterval(block->start_pos(), pos - 1); 955 range->AddUseInterval(block->start_pos(), pos - 1);
910 range->AddHintedUse(pos - 1, move->src_slot(), in_ref); 956 range->AddHintedUse(pos - 1, move->src_slot(), in_ref);
911 } else if (in_ref->IsUnallocated()) { 957 } else if (in_ref->IsUnallocated()) {
912 if (in_ref->policy() == Location::kWritableRegister) { 958 if (in_ref->policy() == Location::kWritableRegister) {
913 // Writable unallocated input. Expected shape of 959 // Writable unallocated input. Expected shape of
914 // live ranges: 960 // live ranges:
915 // 961 //
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
1107 if (locs->out(0).IsUnallocated() && 1153 if (locs->out(0).IsUnallocated() &&
1108 (locs->out(0).policy() == Location::kSameAsFirstInput) && 1154 (locs->out(0).policy() == Location::kSameAsFirstInput) &&
1109 (locs->in(0).IsMachineRegister())) { 1155 (locs->in(0).IsMachineRegister())) {
1110 locs->set_out(0, locs->in(0)); 1156 locs->set_out(0, locs->in(0));
1111 } 1157 }
1112 1158
1113 const bool output_same_as_first_input = 1159 const bool output_same_as_first_input =
1114 locs->out(0).IsUnallocated() && 1160 locs->out(0).IsUnallocated() &&
1115 (locs->out(0).policy() == Location::kSameAsFirstInput); 1161 (locs->out(0).policy() == Location::kSameAsFirstInput);
1116 1162
1163 // Output is same as first input which is a pair.
1164 if (output_same_as_first_input && locs->in(0).IsPairLocation()) {
1165 // Make out into a PairLocation.
1166 locs->set_out(0, Location::Pair(Location::RequiresRegister(),
1167 Location::RequiresRegister()));
1168 }
1117 // Add uses from the deoptimization environment. 1169 // Add uses from the deoptimization environment.
1118 if (current->env() != NULL) ProcessEnvironmentUses(block, current); 1170 if (current->env() != NULL) ProcessEnvironmentUses(block, current);
1119 1171
1120 // Process inputs. 1172 // Process inputs.
1121 // Skip the first input if output is specified with kSameAsFirstInput policy, 1173 // Skip the first input if output is specified with kSameAsFirstInput policy,
1122 // they will be processed together at the very end. 1174 // they will be processed together at the very end.
1123 { 1175 {
1124 for (intptr_t j = output_same_as_first_input ? 1 : 0; 1176 for (intptr_t j = output_same_as_first_input ? 1 : 0;
1125 j < locs->input_count(); 1177 j < locs->input_count();
1126 j++) { 1178 j++) {
1127 // Determine if we are dealing with a value pair, and if so, whether 1179 // Determine if we are dealing with a value pair, and if so, whether
1128 // the location is the first register or second register. 1180 // the location is the first register or second register.
1129 Value* input = current->InputAt(j); 1181 Value* input = current->InputAt(j);
1130 Location* in_ref = locs->in_slot(j); 1182 Location* in_ref = locs->in_slot(j);
1183 RegisterSet* live_registers = NULL;
1184 if (locs->HasCallOnSlowPath()) {
1185 live_registers = locs->live_registers();
1186 }
1131 if (in_ref->IsPairLocation()) { 1187 if (in_ref->IsPairLocation()) {
1132 ASSERT(input->definition()->HasPairRepresentation()); 1188 ASSERT(input->definition()->HasPairRepresentation());
1133 PairLocation* pair = in_ref->AsPairLocation(); 1189 PairLocation* pair = in_ref->AsPairLocation();
1134 const intptr_t vreg = input->definition()->ssa_temp_index(); 1190 const intptr_t vreg = input->definition()->ssa_temp_index();
1135 // Each element of the pair is assigned it's own virtual register number 1191 // Each element of the pair is assigned it's own virtual register number
1136 // and is allocated its own LiveRange. 1192 // and is allocated its own LiveRange.
1137 ProcessOneInput(block, pos, pair->SlotAt(0), 1193 ProcessOneInput(block, pos, pair->SlotAt(0),
1138 input, vreg); 1194 input, vreg, live_registers);
1139 ProcessOneInput(block, pos, pair->SlotAt(1), input, 1195 ProcessOneInput(block, pos, pair->SlotAt(1), input,
1140 ToSecondPairVreg(vreg)); 1196 ToSecondPairVreg(vreg), live_registers);
1141 } else { 1197 } else {
1142 ProcessOneInput(block, pos, in_ref, input, 1198 ProcessOneInput(block, pos, in_ref, input,
1143 input->definition()->ssa_temp_index()); 1199 input->definition()->ssa_temp_index(), live_registers);
1144 } 1200 }
1145 } 1201 }
1146 } 1202 }
1147 1203
1148 // Process temps. 1204 // Process temps.
1149 for (intptr_t j = 0; j < locs->temp_count(); j++) { 1205 for (intptr_t j = 0; j < locs->temp_count(); j++) {
1150 // Expected shape of live range: 1206 // Expected shape of live range:
1151 // 1207 //
1152 // i i' 1208 // i i'
1153 // [--) 1209 // [--)
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
1515 Location* loc = use->location_slot(); 1571 Location* loc = use->location_slot();
1516 if (loc->IsUnallocated() && loc->IsRegisterBeneficial()) { 1572 if (loc->IsUnallocated() && loc->IsRegisterBeneficial()) {
1517 first_register_beneficial_use_ = use; 1573 first_register_beneficial_use_ = use;
1518 return use; 1574 return use;
1519 } 1575 }
1520 } 1576 }
1521 return NULL; 1577 return NULL;
1522 } 1578 }
1523 1579
1524 1580
1581 UsePosition* AllocationFinger::FirstInterferingUse(intptr_t after) {
1582 if (IsInstructionEndPosition(after)) {
1583 // If after is a position at the end of the instruction disregard
1584 // any use occuring at it.
1585 after += 1;
1586 }
1587 return FirstRegisterUse(after);
1588 }
1589
1590
1525 void AllocationFinger::UpdateAfterSplit(intptr_t first_use_after_split_pos) { 1591 void AllocationFinger::UpdateAfterSplit(intptr_t first_use_after_split_pos) {
1526 if ((first_register_use_ != NULL) && 1592 if ((first_register_use_ != NULL) &&
1527 (first_register_use_->pos() >= first_use_after_split_pos)) { 1593 (first_register_use_->pos() >= first_use_after_split_pos)) {
1528 first_register_use_ = NULL; 1594 first_register_use_ = NULL;
1529 } 1595 }
1530 1596
1531 if ((first_register_beneficial_use_ != NULL) && 1597 if ((first_register_beneficial_use_ != NULL) &&
1532 (first_register_beneficial_use_->pos() >= first_use_after_split_pos)) { 1598 (first_register_beneficial_use_->pos() >= first_use_after_split_pos)) {
1533 first_register_beneficial_use_ = NULL; 1599 first_register_beneficial_use_ = NULL;
1534 } 1600 }
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
1688 // Split at block's start. 1754 // Split at block's start.
1689 split_pos = split_block->entry()->lifetime_position(); 1755 split_pos = split_block->entry()->lifetime_position();
1690 } else { 1756 } else {
1691 // Interval [from, to) is contained inside a single block. 1757 // Interval [from, to) is contained inside a single block.
1692 1758
1693 // Split at position corresponding to the end of the previous 1759 // Split at position corresponding to the end of the previous
1694 // instruction. 1760 // instruction.
1695 split_pos = ToInstructionStart(to) - 1; 1761 split_pos = ToInstructionStart(to) - 1;
1696 } 1762 }
1697 1763
1698 ASSERT((split_pos != kIllegalPosition) && (from < split_pos)); 1764 ASSERT(split_pos != kIllegalPosition);
1765 ASSERT(from < split_pos);
1699 1766
1700 return range->SplitAt(split_pos); 1767 return range->SplitAt(split_pos);
1701 } 1768 }
1702 1769
1703 1770
1704 void FlowGraphAllocator::SpillBetween(LiveRange* range, 1771 void FlowGraphAllocator::SpillBetween(LiveRange* range,
1705 intptr_t from, 1772 intptr_t from,
1706 intptr_t to) { 1773 intptr_t to) {
1707 ASSERT(from < to); 1774 ASSERT(from < to);
1708 TRACE_ALLOC(OS::Print("spill v%" Pd " [%" Pd ", %" Pd ") " 1775 TRACE_ALLOC(OS::Print("spill v%" Pd " [%" Pd ", %" Pd ") "
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1762 // During fpu register allocation spill slot indices are computed in terms of 1829 // During fpu register allocation spill slot indices are computed in terms of
1763 // double (64bit) stack slots. We treat quad stack slot (128bit) as a 1830 // double (64bit) stack slots. We treat quad stack slot (128bit) as a
1764 // consecutive pair of two double spill slots. 1831 // consecutive pair of two double spill slots.
1765 // Special care is taken to never allocate the same index to both 1832 // Special care is taken to never allocate the same index to both
1766 // double and quad spill slots as it complicates disambiguation during 1833 // double and quad spill slots as it complicates disambiguation during
1767 // parallel move resolution. 1834 // parallel move resolution.
1768 const bool need_quad = (register_kind_ == Location::kFpuRegister) && 1835 const bool need_quad = (register_kind_ == Location::kFpuRegister) &&
1769 ((range->representation() == kUnboxedFloat32x4) || 1836 ((range->representation() == kUnboxedFloat32x4) ||
1770 (range->representation() == kUnboxedInt32x4) || 1837 (range->representation() == kUnboxedInt32x4) ||
1771 (range->representation() == kUnboxedFloat64x2)); 1838 (range->representation() == kUnboxedFloat64x2));
1839 const bool need_untagged = (register_kind_ == Location::kRegister) &&
1840 ((range->representation() == kUntagged));
1772 1841
1773 // Search for a free spill slot among allocated: the value in it should be 1842 // Search for a free spill slot among allocated: the value in it should be
1774 // dead and its type should match (e.g. it should not be a part of the quad if 1843 // dead and its type should match (e.g. it should not be a part of the quad if
1775 // we are allocating normal double slot). 1844 // we are allocating normal double slot).
1776 // For CPU registers we need to take reserved slots for try-catch into 1845 // For CPU registers we need to take reserved slots for try-catch into
1777 // account. 1846 // account.
1778 intptr_t idx = register_kind_ == Location::kRegister 1847 intptr_t idx = register_kind_ == Location::kRegister
1779 ? flow_graph_.graph_entry()->fixed_slot_count() 1848 ? flow_graph_.graph_entry()->fixed_slot_count()
1780 : 0; 1849 : 0;
1781 for (; idx < spill_slots_.length(); idx++) { 1850 for (; idx < spill_slots_.length(); idx++) {
1782 if ((need_quad == quad_spill_slots_[idx]) && 1851 if ((need_quad == quad_spill_slots_[idx]) &&
1852 (need_untagged == untagged_spill_slots_[idx]) &&
1783 (spill_slots_[idx] <= start)) { 1853 (spill_slots_[idx] <= start)) {
1784 break; 1854 break;
1785 } 1855 }
1786 } 1856 }
1787 1857
1788 if (idx == spill_slots_.length()) { 1858 if (idx == spill_slots_.length()) {
1789 // No free spill slot found. Allocate a new one. 1859 // No free spill slot found. Allocate a new one.
1790 spill_slots_.Add(0); 1860 spill_slots_.Add(0);
1791 quad_spill_slots_.Add(need_quad); 1861 quad_spill_slots_.Add(need_quad);
1862 untagged_spill_slots_.Add(need_untagged);
1792 if (need_quad) { // Allocate two double stack slots if we need quad slot. 1863 if (need_quad) { // Allocate two double stack slots if we need quad slot.
1793 spill_slots_.Add(0); 1864 spill_slots_.Add(0);
1794 quad_spill_slots_.Add(need_quad); 1865 quad_spill_slots_.Add(need_quad);
1866 untagged_spill_slots_.Add(need_untagged);
1795 } 1867 }
1796 } 1868 }
1797 1869
1798 // Set spill slot expiration boundary to the live range's end. 1870 // Set spill slot expiration boundary to the live range's end.
1799 spill_slots_[idx] = end; 1871 spill_slots_[idx] = end;
1800 if (need_quad) { 1872 if (need_quad) {
1801 ASSERT(quad_spill_slots_[idx] && quad_spill_slots_[idx + 1]); 1873 ASSERT(quad_spill_slots_[idx] && quad_spill_slots_[idx + 1]);
1802 idx++; // Use the higher index it corresponds to the lower stack address. 1874 idx++; // Use the higher index it corresponds to the lower stack address.
1803 spill_slots_[idx] = end; 1875 spill_slots_[idx] = end;
1804 } else { 1876 } else {
(...skipping 10 matching lines...) Expand all
1815 const intptr_t slot_idx = cpu_spill_slot_count_ + 1887 const intptr_t slot_idx = cpu_spill_slot_count_ +
1816 idx * kDoubleSpillFactor + (kDoubleSpillFactor - 1); 1888 idx * kDoubleSpillFactor + (kDoubleSpillFactor - 1);
1817 1889
1818 Location location; 1890 Location location;
1819 if ((range->representation() == kUnboxedFloat32x4) || 1891 if ((range->representation() == kUnboxedFloat32x4) ||
1820 (range->representation() == kUnboxedInt32x4) || 1892 (range->representation() == kUnboxedInt32x4) ||
1821 (range->representation() == kUnboxedFloat64x2)) { 1893 (range->representation() == kUnboxedFloat64x2)) {
1822 ASSERT(need_quad); 1894 ASSERT(need_quad);
1823 location = Location::QuadStackSlot(slot_idx); 1895 location = Location::QuadStackSlot(slot_idx);
1824 } else { 1896 } else {
1825 ASSERT((range->representation() == kUnboxedDouble) || 1897 ASSERT((range->representation() == kUnboxedDouble));
1826 (range->representation() == kUnboxedMint));
1827 location = Location::DoubleStackSlot(slot_idx); 1898 location = Location::DoubleStackSlot(slot_idx);
1828 } 1899 }
1829 range->set_spill_slot(location); 1900 range->set_spill_slot(location);
1830 } 1901 }
1831 1902
1832 spilled_.Add(range); 1903 spilled_.Add(range);
1833 } 1904 }
1834 1905
1835 1906
1836 void FlowGraphAllocator::MarkAsObjectAtSafepoints(LiveRange* range) { 1907 void FlowGraphAllocator::MarkAsObjectAtSafepoints(LiveRange* range) {
1837 intptr_t stack_index = range->spill_slot().stack_index(); 1908 intptr_t stack_index = range->spill_slot().stack_index();
1838 ASSERT(stack_index >= 0); 1909 ASSERT(stack_index >= 0);
1839 1910
1840 while (range != NULL) { 1911 while (range != NULL) {
1841 for (SafepointPosition* safepoint = range->first_safepoint(); 1912 for (SafepointPosition* safepoint = range->first_safepoint();
1842 safepoint != NULL; 1913 safepoint != NULL;
1843 safepoint = safepoint->next()) { 1914 safepoint = safepoint->next()) {
1915 // Mark the stack slot as having an object.
1844 safepoint->locs()->stack_bitmap()->Set(stack_index, true); 1916 safepoint->locs()->stack_bitmap()->Set(stack_index, true);
1845 } 1917 }
1846 range = range->next_sibling(); 1918 range = range->next_sibling();
1847 } 1919 }
1848 } 1920 }
1849 1921
1850 1922
1851 void FlowGraphAllocator::Spill(LiveRange* range) { 1923 void FlowGraphAllocator::Spill(LiveRange* range) {
1852 LiveRange* parent = GetLiveRange(range->vreg()); 1924 LiveRange* parent = GetLiveRange(range->vreg());
1853 if (parent->spill_slot().IsInvalid()) { 1925 if (parent->spill_slot().IsInvalid()) {
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
2192 UseInterval* first_pending_use_interval = 2264 UseInterval* first_pending_use_interval =
2193 allocated->finger()->first_pending_use_interval(); 2265 allocated->finger()->first_pending_use_interval();
2194 if (first_pending_use_interval->Contains(start)) { 2266 if (first_pending_use_interval->Contains(start)) {
2195 // This is an active interval. 2267 // This is an active interval.
2196 if (allocated->vreg() < 0) { 2268 if (allocated->vreg() < 0) {
2197 // This register blocked by an interval that 2269 // This register blocked by an interval that
2198 // can't be spilled. 2270 // can't be spilled.
2199 return false; 2271 return false;
2200 } 2272 }
2201 2273
2202 const UsePosition* use = 2274 UsePosition* use =
2203 allocated->finger()->FirstRegisterBeneficialUse(unallocated->Start()); 2275 allocated->finger()->FirstInterferingUse(start);
2204
2205 if ((use != NULL) && ((ToInstructionStart(use->pos()) - start) <= 1)) { 2276 if ((use != NULL) && ((ToInstructionStart(use->pos()) - start) <= 1)) {
2206 // This register is blocked by interval that is used 2277 // This register is blocked by interval that is used
2207 // as register in the current instruction and can't 2278 // as register in the current instruction and can't
2208 // be spilled. 2279 // be spilled.
2209 return false; 2280 return false;
2210 } 2281 }
2211 2282
2212 const intptr_t use_pos = (use != NULL) ? use->pos() 2283 const intptr_t use_pos = (use != NULL) ? use->pos()
2213 : allocated->End(); 2284 : allocated->End();
2214 2285
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2274 bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated, 2345 bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated,
2275 LiveRange* unallocated) { 2346 LiveRange* unallocated) {
2276 UseInterval* first_unallocated = 2347 UseInterval* first_unallocated =
2277 unallocated->finger()->first_pending_use_interval(); 2348 unallocated->finger()->first_pending_use_interval();
2278 const intptr_t intersection = FirstIntersection( 2349 const intptr_t intersection = FirstIntersection(
2279 allocated->finger()->first_pending_use_interval(), 2350 allocated->finger()->first_pending_use_interval(),
2280 first_unallocated); 2351 first_unallocated);
2281 if (intersection == kMaxPosition) return false; 2352 if (intersection == kMaxPosition) return false;
2282 2353
2283 const intptr_t spill_position = first_unallocated->start(); 2354 const intptr_t spill_position = first_unallocated->start();
2284 UsePosition* use = allocated->finger()->FirstRegisterUse(spill_position); 2355 UsePosition* use = allocated->finger()->FirstInterferingUse(spill_position);
2285 if (use == NULL) { 2356 if (use == NULL) {
2286 // No register uses after this point. 2357 // No register uses after this point.
2287 SpillAfter(allocated, spill_position); 2358 SpillAfter(allocated, spill_position);
2288 } else { 2359 } else {
2289 const intptr_t restore_position = 2360 const intptr_t restore_position =
2290 (spill_position < intersection) ? MinPosition(intersection, use->pos()) 2361 (spill_position < intersection) ? MinPosition(intersection, use->pos())
2291 : use->pos(); 2362 : use->pos();
2292 2363
2293 SpillBetween(allocated, spill_position, restore_position); 2364 SpillBetween(allocated, spill_position, restore_position);
2294 } 2365 }
(...skipping 14 matching lines...) Expand all
2309 parallel_move = CreateParallelMoveBefore(instr, pos); 2380 parallel_move = CreateParallelMoveBefore(instr, pos);
2310 } else { 2381 } else {
2311 parallel_move = CreateParallelMoveAfter(instr, pos); 2382 parallel_move = CreateParallelMoveAfter(instr, pos);
2312 } 2383 }
2313 2384
2314 return parallel_move->AddMove(to, from); 2385 return parallel_move->AddMove(to, from);
2315 } 2386 }
2316 2387
2317 2388
2318 void FlowGraphAllocator::ConvertUseTo(UsePosition* use, Location loc) { 2389 void FlowGraphAllocator::ConvertUseTo(UsePosition* use, Location loc) {
2390 ASSERT(!loc.IsPairLocation());
2319 ASSERT(use->location_slot() != NULL); 2391 ASSERT(use->location_slot() != NULL);
2320 Location* slot = use->location_slot(); 2392 Location* slot = use->location_slot();
2321 ASSERT(slot->IsUnallocated()); 2393 ASSERT(slot->IsUnallocated());
2322 TRACE_ALLOC(OS::Print(" use at %" Pd " converted to ", use->pos())); 2394 TRACE_ALLOC(OS::Print(" use at %" Pd " converted to ", use->pos()));
2323 TRACE_ALLOC(loc.Print()); 2395 TRACE_ALLOC(loc.Print());
2324 TRACE_ALLOC(OS::Print("\n")); 2396 TRACE_ALLOC(OS::Print("\n"));
2325 *slot = loc; 2397 *slot = loc;
2326 } 2398 }
2327 2399
2328 2400
(...skipping 14 matching lines...) Expand all
2343 } 2415 }
2344 2416
2345 // Add live registers at all safepoints for instructions with slow-path 2417 // Add live registers at all safepoints for instructions with slow-path
2346 // code. 2418 // code.
2347 if (loc.IsMachineRegister()) { 2419 if (loc.IsMachineRegister()) {
2348 for (SafepointPosition* safepoint = range->first_safepoint(); 2420 for (SafepointPosition* safepoint = range->first_safepoint();
2349 safepoint != NULL; 2421 safepoint != NULL;
2350 safepoint = safepoint->next()) { 2422 safepoint = safepoint->next()) {
2351 if (!safepoint->locs()->always_calls()) { 2423 if (!safepoint->locs()->always_calls()) {
2352 ASSERT(safepoint->locs()->can_call()); 2424 ASSERT(safepoint->locs()->can_call());
2353 safepoint->locs()->live_registers()->Add(loc); 2425 safepoint->locs()->live_registers()->Add(loc, range->representation());
2354 } 2426 }
2355 } 2427 }
2356 } 2428 }
2357 } 2429 }
2358 2430
2359 2431
2360 void FlowGraphAllocator::AdvanceActiveIntervals(const intptr_t start) { 2432 void FlowGraphAllocator::AdvanceActiveIntervals(const intptr_t start) {
2361 for (intptr_t reg = 0; reg < NumberOfRegisters(); reg++) { 2433 for (intptr_t reg = 0; reg < NumberOfRegisters(); reg++) {
2362 if (registers_[reg]->is_empty()) continue; 2434 if (registers_[reg]->is_empty()) continue;
2363 2435
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
2662 ASSERT(range->assigned_location().Equals(range->spill_slot())); 2734 ASSERT(range->assigned_location().Equals(range->spill_slot()));
2663 } else { 2735 } else {
2664 AddMoveAt(range->Start() + 1, 2736 AddMoveAt(range->Start() + 1,
2665 range->spill_slot(), 2737 range->spill_slot(),
2666 range->assigned_location()); 2738 range->assigned_location());
2667 } 2739 }
2668 } 2740 }
2669 } 2741 }
2670 2742
2671 2743
2744 static Representation RepresentationForRange(Representation definition_rep) {
2745 if (definition_rep == kUnboxedMint) {
2746 // kUnboxedMint is split into two ranges, each of which are kUntagged.
2747 return kUntagged;
2748 }
2749 return definition_rep;
2750 }
2751
2752
2672 void FlowGraphAllocator::CollectRepresentations() { 2753 void FlowGraphAllocator::CollectRepresentations() {
2673 // Parameters. 2754 // Parameters.
2674 GraphEntryInstr* graph_entry = flow_graph_.graph_entry(); 2755 GraphEntryInstr* graph_entry = flow_graph_.graph_entry();
2675 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); ++i) { 2756 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); ++i) {
2676 Definition* def = (*graph_entry->initial_definitions())[i]; 2757 Definition* def = (*graph_entry->initial_definitions())[i];
2677 value_representations_[def->ssa_temp_index()] = def->representation(); 2758 value_representations_[def->ssa_temp_index()] =
2759 RepresentationForRange(def->representation());
2678 ASSERT(!def->HasPairRepresentation()); 2760 ASSERT(!def->HasPairRepresentation());
2679 } 2761 }
2680 2762
2681 for (BlockIterator it = flow_graph_.reverse_postorder_iterator(); 2763 for (BlockIterator it = flow_graph_.reverse_postorder_iterator();
2682 !it.Done(); 2764 !it.Done();
2683 it.Advance()) { 2765 it.Advance()) {
2684 BlockEntryInstr* block = it.Current(); 2766 BlockEntryInstr* block = it.Current();
2685 2767
2686 // Catch entry. 2768 // Catch entry.
2687 if (block->IsCatchBlockEntry()) { 2769 if (block->IsCatchBlockEntry()) {
2688 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry(); 2770 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry();
2689 for (intptr_t i = 0; 2771 for (intptr_t i = 0;
2690 i < catch_entry->initial_definitions()->length(); 2772 i < catch_entry->initial_definitions()->length();
2691 ++i) { 2773 ++i) {
2692 Definition* def = (*catch_entry->initial_definitions())[i]; 2774 Definition* def = (*catch_entry->initial_definitions())[i];
2693 value_representations_[def->ssa_temp_index()] = def->representation(); 2775 ASSERT(!def->HasPairRepresentation());
2776 value_representations_[def->ssa_temp_index()] =
2777 RepresentationForRange(def->representation());
2694 } 2778 }
2695 } 2779 }
2696 // Phis. 2780 // Phis.
2697 if (block->IsJoinEntry()) { 2781 if (block->IsJoinEntry()) {
2698 JoinEntryInstr* join = block->AsJoinEntry(); 2782 JoinEntryInstr* join = block->AsJoinEntry();
2699 for (PhiIterator it(join); !it.Done(); it.Advance()) { 2783 for (PhiIterator it(join); !it.Done(); it.Advance()) {
2700 // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation. 2784 // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation.
2701 PhiInstr* phi = it.Current(); 2785 PhiInstr* phi = it.Current();
2702 if ((phi != NULL) && (phi->ssa_temp_index() >= 0)) { 2786 if ((phi != NULL) && (phi->ssa_temp_index() >= 0)) {
2703 value_representations_[phi->ssa_temp_index()] = phi->representation(); 2787 ASSERT(!phi->HasPairRepresentation());
2788 value_representations_[phi->ssa_temp_index()] =
2789 RepresentationForRange(phi->representation());
2704 } 2790 }
2705 } 2791 }
2706 } 2792 }
2707 // Normal instructions. 2793 // Normal instructions.
2708 for (ForwardInstructionIterator instr_it(block); 2794 for (ForwardInstructionIterator instr_it(block);
2709 !instr_it.Done(); 2795 !instr_it.Done();
2710 instr_it.Advance()) { 2796 instr_it.Advance()) {
2711 Definition* def = instr_it.Current()->AsDefinition(); 2797 Definition* def = instr_it.Current()->AsDefinition();
2712 if ((def != NULL) && (def->ssa_temp_index() >= 0)) { 2798 if ((def != NULL) && (def->ssa_temp_index() >= 0)) {
2713 const intptr_t vreg = def->ssa_temp_index(); 2799 const intptr_t vreg = def->ssa_temp_index();
2714 value_representations_[vreg] = def->representation(); 2800 value_representations_[vreg] =
2801 RepresentationForRange(def->representation());
2715 if (def->HasPairRepresentation()) { 2802 if (def->HasPairRepresentation()) {
2716 value_representations_[ToSecondPairVreg(vreg)] = def->representation(); 2803 value_representations_[ToSecondPairVreg(vreg)] =
2804 RepresentationForRange(def->representation());
2717 } 2805 }
2718 } 2806 }
2719 } 2807 }
2720 } 2808 }
2721 } 2809 }
2722 2810
2723 2811
2724 void FlowGraphAllocator::AllocateRegisters() { 2812 void FlowGraphAllocator::AllocateRegisters() {
2725 CollectRepresentations(); 2813 CollectRepresentations();
2726 2814
(...skipping 27 matching lines...) Expand all
2754 PrepareForAllocation(Location::kRegister, 2842 PrepareForAllocation(Location::kRegister,
2755 kNumberOfCpuRegisters, 2843 kNumberOfCpuRegisters,
2756 unallocated_cpu_, 2844 unallocated_cpu_,
2757 cpu_regs_, 2845 cpu_regs_,
2758 blocked_cpu_registers_); 2846 blocked_cpu_registers_);
2759 AllocateUnallocatedRanges(); 2847 AllocateUnallocatedRanges();
2760 2848
2761 cpu_spill_slot_count_ = spill_slots_.length(); 2849 cpu_spill_slot_count_ = spill_slots_.length();
2762 spill_slots_.Clear(); 2850 spill_slots_.Clear();
2763 quad_spill_slots_.Clear(); 2851 quad_spill_slots_.Clear();
2852 untagged_spill_slots_.Clear();
2764 2853
2765 PrepareForAllocation(Location::kFpuRegister, 2854 PrepareForAllocation(Location::kFpuRegister,
2766 kNumberOfFpuRegisters, 2855 kNumberOfFpuRegisters,
2767 unallocated_xmm_, 2856 unallocated_xmm_,
2768 fpu_regs_, 2857 fpu_regs_,
2769 blocked_fpu_registers_); 2858 blocked_fpu_registers_);
2770 AllocateUnallocatedRanges(); 2859 AllocateUnallocatedRanges();
2771 2860
2772 ResolveControlFlow(); 2861 ResolveControlFlow();
2773 2862
(...skipping 13 matching lines...) Expand all
2787 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", 2876 OS::Print("-- [after ssa allocator] ir [%s] -------------\n",
2788 function.ToFullyQualifiedCString()); 2877 function.ToFullyQualifiedCString());
2789 FlowGraphPrinter printer(flow_graph_, true); 2878 FlowGraphPrinter printer(flow_graph_, true);
2790 printer.PrintBlocks(); 2879 printer.PrintBlocks();
2791 OS::Print("----------------------------------------------\n"); 2880 OS::Print("----------------------------------------------\n");
2792 } 2881 }
2793 } 2882 }
2794 2883
2795 2884
2796 } // namespace dart 2885 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698