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