OLD | NEW |
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 617 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 if (loc.policy() == Location::kRequiresFpuRegister) { | 628 if (loc.policy() == Location::kRequiresFpuRegister) { |
629 return Location::kFpuRegister; | 629 return Location::kFpuRegister; |
630 } else { | 630 } else { |
631 return Location::kRegister; | 631 return Location::kRegister; |
632 } | 632 } |
633 } | 633 } |
634 | 634 |
635 | 635 |
636 static Location::Kind RegisterKindForResult(Instruction* instr) { | 636 static Location::Kind RegisterKindForResult(Instruction* instr) { |
637 if ((instr->representation() == kUnboxedDouble) || | 637 if ((instr->representation() == kUnboxedDouble) || |
638 (instr->representation() == kUnboxedMint) || | |
639 (instr->representation() == kUnboxedFloat32x4) || | 638 (instr->representation() == kUnboxedFloat32x4) || |
640 (instr->representation() == kUnboxedInt32x4) || | 639 (instr->representation() == kUnboxedInt32x4) || |
641 (instr->representation() == kUnboxedFloat64x2) || | 640 (instr->representation() == kUnboxedFloat64x2) || |
642 (instr->representation() == kPairOfUnboxedDouble)) { | 641 (instr->representation() == kPairOfUnboxedDouble)) { |
643 return Location::kFpuRegister; | 642 return Location::kFpuRegister; |
644 } else { | 643 } else { |
645 return Location::kRegister; | 644 return Location::kRegister; |
646 } | 645 } |
647 } | 646 } |
648 | 647 |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
798 } | 797 } |
799 | 798 |
800 const intptr_t block_start_pos = block->start_pos(); | 799 const intptr_t block_start_pos = block->start_pos(); |
801 const intptr_t use_pos = current->lifetime_position() + 1; | 800 const intptr_t use_pos = current->lifetime_position() + 1; |
802 | 801 |
803 Location* locations = | 802 Location* locations = |
804 Isolate::Current()->current_zone()->Alloc<Location>(env->Length()); | 803 Isolate::Current()->current_zone()->Alloc<Location>(env->Length()); |
805 | 804 |
806 for (intptr_t i = 0; i < env->Length(); ++i) { | 805 for (intptr_t i = 0; i < env->Length(); ++i) { |
807 Value* value = env->ValueAt(i); | 806 Value* value = env->ValueAt(i); |
808 locations[i] = Location::Any(); | |
809 Definition* def = value->definition(); | 807 Definition* def = value->definition(); |
| 808 if (def->HasPairRepresentation()) { |
| 809 locations[i] = Location::Pair(Location::Any(), Location::Any()); |
| 810 } else { |
| 811 locations[i] = Location::Any(); |
| 812 } |
810 | 813 |
811 if (def->IsPushArgument()) { | 814 if (def->IsPushArgument()) { |
812 // Frame size is unknown until after allocation. | 815 // Frame size is unknown until after allocation. |
813 locations[i] = Location::NoLocation(); | 816 locations[i] = Location::NoLocation(); |
814 continue; | 817 continue; |
815 } | 818 } |
816 | 819 |
817 ConstantInstr* constant = def->AsConstant(); | 820 ConstantInstr* constant = def->AsConstant(); |
818 if (constant != NULL) { | 821 if (constant != NULL) { |
819 locations[i] = Location::Constant(constant->value()); | 822 locations[i] = Location::Constant(constant->value()); |
820 continue; | 823 continue; |
821 } | 824 } |
822 | 825 |
823 MaterializeObjectInstr* mat = def->AsMaterializeObject(); | 826 MaterializeObjectInstr* mat = def->AsMaterializeObject(); |
824 if (mat != NULL) { | 827 if (mat != NULL) { |
825 // MaterializeObject itself produces no value. But its uses | 828 // MaterializeObject itself produces no value. But its uses |
826 // are treated as part of the environment: allocated locations | 829 // are treated as part of the environment: allocated locations |
827 // will be used when building deoptimization data. | 830 // will be used when building deoptimization data. |
828 locations[i] = Location::NoLocation(); | 831 locations[i] = Location::NoLocation(); |
829 ProcessMaterializationUses(block, block_start_pos, use_pos, mat); | 832 ProcessMaterializationUses(block, block_start_pos, use_pos, mat); |
830 continue; | 833 continue; |
831 } | 834 } |
832 | 835 |
833 LiveRange* range = GetLiveRange(def->ssa_temp_index()); | |
834 range->AddUseInterval(block_start_pos, use_pos); | |
835 range->AddUse(use_pos, &locations[i]); | |
836 | |
837 if (def->HasPairRepresentation()) { | 836 if (def->HasPairRepresentation()) { |
838 LiveRange* range = | 837 PairLocation* location_pair = locations[i].AsPairLocation(); |
| 838 { |
| 839 // First live range. |
| 840 LiveRange* range = GetLiveRange(def->ssa_temp_index()); |
| 841 range->AddUseInterval(block_start_pos, use_pos); |
| 842 range->AddUse(use_pos, location_pair->SlotAt(0)); |
| 843 } |
| 844 { |
| 845 // Second live range. |
| 846 LiveRange* range = |
839 GetLiveRange(ToSecondPairVreg(def->ssa_temp_index())); | 847 GetLiveRange(ToSecondPairVreg(def->ssa_temp_index())); |
| 848 range->AddUseInterval(block_start_pos, use_pos); |
| 849 range->AddUse(use_pos, location_pair->SlotAt(1)); |
| 850 } |
| 851 } else { |
| 852 LiveRange* range = GetLiveRange(def->ssa_temp_index()); |
840 range->AddUseInterval(block_start_pos, use_pos); | 853 range->AddUseInterval(block_start_pos, use_pos); |
841 range->AddUse(use_pos, &locations[i]); | 854 range->AddUse(use_pos, &locations[i]); |
842 } | 855 } |
843 } | 856 } |
844 | 857 |
845 env->set_locations(locations); | 858 env->set_locations(locations); |
846 env = env->outer(); | 859 env = env->outer(); |
847 } | 860 } |
848 } | 861 } |
849 | 862 |
(...skipping 15 matching lines...) Expand all Loading... |
865 | 878 |
866 for (intptr_t i = 0; i < mat->InputCount(); ++i) { | 879 for (intptr_t i = 0; i < mat->InputCount(); ++i) { |
867 Definition* def = mat->InputAt(i)->definition(); | 880 Definition* def = mat->InputAt(i)->definition(); |
868 | 881 |
869 ConstantInstr* constant = def->AsConstant(); | 882 ConstantInstr* constant = def->AsConstant(); |
870 if (constant != NULL) { | 883 if (constant != NULL) { |
871 locations[i] = Location::Constant(constant->value()); | 884 locations[i] = Location::Constant(constant->value()); |
872 continue; | 885 continue; |
873 } | 886 } |
874 | 887 |
875 locations[i] = Location::Any(); | |
876 | |
877 LiveRange* range = GetLiveRange(def->ssa_temp_index()); | |
878 range->AddUseInterval(block_start_pos, use_pos); | |
879 range->AddUse(use_pos, &locations[i]); | |
880 if (def->HasPairRepresentation()) { | 888 if (def->HasPairRepresentation()) { |
881 LiveRange* range = GetLiveRange(ToSecondPairVreg(def->ssa_temp_index())); | 889 locations[i] = Location::Pair(Location::Any(), Location::Any()); |
| 890 PairLocation* location_pair = locations[i].AsPairLocation(); |
| 891 { |
| 892 // First live range. |
| 893 LiveRange* range = GetLiveRange(def->ssa_temp_index()); |
| 894 range->AddUseInterval(block_start_pos, use_pos); |
| 895 range->AddUse(use_pos, location_pair->SlotAt(0)); |
| 896 } |
| 897 { |
| 898 // Second live range. |
| 899 LiveRange* range = |
| 900 GetLiveRange(ToSecondPairVreg(def->ssa_temp_index())); |
| 901 range->AddUseInterval(block_start_pos, use_pos); |
| 902 range->AddUse(use_pos, location_pair->SlotAt(1)); |
| 903 } |
| 904 } else { |
| 905 locations[i] = Location::Any(); |
| 906 LiveRange* range = GetLiveRange(def->ssa_temp_index()); |
882 range->AddUseInterval(block_start_pos, use_pos); | 907 range->AddUseInterval(block_start_pos, use_pos); |
883 range->AddUse(use_pos, &locations[i]); | 908 range->AddUse(use_pos, &locations[i]); |
884 } | 909 } |
885 } | 910 } |
886 | 911 |
887 mat->set_locations(locations); | 912 mat->set_locations(locations); |
888 } | 913 } |
889 | 914 |
890 | 915 |
891 void FlowGraphAllocator::ProcessOneInput(BlockEntryInstr* block, | 916 void FlowGraphAllocator::ProcessOneInput(BlockEntryInstr* block, |
892 intptr_t pos, | 917 intptr_t pos, |
893 Location* in_ref, | 918 Location* in_ref, |
894 Value* input, | 919 Value* input, |
895 intptr_t vreg) { | 920 intptr_t vreg, |
| 921 RegisterSet* live_registers) { |
896 ASSERT(in_ref != NULL); | 922 ASSERT(in_ref != NULL); |
897 ASSERT(!in_ref->IsPairLocation()); | 923 ASSERT(!in_ref->IsPairLocation()); |
898 ASSERT(input != NULL); | 924 ASSERT(input != NULL); |
899 ASSERT(block != NULL); | 925 ASSERT(block != NULL); |
900 LiveRange* range = GetLiveRange(vreg); | 926 LiveRange* range = GetLiveRange(vreg); |
901 if (in_ref->IsMachineRegister()) { | 927 if (in_ref->IsMachineRegister()) { |
902 // Input is expected in a fixed register. Expected shape of | 928 // Input is expected in a fixed register. Expected shape of |
903 // live ranges: | 929 // live ranges: |
904 // | 930 // |
905 // j' i i' | 931 // j' i i' |
906 // value --* | 932 // value --* |
907 // register [-----) | 933 // register [-----) |
908 // | 934 // |
| 935 if (live_registers != NULL) { |
| 936 live_registers->Add(*in_ref, range->representation()); |
| 937 } |
909 MoveOperands* move = | 938 MoveOperands* move = |
910 AddMoveAt(pos - 1, *in_ref, Location::Any()); | 939 AddMoveAt(pos - 1, *in_ref, Location::Any()); |
911 BlockLocation(*in_ref, pos - 1, pos + 1); | 940 BlockLocation(*in_ref, pos - 1, pos + 1); |
912 range->AddUseInterval(block->start_pos(), pos - 1); | 941 range->AddUseInterval(block->start_pos(), pos - 1); |
913 range->AddHintedUse(pos - 1, move->src_slot(), in_ref); | 942 range->AddHintedUse(pos - 1, move->src_slot(), in_ref); |
914 } else if (in_ref->IsUnallocated()) { | 943 } else if (in_ref->IsUnallocated()) { |
915 if (in_ref->policy() == Location::kWritableRegister) { | 944 if (in_ref->policy() == Location::kWritableRegister) { |
916 // Writable unallocated input. Expected shape of | 945 // Writable unallocated input. Expected shape of |
917 // live ranges: | 946 // live ranges: |
918 // | 947 // |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1110 if (locs->out(0).IsUnallocated() && | 1139 if (locs->out(0).IsUnallocated() && |
1111 (locs->out(0).policy() == Location::kSameAsFirstInput) && | 1140 (locs->out(0).policy() == Location::kSameAsFirstInput) && |
1112 (locs->in(0).IsMachineRegister())) { | 1141 (locs->in(0).IsMachineRegister())) { |
1113 locs->set_out(0, locs->in(0)); | 1142 locs->set_out(0, locs->in(0)); |
1114 } | 1143 } |
1115 | 1144 |
1116 const bool output_same_as_first_input = | 1145 const bool output_same_as_first_input = |
1117 locs->out(0).IsUnallocated() && | 1146 locs->out(0).IsUnallocated() && |
1118 (locs->out(0).policy() == Location::kSameAsFirstInput); | 1147 (locs->out(0).policy() == Location::kSameAsFirstInput); |
1119 | 1148 |
| 1149 // Output is same as first input which is a pair. |
| 1150 if (output_same_as_first_input && locs->in(0).IsPairLocation()) { |
| 1151 // Make out into a PairLocation. |
| 1152 locs->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 1153 Location::RequiresRegister())); |
| 1154 } |
1120 // Add uses from the deoptimization environment. | 1155 // Add uses from the deoptimization environment. |
1121 if (current->env() != NULL) ProcessEnvironmentUses(block, current); | 1156 if (current->env() != NULL) ProcessEnvironmentUses(block, current); |
1122 | 1157 |
1123 // Process inputs. | 1158 // Process inputs. |
1124 // Skip the first input if output is specified with kSameAsFirstInput policy, | 1159 // Skip the first input if output is specified with kSameAsFirstInput policy, |
1125 // they will be processed together at the very end. | 1160 // they will be processed together at the very end. |
1126 { | 1161 { |
1127 for (intptr_t j = output_same_as_first_input ? 1 : 0; | 1162 for (intptr_t j = output_same_as_first_input ? 1 : 0; |
1128 j < locs->input_count(); | 1163 j < locs->input_count(); |
1129 j++) { | 1164 j++) { |
1130 // Determine if we are dealing with a value pair, and if so, whether | 1165 // Determine if we are dealing with a value pair, and if so, whether |
1131 // the location is the first register or second register. | 1166 // the location is the first register or second register. |
1132 Value* input = current->InputAt(j); | 1167 Value* input = current->InputAt(j); |
1133 Location* in_ref = locs->in_slot(j); | 1168 Location* in_ref = locs->in_slot(j); |
| 1169 RegisterSet* live_registers = NULL; |
| 1170 if (locs->HasCallOnSlowPath()) { |
| 1171 live_registers = locs->live_registers(); |
| 1172 } |
1134 if (in_ref->IsPairLocation()) { | 1173 if (in_ref->IsPairLocation()) { |
1135 ASSERT(input->definition()->HasPairRepresentation()); | 1174 ASSERT(input->definition()->HasPairRepresentation()); |
1136 PairLocation* pair = in_ref->AsPairLocation(); | 1175 PairLocation* pair = in_ref->AsPairLocation(); |
1137 const intptr_t vreg = input->definition()->ssa_temp_index(); | 1176 const intptr_t vreg = input->definition()->ssa_temp_index(); |
1138 // Each element of the pair is assigned it's own virtual register number | 1177 // Each element of the pair is assigned it's own virtual register number |
1139 // and is allocated its own LiveRange. | 1178 // and is allocated its own LiveRange. |
1140 ProcessOneInput(block, pos, pair->SlotAt(0), | 1179 ProcessOneInput(block, pos, pair->SlotAt(0), |
1141 input, vreg); | 1180 input, vreg, live_registers); |
1142 ProcessOneInput(block, pos, pair->SlotAt(1), input, | 1181 ProcessOneInput(block, pos, pair->SlotAt(1), input, |
1143 ToSecondPairVreg(vreg)); | 1182 ToSecondPairVreg(vreg), live_registers); |
1144 } else { | 1183 } else { |
1145 ProcessOneInput(block, pos, in_ref, input, | 1184 ProcessOneInput(block, pos, in_ref, input, |
1146 input->definition()->ssa_temp_index()); | 1185 input->definition()->ssa_temp_index(), live_registers); |
1147 } | 1186 } |
1148 } | 1187 } |
1149 } | 1188 } |
1150 | 1189 |
1151 // Process temps. | 1190 // Process temps. |
1152 for (intptr_t j = 0; j < locs->temp_count(); j++) { | 1191 for (intptr_t j = 0; j < locs->temp_count(); j++) { |
1153 // Expected shape of live range: | 1192 // Expected shape of live range: |
1154 // | 1193 // |
1155 // i i' | 1194 // i i' |
1156 // [--) | 1195 // [--) |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1518 Location* loc = use->location_slot(); | 1557 Location* loc = use->location_slot(); |
1519 if (loc->IsUnallocated() && loc->IsRegisterBeneficial()) { | 1558 if (loc->IsUnallocated() && loc->IsRegisterBeneficial()) { |
1520 first_register_beneficial_use_ = use; | 1559 first_register_beneficial_use_ = use; |
1521 return use; | 1560 return use; |
1522 } | 1561 } |
1523 } | 1562 } |
1524 return NULL; | 1563 return NULL; |
1525 } | 1564 } |
1526 | 1565 |
1527 | 1566 |
| 1567 UsePosition* AllocationFinger::FirstInterferingUse(intptr_t after) { |
| 1568 if (IsInstructionEndPosition(after)) { |
| 1569 // If after is a position at the end of the instruction disregard |
| 1570 // any use occuring at it. |
| 1571 after += 1; |
| 1572 } |
| 1573 return FirstRegisterUse(after); |
| 1574 } |
| 1575 |
| 1576 |
1528 void AllocationFinger::UpdateAfterSplit(intptr_t first_use_after_split_pos) { | 1577 void AllocationFinger::UpdateAfterSplit(intptr_t first_use_after_split_pos) { |
1529 if ((first_register_use_ != NULL) && | 1578 if ((first_register_use_ != NULL) && |
1530 (first_register_use_->pos() >= first_use_after_split_pos)) { | 1579 (first_register_use_->pos() >= first_use_after_split_pos)) { |
1531 first_register_use_ = NULL; | 1580 first_register_use_ = NULL; |
1532 } | 1581 } |
1533 | 1582 |
1534 if ((first_register_beneficial_use_ != NULL) && | 1583 if ((first_register_beneficial_use_ != NULL) && |
1535 (first_register_beneficial_use_->pos() >= first_use_after_split_pos)) { | 1584 (first_register_beneficial_use_->pos() >= first_use_after_split_pos)) { |
1536 first_register_beneficial_use_ = NULL; | 1585 first_register_beneficial_use_ = NULL; |
1537 } | 1586 } |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1691 // Split at block's start. | 1740 // Split at block's start. |
1692 split_pos = split_block->entry()->lifetime_position(); | 1741 split_pos = split_block->entry()->lifetime_position(); |
1693 } else { | 1742 } else { |
1694 // Interval [from, to) is contained inside a single block. | 1743 // Interval [from, to) is contained inside a single block. |
1695 | 1744 |
1696 // Split at position corresponding to the end of the previous | 1745 // Split at position corresponding to the end of the previous |
1697 // instruction. | 1746 // instruction. |
1698 split_pos = ToInstructionStart(to) - 1; | 1747 split_pos = ToInstructionStart(to) - 1; |
1699 } | 1748 } |
1700 | 1749 |
1701 ASSERT((split_pos != kIllegalPosition) && (from < split_pos)); | 1750 ASSERT(split_pos != kIllegalPosition); |
| 1751 ASSERT(from < split_pos); |
1702 | 1752 |
1703 return range->SplitAt(split_pos); | 1753 return range->SplitAt(split_pos); |
1704 } | 1754 } |
1705 | 1755 |
1706 | 1756 |
1707 void FlowGraphAllocator::SpillBetween(LiveRange* range, | 1757 void FlowGraphAllocator::SpillBetween(LiveRange* range, |
1708 intptr_t from, | 1758 intptr_t from, |
1709 intptr_t to) { | 1759 intptr_t to) { |
1710 ASSERT(from < to); | 1760 ASSERT(from < to); |
1711 TRACE_ALLOC(OS::Print("spill v%" Pd " [%" Pd ", %" Pd ") " | 1761 TRACE_ALLOC(OS::Print("spill v%" Pd " [%" Pd ", %" Pd ") " |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1818 const intptr_t slot_idx = cpu_spill_slot_count_ + | 1868 const intptr_t slot_idx = cpu_spill_slot_count_ + |
1819 idx * kDoubleSpillFactor + (kDoubleSpillFactor - 1); | 1869 idx * kDoubleSpillFactor + (kDoubleSpillFactor - 1); |
1820 | 1870 |
1821 Location location; | 1871 Location location; |
1822 if ((range->representation() == kUnboxedFloat32x4) || | 1872 if ((range->representation() == kUnboxedFloat32x4) || |
1823 (range->representation() == kUnboxedInt32x4) || | 1873 (range->representation() == kUnboxedInt32x4) || |
1824 (range->representation() == kUnboxedFloat64x2)) { | 1874 (range->representation() == kUnboxedFloat64x2)) { |
1825 ASSERT(need_quad); | 1875 ASSERT(need_quad); |
1826 location = Location::QuadStackSlot(slot_idx); | 1876 location = Location::QuadStackSlot(slot_idx); |
1827 } else { | 1877 } else { |
1828 ASSERT((range->representation() == kUnboxedDouble) || | 1878 ASSERT((range->representation() == kUnboxedDouble)); |
1829 (range->representation() == kUnboxedMint)); | |
1830 location = Location::DoubleStackSlot(slot_idx); | 1879 location = Location::DoubleStackSlot(slot_idx); |
1831 } | 1880 } |
1832 range->set_spill_slot(location); | 1881 range->set_spill_slot(location); |
1833 } | 1882 } |
1834 | 1883 |
1835 spilled_.Add(range); | 1884 spilled_.Add(range); |
1836 } | 1885 } |
1837 | 1886 |
1838 | 1887 |
1839 void FlowGraphAllocator::MarkAsObjectAtSafepoints(LiveRange* range) { | 1888 void FlowGraphAllocator::MarkAsObjectAtSafepoints(LiveRange* range) { |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2194 UseInterval* first_pending_use_interval = | 2243 UseInterval* first_pending_use_interval = |
2195 allocated->finger()->first_pending_use_interval(); | 2244 allocated->finger()->first_pending_use_interval(); |
2196 if (first_pending_use_interval->Contains(start)) { | 2245 if (first_pending_use_interval->Contains(start)) { |
2197 // This is an active interval. | 2246 // This is an active interval. |
2198 if (allocated->vreg() < 0) { | 2247 if (allocated->vreg() < 0) { |
2199 // This register blocked by an interval that | 2248 // This register blocked by an interval that |
2200 // can't be spilled. | 2249 // can't be spilled. |
2201 return false; | 2250 return false; |
2202 } | 2251 } |
2203 | 2252 |
2204 const UsePosition* use = | 2253 UsePosition* use = |
2205 allocated->finger()->FirstRegisterBeneficialUse(unallocated->Start()); | 2254 allocated->finger()->FirstInterferingUse(start); |
2206 | |
2207 if ((use != NULL) && ((ToInstructionStart(use->pos()) - start) <= 1)) { | 2255 if ((use != NULL) && ((ToInstructionStart(use->pos()) - start) <= 1)) { |
2208 // This register is blocked by interval that is used | 2256 // This register is blocked by interval that is used |
2209 // as register in the current instruction and can't | 2257 // as register in the current instruction and can't |
2210 // be spilled. | 2258 // be spilled. |
2211 return false; | 2259 return false; |
2212 } | 2260 } |
2213 | 2261 |
2214 const intptr_t use_pos = (use != NULL) ? use->pos() | 2262 const intptr_t use_pos = (use != NULL) ? use->pos() |
2215 : allocated->End(); | 2263 : allocated->End(); |
2216 | 2264 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2276 bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated, | 2324 bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated, |
2277 LiveRange* unallocated) { | 2325 LiveRange* unallocated) { |
2278 UseInterval* first_unallocated = | 2326 UseInterval* first_unallocated = |
2279 unallocated->finger()->first_pending_use_interval(); | 2327 unallocated->finger()->first_pending_use_interval(); |
2280 const intptr_t intersection = FirstIntersection( | 2328 const intptr_t intersection = FirstIntersection( |
2281 allocated->finger()->first_pending_use_interval(), | 2329 allocated->finger()->first_pending_use_interval(), |
2282 first_unallocated); | 2330 first_unallocated); |
2283 if (intersection == kMaxPosition) return false; | 2331 if (intersection == kMaxPosition) return false; |
2284 | 2332 |
2285 const intptr_t spill_position = first_unallocated->start(); | 2333 const intptr_t spill_position = first_unallocated->start(); |
2286 UsePosition* use = allocated->finger()->FirstRegisterUse(spill_position); | 2334 UsePosition* use = allocated->finger()->FirstInterferingUse(spill_position); |
2287 if (use == NULL) { | 2335 if (use == NULL) { |
2288 // No register uses after this point. | 2336 // No register uses after this point. |
2289 SpillAfter(allocated, spill_position); | 2337 SpillAfter(allocated, spill_position); |
2290 } else { | 2338 } else { |
2291 const intptr_t restore_position = | 2339 const intptr_t restore_position = |
2292 (spill_position < intersection) ? MinPosition(intersection, use->pos()) | 2340 (spill_position < intersection) ? MinPosition(intersection, use->pos()) |
2293 : use->pos(); | 2341 : use->pos(); |
2294 | 2342 |
2295 SpillBetween(allocated, spill_position, restore_position); | 2343 SpillBetween(allocated, spill_position, restore_position); |
2296 } | 2344 } |
(...skipping 14 matching lines...) Expand all Loading... |
2311 parallel_move = CreateParallelMoveBefore(instr, pos); | 2359 parallel_move = CreateParallelMoveBefore(instr, pos); |
2312 } else { | 2360 } else { |
2313 parallel_move = CreateParallelMoveAfter(instr, pos); | 2361 parallel_move = CreateParallelMoveAfter(instr, pos); |
2314 } | 2362 } |
2315 | 2363 |
2316 return parallel_move->AddMove(to, from); | 2364 return parallel_move->AddMove(to, from); |
2317 } | 2365 } |
2318 | 2366 |
2319 | 2367 |
2320 void FlowGraphAllocator::ConvertUseTo(UsePosition* use, Location loc) { | 2368 void FlowGraphAllocator::ConvertUseTo(UsePosition* use, Location loc) { |
| 2369 ASSERT(!loc.IsPairLocation()); |
2321 ASSERT(use->location_slot() != NULL); | 2370 ASSERT(use->location_slot() != NULL); |
2322 Location* slot = use->location_slot(); | 2371 Location* slot = use->location_slot(); |
2323 ASSERT(slot->IsUnallocated()); | 2372 ASSERT(slot->IsUnallocated()); |
2324 TRACE_ALLOC(OS::Print(" use at %" Pd " converted to ", use->pos())); | 2373 TRACE_ALLOC(OS::Print(" use at %" Pd " converted to ", use->pos())); |
2325 TRACE_ALLOC(loc.Print()); | 2374 TRACE_ALLOC(loc.Print()); |
2326 TRACE_ALLOC(OS::Print("\n")); | 2375 TRACE_ALLOC(OS::Print("\n")); |
2327 *slot = loc; | 2376 *slot = loc; |
2328 } | 2377 } |
2329 | 2378 |
2330 | 2379 |
(...skipping 14 matching lines...) Expand all Loading... |
2345 } | 2394 } |
2346 | 2395 |
2347 // Add live registers at all safepoints for instructions with slow-path | 2396 // Add live registers at all safepoints for instructions with slow-path |
2348 // code. | 2397 // code. |
2349 if (loc.IsMachineRegister()) { | 2398 if (loc.IsMachineRegister()) { |
2350 for (SafepointPosition* safepoint = range->first_safepoint(); | 2399 for (SafepointPosition* safepoint = range->first_safepoint(); |
2351 safepoint != NULL; | 2400 safepoint != NULL; |
2352 safepoint = safepoint->next()) { | 2401 safepoint = safepoint->next()) { |
2353 if (!safepoint->locs()->always_calls()) { | 2402 if (!safepoint->locs()->always_calls()) { |
2354 ASSERT(safepoint->locs()->can_call()); | 2403 ASSERT(safepoint->locs()->can_call()); |
2355 safepoint->locs()->live_registers()->Add(loc); | 2404 safepoint->locs()->live_registers()->Add(loc, range->representation()); |
2356 } | 2405 } |
2357 } | 2406 } |
2358 } | 2407 } |
2359 } | 2408 } |
2360 | 2409 |
2361 | 2410 |
2362 void FlowGraphAllocator::AdvanceActiveIntervals(const intptr_t start) { | 2411 void FlowGraphAllocator::AdvanceActiveIntervals(const intptr_t start) { |
2363 for (intptr_t reg = 0; reg < NumberOfRegisters(); reg++) { | 2412 for (intptr_t reg = 0; reg < NumberOfRegisters(); reg++) { |
2364 if (registers_[reg].is_empty()) continue; | 2413 if (registers_[reg].is_empty()) continue; |
2365 | 2414 |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2659 ASSERT(range->assigned_location().Equals(range->spill_slot())); | 2708 ASSERT(range->assigned_location().Equals(range->spill_slot())); |
2660 } else { | 2709 } else { |
2661 AddMoveAt(range->Start() + 1, | 2710 AddMoveAt(range->Start() + 1, |
2662 range->spill_slot(), | 2711 range->spill_slot(), |
2663 range->assigned_location()); | 2712 range->assigned_location()); |
2664 } | 2713 } |
2665 } | 2714 } |
2666 } | 2715 } |
2667 | 2716 |
2668 | 2717 |
| 2718 static Representation RepresentationForRange(Representation definition_rep) { |
| 2719 if (definition_rep == kUnboxedMint) { |
| 2720 // kUnboxedMint is split into two ranges, each of which are kUntagged. |
| 2721 return kUntagged; |
| 2722 } |
| 2723 return definition_rep; |
| 2724 } |
| 2725 |
| 2726 |
2669 void FlowGraphAllocator::CollectRepresentations() { | 2727 void FlowGraphAllocator::CollectRepresentations() { |
2670 // Parameters. | 2728 // Parameters. |
2671 GraphEntryInstr* graph_entry = flow_graph_.graph_entry(); | 2729 GraphEntryInstr* graph_entry = flow_graph_.graph_entry(); |
2672 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); ++i) { | 2730 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); ++i) { |
2673 Definition* def = (*graph_entry->initial_definitions())[i]; | 2731 Definition* def = (*graph_entry->initial_definitions())[i]; |
2674 value_representations_[def->ssa_temp_index()] = def->representation(); | 2732 value_representations_[def->ssa_temp_index()] = |
| 2733 RepresentationForRange(def->representation()); |
2675 ASSERT(!def->HasPairRepresentation()); | 2734 ASSERT(!def->HasPairRepresentation()); |
2676 } | 2735 } |
2677 | 2736 |
2678 for (BlockIterator it = flow_graph_.reverse_postorder_iterator(); | 2737 for (BlockIterator it = flow_graph_.reverse_postorder_iterator(); |
2679 !it.Done(); | 2738 !it.Done(); |
2680 it.Advance()) { | 2739 it.Advance()) { |
2681 BlockEntryInstr* block = it.Current(); | 2740 BlockEntryInstr* block = it.Current(); |
2682 | 2741 |
2683 // Catch entry. | 2742 // Catch entry. |
2684 if (block->IsCatchBlockEntry()) { | 2743 if (block->IsCatchBlockEntry()) { |
2685 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry(); | 2744 CatchBlockEntryInstr* catch_entry = block->AsCatchBlockEntry(); |
2686 for (intptr_t i = 0; | 2745 for (intptr_t i = 0; |
2687 i < catch_entry->initial_definitions()->length(); | 2746 i < catch_entry->initial_definitions()->length(); |
2688 ++i) { | 2747 ++i) { |
2689 Definition* def = (*catch_entry->initial_definitions())[i]; | 2748 Definition* def = (*catch_entry->initial_definitions())[i]; |
2690 value_representations_[def->ssa_temp_index()] = def->representation(); | 2749 ASSERT(!def->HasPairRepresentation()); |
| 2750 value_representations_[def->ssa_temp_index()] = |
| 2751 RepresentationForRange(def->representation()); |
2691 } | 2752 } |
2692 } | 2753 } |
2693 // Phis. | 2754 // Phis. |
2694 if (block->IsJoinEntry()) { | 2755 if (block->IsJoinEntry()) { |
2695 JoinEntryInstr* join = block->AsJoinEntry(); | 2756 JoinEntryInstr* join = block->AsJoinEntry(); |
2696 for (PhiIterator it(join); !it.Done(); it.Advance()) { | 2757 for (PhiIterator it(join); !it.Done(); it.Advance()) { |
2697 // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation. | 2758 // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation. |
2698 PhiInstr* phi = it.Current(); | 2759 PhiInstr* phi = it.Current(); |
2699 if ((phi != NULL) && (phi->ssa_temp_index() >= 0)) { | 2760 if ((phi != NULL) && (phi->ssa_temp_index() >= 0)) { |
2700 value_representations_[phi->ssa_temp_index()] = phi->representation(); | 2761 ASSERT(!phi->HasPairRepresentation()); |
| 2762 value_representations_[phi->ssa_temp_index()] = |
| 2763 RepresentationForRange(phi->representation()); |
2701 } | 2764 } |
2702 } | 2765 } |
2703 } | 2766 } |
2704 // Normal instructions. | 2767 // Normal instructions. |
2705 for (ForwardInstructionIterator instr_it(block); | 2768 for (ForwardInstructionIterator instr_it(block); |
2706 !instr_it.Done(); | 2769 !instr_it.Done(); |
2707 instr_it.Advance()) { | 2770 instr_it.Advance()) { |
2708 Definition* def = instr_it.Current()->AsDefinition(); | 2771 Definition* def = instr_it.Current()->AsDefinition(); |
2709 if ((def != NULL) && (def->ssa_temp_index() >= 0)) { | 2772 if ((def != NULL) && (def->ssa_temp_index() >= 0)) { |
2710 const intptr_t vreg = def->ssa_temp_index(); | 2773 const intptr_t vreg = def->ssa_temp_index(); |
2711 value_representations_[vreg] = def->representation(); | 2774 value_representations_[vreg] = |
| 2775 RepresentationForRange(def->representation()); |
2712 if (def->HasPairRepresentation()) { | 2776 if (def->HasPairRepresentation()) { |
2713 value_representations_[ToSecondPairVreg(vreg)] = def->representation(); | 2777 value_representations_[ToSecondPairVreg(vreg)] = |
| 2778 RepresentationForRange(def->representation()); |
2714 } | 2779 } |
2715 } | 2780 } |
2716 } | 2781 } |
2717 } | 2782 } |
2718 } | 2783 } |
2719 | 2784 |
2720 | 2785 |
2721 void FlowGraphAllocator::AllocateRegisters() { | 2786 void FlowGraphAllocator::AllocateRegisters() { |
2722 CollectRepresentations(); | 2787 CollectRepresentations(); |
2723 | 2788 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2784 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", | 2849 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", |
2785 function.ToFullyQualifiedCString()); | 2850 function.ToFullyQualifiedCString()); |
2786 FlowGraphPrinter printer(flow_graph_, true); | 2851 FlowGraphPrinter printer(flow_graph_, true); |
2787 printer.PrintBlocks(); | 2852 printer.PrintBlocks(); |
2788 OS::Print("----------------------------------------------\n"); | 2853 OS::Print("----------------------------------------------\n"); |
2789 } | 2854 } |
2790 } | 2855 } |
2791 | 2856 |
2792 | 2857 |
2793 } // namespace dart | 2858 } // namespace dart |
OLD | NEW |