OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 the V8 project authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "src/compiler/coalesced-live-ranges.h" | |
6 #include "test/unittests/test-utils.h" | |
7 | |
8 namespace v8 { | |
9 namespace internal { | |
10 namespace compiler { | |
11 | |
12 | |
13 // Utility offering shorthand syntax for building up a range by providing its ID | |
14 // and pairs (start, end) specifying intervals. Circumvents current incomplete | |
15 // support for C++ features such as instantiation lists, on OS X and Android. | |
16 class TestRangeBuilder { | |
17 public: | |
18 explicit TestRangeBuilder(Zone* zone) : id_(-1), pairs_(), zone_(zone) {} | |
19 | |
20 TestRangeBuilder& Id(int id) { | |
21 id_ = id; | |
22 return *this; | |
23 } | |
24 TestRangeBuilder& Add(int start, int end) { | |
25 pairs_.push_back({start, end}); | |
26 return *this; | |
27 } | |
28 | |
29 LiveRange* Build(int start, int end) { return Add(start, end).Build(); } | |
30 | |
31 LiveRange* Build() { | |
32 LiveRange* range = new (zone_) LiveRange(id_, MachineType::kRepTagged); | |
33 // Traverse the provided interval specifications backwards, because that is | |
34 // what LiveRange expects. | |
35 for (int i = static_cast<int>(pairs_.size()) - 1; i >= 0; --i) { | |
36 auto pair = pairs_[i]; | |
Jarin
2015/07/21 08:51:18
auto -> Interval
Mircea Trofin
2015/07/21 14:51:01
Done.
| |
37 LifetimePosition start = LifetimePosition::FromInt(pair.first); | |
38 LifetimePosition end = LifetimePosition::FromInt(pair.second); | |
39 CHECK(start < end); | |
40 range->AddUseInterval(start, end, zone_); | |
41 } | |
42 | |
43 pairs_.clear(); | |
44 return range; | |
45 } | |
46 | |
47 private: | |
48 typedef std::pair<int, int> Interval; | |
49 typedef std::vector<Interval> IntervalList; | |
50 int id_; | |
51 IntervalList pairs_; | |
52 Zone* zone_; | |
53 }; | |
54 | |
55 | |
56 class CoalescedLiveRangesTest : public TestWithZone { | |
57 public: | |
58 CoalescedLiveRangesTest() : TestWithZone(), ranges_(zone()) {} | |
59 bool HasNoConflicts(const LiveRange* range); | |
60 bool ConflictsPreciselyWith(const LiveRange* range, int id); | |
61 bool ConflictsPreciselyWith(const LiveRange* range, int id1, int id2); | |
62 | |
63 CoalescedLiveRanges& ranges() { return ranges_; } | |
64 const CoalescedLiveRanges& ranges() const { return ranges_; } | |
65 bool AllocationsAreValid() const; | |
66 void RemoveConflicts(LiveRange* range); | |
67 | |
68 private: | |
69 typedef ZoneSet<int> LiveRangeIDs; | |
70 bool IsRangeConflictingWith(const LiveRange* range, const LiveRangeIDs& ids); | |
71 CoalescedLiveRanges ranges_; | |
72 }; | |
73 | |
74 | |
75 bool CoalescedLiveRangesTest::ConflictsPreciselyWith(const LiveRange* range, | |
76 int id) { | |
77 LiveRangeIDs set(zone()); | |
78 set.insert(id); | |
79 return IsRangeConflictingWith(range, set); | |
80 } | |
81 | |
82 | |
83 bool CoalescedLiveRangesTest::ConflictsPreciselyWith(const LiveRange* range, | |
84 int id1, int id2) { | |
85 LiveRangeIDs set(zone()); | |
86 set.insert(id1); | |
87 set.insert(id2); | |
88 return IsRangeConflictingWith(range, set); | |
89 } | |
90 | |
91 | |
92 bool CoalescedLiveRangesTest::HasNoConflicts(const LiveRange* range) { | |
93 LiveRangeIDs set(zone()); | |
94 return IsRangeConflictingWith(range, set); | |
95 } | |
96 | |
97 | |
98 void CoalescedLiveRangesTest::RemoveConflicts(LiveRange* range) { | |
99 auto conflicts = ranges().GetConflicts(range); | |
100 LiveRangeIDs seen(zone()); | |
101 for (auto c = conflicts.Current(); c != nullptr; | |
102 c = conflicts.ClearCurrentAndGetNext()) { | |
103 EXPECT_FALSE(seen.count(c->id()) > 0); | |
104 seen.insert(c->id()); | |
105 } | |
106 } | |
107 | |
108 | |
109 bool CoalescedLiveRangesTest::AllocationsAreValid() const { | |
110 return ranges().TestOnlyVerifyAllocationsAreValid(); | |
111 } | |
112 | |
113 | |
114 bool CoalescedLiveRangesTest::IsRangeConflictingWith(const LiveRange* range, | |
115 const LiveRangeIDs& ids) { | |
116 LiveRangeIDs found_ids(zone()); | |
117 | |
118 auto conflicts = ranges().GetConflicts(range); | |
119 for (auto conflict = conflicts.Current(); conflict != nullptr; | |
120 conflict = conflicts.GetNext()) { | |
121 found_ids.insert(conflict->id()); | |
122 } | |
123 return found_ids == ids; | |
124 } | |
125 | |
126 | |
127 TEST_F(CoalescedLiveRangesTest, VisitEmptyAllocations) { | |
128 LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(1, 5); | |
129 ASSERT_TRUE(ranges().empty()); | |
130 ASSERT_TRUE(AllocationsAreValid()); | |
131 ASSERT_TRUE(HasNoConflicts(range)); | |
132 } | |
133 | |
134 | |
135 TEST_F(CoalescedLiveRangesTest, CandidateBeforeAfterAllocations) { | |
136 LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(5, 6); | |
137 ranges().AllocateRange(range); | |
138 ASSERT_FALSE(ranges().empty()); | |
139 ASSERT_TRUE(AllocationsAreValid()); | |
140 LiveRange* query = TestRangeBuilder(zone()).Id(2).Build(1, 2); | |
141 ASSERT_TRUE(HasNoConflicts(query)); | |
142 query = TestRangeBuilder(zone()).Id(3).Build(1, 5); | |
143 ASSERT_TRUE(HasNoConflicts(query)); | |
144 } | |
145 | |
146 | |
147 TEST_F(CoalescedLiveRangesTest, CandidateBeforeAfterManyAllocations) { | |
148 LiveRange* range = | |
149 TestRangeBuilder(zone()).Id(1).Add(5, 7).Add(10, 12).Build(); | |
150 ranges().AllocateRange(range); | |
151 ASSERT_FALSE(ranges().empty()); | |
152 ASSERT_TRUE(AllocationsAreValid()); | |
153 LiveRange* query = | |
154 TestRangeBuilder(zone()).Id(2).Add(1, 2).Add(13, 15).Build(); | |
155 ASSERT_TRUE(HasNoConflicts(query)); | |
156 query = TestRangeBuilder(zone()).Id(3).Add(1, 5).Add(12, 15).Build(); | |
157 ASSERT_TRUE(HasNoConflicts(query)); | |
158 } | |
159 | |
160 | |
161 TEST_F(CoalescedLiveRangesTest, SelfConflictsPreciselyWithSelf) { | |
162 LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(1, 5); | |
163 ranges().AllocateRange(range); | |
164 ASSERT_FALSE(ranges().empty()); | |
165 ASSERT_TRUE(AllocationsAreValid()); | |
166 ASSERT_TRUE(ConflictsPreciselyWith(range, 1)); | |
167 range = TestRangeBuilder(zone()).Id(2).Build(8, 10); | |
168 ranges().AllocateRange(range); | |
169 ASSERT_TRUE(ConflictsPreciselyWith(range, 2)); | |
170 } | |
171 | |
172 | |
173 TEST_F(CoalescedLiveRangesTest, QueryStartsBeforeConflict) { | |
174 LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(2, 5); | |
175 ranges().AllocateRange(range); | |
176 LiveRange* query = TestRangeBuilder(zone()).Id(2).Build(1, 3); | |
177 ASSERT_TRUE(ConflictsPreciselyWith(query, 1)); | |
178 range = TestRangeBuilder(zone()).Id(3).Build(8, 10); | |
179 ranges().AllocateRange(range); | |
180 query = TestRangeBuilder(zone()).Id(4).Build(6, 9); | |
181 ASSERT_TRUE(ConflictsPreciselyWith(query, 3)); | |
182 } | |
183 | |
184 | |
185 TEST_F(CoalescedLiveRangesTest, QueryStartsInConflict) { | |
186 LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(2, 5); | |
187 ranges().AllocateRange(range); | |
188 LiveRange* query = TestRangeBuilder(zone()).Id(2).Build(3, 6); | |
189 ASSERT_TRUE(ConflictsPreciselyWith(query, 1)); | |
190 range = TestRangeBuilder(zone()).Id(3).Build(8, 10); | |
191 ranges().AllocateRange(range); | |
192 query = TestRangeBuilder(zone()).Id(4).Build(9, 11); | |
193 ASSERT_TRUE(ConflictsPreciselyWith(query, 3)); | |
194 } | |
195 | |
196 | |
197 TEST_F(CoalescedLiveRangesTest, QueryContainedInConflict) { | |
198 LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(1, 5); | |
199 ranges().AllocateRange(range); | |
200 LiveRange* query = TestRangeBuilder(zone()).Id(2).Build(2, 3); | |
201 ASSERT_TRUE(ConflictsPreciselyWith(query, 1)); | |
202 } | |
203 | |
204 | |
205 TEST_F(CoalescedLiveRangesTest, QueryContainsConflict) { | |
206 LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(2, 3); | |
207 ranges().AllocateRange(range); | |
208 LiveRange* query = TestRangeBuilder(zone()).Id(2).Build(1, 5); | |
209 ASSERT_TRUE(ConflictsPreciselyWith(query, 1)); | |
210 } | |
211 | |
212 | |
213 TEST_F(CoalescedLiveRangesTest, QueryCoversManyIntervalsSameRange) { | |
214 LiveRange* range = | |
215 TestRangeBuilder(zone()).Id(1).Add(1, 5).Add(7, 9).Add(20, 25).Build(); | |
216 ranges().AllocateRange(range); | |
217 LiveRange* query = TestRangeBuilder(zone()).Id(2).Build(2, 8); | |
218 ASSERT_TRUE(ConflictsPreciselyWith(query, 1)); | |
219 } | |
220 | |
221 | |
222 TEST_F(CoalescedLiveRangesTest, QueryCoversManyIntervalsDifferentRanges) { | |
223 LiveRange* range = | |
224 TestRangeBuilder(zone()).Id(1).Add(1, 5).Add(20, 25).Build(); | |
225 ranges().AllocateRange(range); | |
226 range = TestRangeBuilder(zone()).Id(2).Build(7, 10); | |
227 ranges().AllocateRange(range); | |
228 LiveRange* query = TestRangeBuilder(zone()).Id(3).Build(2, 22); | |
229 ASSERT_TRUE(ConflictsPreciselyWith(query, 1, 2)); | |
230 } | |
231 | |
232 | |
233 TEST_F(CoalescedLiveRangesTest, QueryFitsInGaps) { | |
234 LiveRange* range = | |
235 TestRangeBuilder(zone()).Id(1).Add(1, 5).Add(10, 15).Add(20, 25).Build(); | |
236 ranges().AllocateRange(range); | |
237 LiveRange* query = | |
238 TestRangeBuilder(zone()).Id(3).Add(5, 10).Add(16, 19).Add(27, 30).Build(); | |
239 ASSERT_TRUE(HasNoConflicts(query)); | |
240 } | |
241 | |
242 | |
243 TEST_F(CoalescedLiveRangesTest, DeleteConflictBefore) { | |
244 LiveRange* range = TestRangeBuilder(zone()).Id(1).Add(1, 4).Add(5, 6).Build(); | |
245 ranges().AllocateRange(range); | |
246 range = TestRangeBuilder(zone()).Id(2).Build(40, 50); | |
247 ranges().AllocateRange(range); | |
248 LiveRange* query = TestRangeBuilder(zone()).Id(3).Build(3, 7); | |
249 RemoveConflicts(query); | |
250 query = TestRangeBuilder(zone()).Id(4).Build(0, 60); | |
251 ASSERT_TRUE(ConflictsPreciselyWith(query, 2)); | |
252 } | |
253 | |
254 | |
255 TEST_F(CoalescedLiveRangesTest, DeleteConflictAfter) { | |
256 LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(1, 5); | |
257 ranges().AllocateRange(range); | |
258 range = TestRangeBuilder(zone()).Id(2).Add(40, 50).Add(60, 70).Build(); | |
259 ranges().AllocateRange(range); | |
260 LiveRange* query = TestRangeBuilder(zone()).Id(3).Build(45, 60); | |
261 RemoveConflicts(query); | |
262 query = TestRangeBuilder(zone()).Id(4).Build(0, 60); | |
263 ASSERT_TRUE(ConflictsPreciselyWith(query, 1)); | |
264 } | |
265 | |
266 | |
267 TEST_F(CoalescedLiveRangesTest, DeleteConflictStraddle) { | |
268 LiveRange* range = | |
269 TestRangeBuilder(zone()).Id(1).Add(1, 5).Add(10, 20).Build(); | |
270 ranges().AllocateRange(range); | |
271 range = TestRangeBuilder(zone()).Id(2).Build(40, 50); | |
272 ranges().AllocateRange(range); | |
273 LiveRange* query = TestRangeBuilder(zone()).Id(3).Build(4, 15); | |
274 RemoveConflicts(query); | |
275 query = TestRangeBuilder(zone()).Id(4).Build(0, 60); | |
276 ASSERT_TRUE(ConflictsPreciselyWith(query, 2)); | |
277 } | |
278 | |
279 | |
280 TEST_F(CoalescedLiveRangesTest, DeleteConflictManyOverlapsBefore) { | |
281 LiveRange* range = | |
282 TestRangeBuilder(zone()).Id(1).Add(1, 5).Add(6, 10).Add(10, 20).Build(); | |
283 ranges().AllocateRange(range); | |
284 range = TestRangeBuilder(zone()).Id(2).Build(40, 50); | |
285 ranges().AllocateRange(range); | |
286 LiveRange* query = TestRangeBuilder(zone()).Id(3).Build(4, 15); | |
287 RemoveConflicts(query); | |
288 query = TestRangeBuilder(zone()).Id(4).Build(0, 60); | |
289 ASSERT_TRUE(ConflictsPreciselyWith(query, 2)); | |
290 } | |
291 | |
292 | |
293 TEST_F(CoalescedLiveRangesTest, DeleteWhenConflictRepeatsAfterNonConflict) { | |
294 LiveRange* range = | |
295 TestRangeBuilder(zone()).Id(1).Add(1, 5).Add(6, 10).Add(20, 30).Build(); | |
296 ranges().AllocateRange(range); | |
297 range = TestRangeBuilder(zone()).Id(2).Build(12, 15); | |
298 ranges().AllocateRange(range); | |
299 LiveRange* query = | |
300 TestRangeBuilder(zone()).Id(3).Add(1, 8).Add(22, 25).Build(); | |
301 RemoveConflicts(query); | |
302 query = TestRangeBuilder(zone()).Id(4).Build(0, 60); | |
303 ASSERT_TRUE(ConflictsPreciselyWith(query, 2)); | |
304 } | |
305 | |
306 | |
307 } // namespace compiler | |
308 } // namespace internal | |
309 } // namespace v8 | |
OLD | NEW |