| 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 |