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 |