| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/live-range-separator.h" | 5 #include "src/compiler/live-range-separator.h" |
| 6 #include "src/compiler/register-allocator.h" | 6 #include "src/compiler/register-allocator.h" |
| 7 | 7 |
| 8 namespace v8 { | 8 namespace v8 { |
| 9 namespace internal { | 9 namespace internal { |
| 10 namespace compiler { | 10 namespace compiler { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 LifetimePosition end) { | 59 LifetimePosition end) { |
| 60 for (UseInterval *interval = range->first_interval(); interval != nullptr; | 60 for (UseInterval *interval = range->first_interval(); interval != nullptr; |
| 61 interval = interval->next()) { | 61 interval = interval->next()) { |
| 62 if (interval->start() <= start && start < interval->end()) return false; | 62 if (interval->start() <= start && start < interval->end()) return false; |
| 63 if (interval->start() < end && end <= interval->end()) return false; | 63 if (interval->start() < end && end <= interval->end()) return false; |
| 64 } | 64 } |
| 65 return true; | 65 return true; |
| 66 } | 66 } |
| 67 | 67 |
| 68 | 68 |
| 69 void CreateSplinter(LiveRange *range, RegisterAllocationData *data, | 69 void CreateSplinter(TopLevelLiveRange *range, RegisterAllocationData *data, |
| 70 LifetimePosition first_cut, LifetimePosition last_cut) { | 70 LifetimePosition first_cut, LifetimePosition last_cut) { |
| 71 DCHECK(!range->IsChild()); | |
| 72 DCHECK(!range->IsSplinter()); | 71 DCHECK(!range->IsSplinter()); |
| 73 // We can ignore ranges that live solely in deferred blocks. | 72 // We can ignore ranges that live solely in deferred blocks. |
| 74 // If a range ends right at the end of a deferred block, it is marked by | 73 // If a range ends right at the end of a deferred block, it is marked by |
| 75 // the range builder as ending at gap start of the next block - since the | 74 // the range builder as ending at gap start of the next block - since the |
| 76 // end is a position where the variable isn't live. We need to take that | 75 // end is a position where the variable isn't live. We need to take that |
| 77 // into consideration. | 76 // into consideration. |
| 78 LifetimePosition max_allowed_end = last_cut.NextFullStart(); | 77 LifetimePosition max_allowed_end = last_cut.NextFullStart(); |
| 79 | 78 |
| 80 if (first_cut <= range->Start() && max_allowed_end >= range->End()) { | 79 if (first_cut <= range->Start() && max_allowed_end >= range->End()) { |
| 81 return; | 80 return; |
| 82 } | 81 } |
| 83 | 82 |
| 84 LifetimePosition start = Max(first_cut, range->Start()); | 83 LifetimePosition start = Max(first_cut, range->Start()); |
| 85 LifetimePosition end = Min(last_cut, range->End()); | 84 LifetimePosition end = Min(last_cut, range->End()); |
| 86 // Skip ranges that have a hole where the deferred block(s) are. | 85 // Skip ranges that have a hole where the deferred block(s) are. |
| 87 if (IsIntervalAlreadyExcluded(range, start, end)) return; | 86 if (IsIntervalAlreadyExcluded(range, start, end)) return; |
| 88 | 87 |
| 89 if (start < end) { | 88 if (start < end) { |
| 90 // Ensure the original range has a spill range associated, before it gets | 89 // Ensure the original range has a spill range associated, before it gets |
| 91 // splintered. Splinters will point to it. This way, when attempting to | 90 // splintered. Splinters will point to it. This way, when attempting to |
| 92 // reuse spill slots of splinters, during allocation, we avoid clobbering | 91 // reuse spill slots of splinters, during allocation, we avoid clobbering |
| 93 // such slots. | 92 // such slots. |
| 94 if (range->MayRequireSpillRange()) { | 93 if (range->MayRequireSpillRange()) { |
| 95 data->CreateSpillRangeForLiveRange(range); | 94 data->CreateSpillRangeForLiveRange(range); |
| 96 } | 95 } |
| 97 LiveRange *result = data->NewChildRangeFor(range); | 96 TopLevelLiveRange *result = data->NextLiveRange(range->machine_type()); |
| 97 DCHECK_NULL(data->live_ranges()[result->vreg()]); |
| 98 data->live_ranges()[result->vreg()] = result; |
| 99 |
| 98 Zone *zone = data->allocation_zone(); | 100 Zone *zone = data->allocation_zone(); |
| 99 range->Splinter(start, end, result, zone); | 101 range->Splinter(start, end, result, zone); |
| 100 } | 102 } |
| 101 } | 103 } |
| 102 | 104 |
| 103 | 105 |
| 104 // Splinter all ranges live inside successive deferred blocks. | 106 // Splinter all ranges live inside successive deferred blocks. |
| 105 // No control flow analysis is performed. After the register allocation, we will | 107 // No control flow analysis is performed. After the register allocation, we will |
| 106 // merge the splinters back into the original ranges, and then rely on the | 108 // merge the splinters back into the original ranges, and then rely on the |
| 107 // range connector to properly connect them. | 109 // range connector to properly connect them. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 131 last->last_instruction_index()); | 133 last->last_instruction_index()); |
| 132 | 134 |
| 133 BitVector ranges_to_splinter(*in_set, zone); | 135 BitVector ranges_to_splinter(*in_set, zone); |
| 134 ranges_to_splinter.Union(*out_set); | 136 ranges_to_splinter.Union(*out_set); |
| 135 BitVector::Iterator iterator(&ranges_to_splinter); | 137 BitVector::Iterator iterator(&ranges_to_splinter); |
| 136 | 138 |
| 137 while (!iterator.Done()) { | 139 while (!iterator.Done()) { |
| 138 int range_id = iterator.Current(); | 140 int range_id = iterator.Current(); |
| 139 iterator.Advance(); | 141 iterator.Advance(); |
| 140 | 142 |
| 141 LiveRange *range = data->live_ranges()[range_id]; | 143 TopLevelLiveRange *range = data->live_ranges()[range_id]; |
| 142 CreateSplinter(range, data, first_cut, last_cut); | 144 CreateSplinter(range, data, first_cut, last_cut); |
| 143 } | 145 } |
| 144 } | 146 } |
| 145 } | 147 } |
| 146 } // namespace | 148 } // namespace |
| 147 | 149 |
| 148 | 150 |
| 149 void LiveRangeSeparator::Splinter() { | 151 void LiveRangeSeparator::Splinter() { |
| 150 AssociateDeferredBlockSequences(data()->code()); | 152 AssociateDeferredBlockSequences(data()->code()); |
| 151 SplinterRangesInDeferredBlocks(data()); | 153 SplinterRangesInDeferredBlocks(data()); |
| 152 } | 154 } |
| 153 | 155 |
| 154 | 156 |
| 155 void LiveRangeMerger::Merge() { | 157 void LiveRangeMerger::Merge() { |
| 156 int live_range_count = static_cast<int>(data()->live_ranges().size()); | 158 int live_range_count = static_cast<int>(data()->live_ranges().size()); |
| 157 for (int i = 0; i < live_range_count; ++i) { | 159 for (int i = 0; i < live_range_count; ++i) { |
| 158 LiveRange *range = data()->live_ranges()[i]; | 160 TopLevelLiveRange *range = data()->live_ranges()[i]; |
| 159 if (range == nullptr || range->IsEmpty() || range->IsChild() || | 161 if (range == nullptr || range->IsEmpty() || !range->IsSplinter()) { |
| 160 !range->IsSplinter()) { | |
| 161 continue; | 162 continue; |
| 162 } | 163 } |
| 163 LiveRange *splinter_parent = range->splintered_from(); | 164 TopLevelLiveRange *splinter_parent = range->splintered_from(); |
| 164 | 165 |
| 165 splinter_parent->Merge(range, data()); | 166 splinter_parent->Merge(range, data()); |
| 166 } | 167 } |
| 167 } | 168 } |
| 168 | 169 |
| 169 | 170 |
| 170 } // namespace compiler | 171 } // namespace compiler |
| 171 } // namespace internal | 172 } // namespace internal |
| 172 } // namespace v8 | 173 } // namespace v8 |
| OLD | NEW |