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]; | |
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 typedef std::set<int> LiveRangeIDs; | |
57 | |
58 | |
59 // Utility offering shorthand building of a set of integers. Circumvents current | |
60 // incomplete support for C++ features such as instantiation lists, on OS X and | |
61 // Android. | |
62 class Conflicts { | |
63 public: | |
64 Conflicts(int number_of_conflicts, ...) : set_() { | |
Benedikt Meurer
2015/07/14 04:35:01
Do we really need to use varargs here? You could a
Mircea Trofin
2015/07/14 16:19:18
Agreed, and even easier, since the purpose was sim
| |
65 CHECK(number_of_conflicts > 0); | |
66 va_list conflict_list; | |
67 va_start(conflict_list, number_of_conflicts); | |
68 for (int i = 0; i < number_of_conflicts; ++i) { | |
69 int val = va_arg(conflict_list, int); | |
70 set_.insert(val); | |
71 } | |
72 va_end(conflict_list); | |
73 } | |
74 | |
75 operator LiveRangeIDs&() { return set_; } | |
Benedikt Meurer
2015/07/14 04:35:01
Same here, there's no need for operator overloadin
Mircea Trofin
2015/07/14 16:19:18
Done.
| |
76 static LiveRangeIDs& None() { return empty_set; } | |
77 | |
78 private: | |
79 static LiveRangeIDs empty_set; | |
80 LiveRangeIDs set_; | |
81 }; | |
82 | |
83 LiveRangeIDs Conflicts::empty_set; | |
84 | |
85 class CoalescedLiveRangesTest : public TestWithZone { | |
86 public: | |
87 CoalescedLiveRangesTest() : TestWithZone(), ranges_(zone()) {} | |
88 bool CheckConflictsMatch(const LiveRange* range, const LiveRangeIDs& ids); | |
89 | |
90 CoalescedLiveRanges& ranges() { return ranges_; } | |
91 const CoalescedLiveRanges& ranges() const { return ranges_; } | |
92 bool AllocationsAreValid() const; | |
93 void RemoveConflicts(LiveRange* range); | |
94 | |
95 private: | |
96 CoalescedLiveRanges ranges_; | |
97 }; | |
98 | |
99 | |
100 void CoalescedLiveRangesTest::RemoveConflicts(LiveRange* range) { | |
101 ranges().RemoveConflicts(range, [](LiveRange* conflict) {}); | |
102 } | |
103 | |
104 | |
105 bool CoalescedLiveRangesTest::AllocationsAreValid() const { | |
106 return ranges().TestOnlyVerifyAllocationsAreValid(); | |
107 } | |
108 | |
109 | |
110 bool CoalescedLiveRangesTest::CheckConflictsMatch(const LiveRange* range, | |
111 const LiveRangeIDs& ids) { | |
112 LiveRangeIDs found_ids; | |
113 | |
114 ranges().VisitConflicts(range, [&](const LiveRange* conflict) { | |
115 found_ids.insert(conflict->id()); | |
116 return true; | |
117 }); | |
118 return found_ids == ids; | |
119 } | |
120 | |
121 | |
122 TEST_F(CoalescedLiveRangesTest, VisitEmptyAllocations) { | |
123 LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(1, 5); | |
124 ASSERT_TRUE(ranges().empty()); | |
125 ASSERT_TRUE(AllocationsAreValid()); | |
126 ASSERT_TRUE(CheckConflictsMatch(range, Conflicts::None())); | |
127 } | |
128 | |
129 | |
130 TEST_F(CoalescedLiveRangesTest, CandidateBeforeAfterAllocations) { | |
131 LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(5, 6); | |
132 ranges().AllocateRange(range); | |
133 ASSERT_FALSE(ranges().empty()); | |
134 ASSERT_TRUE(AllocationsAreValid()); | |
135 LiveRange* query = TestRangeBuilder(zone()).Id(2).Build(1, 2); | |
136 ASSERT_TRUE(CheckConflictsMatch(query, Conflicts::None())); | |
137 query = TestRangeBuilder(zone()).Id(3).Build(1, 5); | |
138 ASSERT_TRUE(CheckConflictsMatch(query, Conflicts::None())); | |
139 } | |
140 | |
141 | |
142 TEST_F(CoalescedLiveRangesTest, CandidateBeforeAfterManyAllocations) { | |
143 LiveRange* range = | |
144 TestRangeBuilder(zone()).Id(1).Add(5, 7).Add(10, 12).Build(); | |
145 ranges().AllocateRange(range); | |
146 ASSERT_FALSE(ranges().empty()); | |
147 ASSERT_TRUE(AllocationsAreValid()); | |
148 LiveRange* query = | |
149 TestRangeBuilder(zone()).Id(2).Add(1, 2).Add(13, 15).Build(); | |
150 ASSERT_TRUE(CheckConflictsMatch(query, Conflicts::None())); | |
151 query = TestRangeBuilder(zone()).Id(3).Add(1, 5).Add(12, 15).Build(); | |
152 ASSERT_TRUE(CheckConflictsMatch(query, Conflicts::None())); | |
153 } | |
154 | |
155 | |
156 TEST_F(CoalescedLiveRangesTest, SelfConflictsWithSelf) { | |
157 LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(1, 5); | |
158 ranges().AllocateRange(range); | |
159 ASSERT_FALSE(ranges().empty()); | |
160 ASSERT_TRUE(AllocationsAreValid()); | |
161 ASSERT_TRUE(CheckConflictsMatch(range, Conflicts(1, 1))); | |
162 range = TestRangeBuilder(zone()).Id(2).Build(8, 10); | |
163 ranges().AllocateRange(range); | |
164 ASSERT_TRUE(CheckConflictsMatch(range, Conflicts(1, 2))); | |
165 } | |
166 | |
167 | |
168 TEST_F(CoalescedLiveRangesTest, QueryStartsBeforeConflict) { | |
169 LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(2, 5); | |
170 ranges().AllocateRange(range); | |
171 LiveRange* query = TestRangeBuilder(zone()).Id(2).Build(1, 3); | |
172 ASSERT_TRUE(CheckConflictsMatch(query, Conflicts(1, 1))); | |
173 range = TestRangeBuilder(zone()).Id(3).Build(8, 10); | |
174 ranges().AllocateRange(range); | |
175 query = TestRangeBuilder(zone()).Id(4).Build(6, 9); | |
176 ASSERT_TRUE(CheckConflictsMatch(query, Conflicts(1, 3))); | |
177 } | |
178 | |
179 | |
180 TEST_F(CoalescedLiveRangesTest, QueryStartsInConflict) { | |
181 LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(2, 5); | |
182 ranges().AllocateRange(range); | |
183 LiveRange* query = TestRangeBuilder(zone()).Id(2).Build(3, 6); | |
184 ASSERT_TRUE(CheckConflictsMatch(query, Conflicts(1, 1))); | |
185 range = TestRangeBuilder(zone()).Id(3).Build(8, 10); | |
186 ranges().AllocateRange(range); | |
187 query = TestRangeBuilder(zone()).Id(4).Build(9, 11); | |
188 ASSERT_TRUE(CheckConflictsMatch(query, Conflicts(1, 3))); | |
189 } | |
190 | |
191 | |
192 TEST_F(CoalescedLiveRangesTest, QueryContainedInConflict) { | |
193 LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(1, 5); | |
194 ranges().AllocateRange(range); | |
195 LiveRange* query = TestRangeBuilder(zone()).Id(2).Build(2, 3); | |
196 ASSERT_TRUE(CheckConflictsMatch(query, Conflicts(1, 1))); | |
197 } | |
198 | |
199 | |
200 TEST_F(CoalescedLiveRangesTest, QueryContainsConflict) { | |
201 LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(2, 3); | |
202 ranges().AllocateRange(range); | |
203 LiveRange* query = TestRangeBuilder(zone()).Id(2).Build(1, 5); | |
204 ASSERT_TRUE(CheckConflictsMatch(query, Conflicts(1, 1))); | |
205 } | |
206 | |
207 | |
208 TEST_F(CoalescedLiveRangesTest, QueryCoversManyIntervalsSameRange) { | |
209 LiveRange* range = | |
210 TestRangeBuilder(zone()).Id(1).Add(1, 5).Add(7, 9).Add(20, 25).Build(); | |
211 ranges().AllocateRange(range); | |
212 LiveRange* query = TestRangeBuilder(zone()).Id(2).Build(2, 8); | |
213 ASSERT_TRUE(CheckConflictsMatch(query, Conflicts(1, 1))); | |
214 } | |
215 | |
216 | |
217 TEST_F(CoalescedLiveRangesTest, QueryCoversManyIntervalsDifferentRanges) { | |
218 LiveRange* range = | |
219 TestRangeBuilder(zone()).Id(1).Add(1, 5).Add(20, 25).Build(); | |
220 ranges().AllocateRange(range); | |
221 range = TestRangeBuilder(zone()).Id(2).Build(7, 10); | |
222 ranges().AllocateRange(range); | |
223 LiveRange* query = TestRangeBuilder(zone()).Id(3).Build(2, 22); | |
224 ASSERT_TRUE(CheckConflictsMatch(query, Conflicts(2, 1, 2))); | |
225 } | |
226 | |
227 | |
228 TEST_F(CoalescedLiveRangesTest, QueryFitsInGaps) { | |
229 LiveRange* range = | |
230 TestRangeBuilder(zone()).Id(1).Add(1, 5).Add(10, 15).Add(20, 25).Build(); | |
231 ranges().AllocateRange(range); | |
232 LiveRange* query = | |
233 TestRangeBuilder(zone()).Id(3).Add(5, 10).Add(16, 19).Add(27, 30).Build(); | |
234 ASSERT_TRUE(CheckConflictsMatch(query, Conflicts::None())); | |
235 } | |
236 | |
237 | |
238 TEST_F(CoalescedLiveRangesTest, DeleteConflictBefore) { | |
239 LiveRange* range = TestRangeBuilder(zone()).Id(1).Add(1, 4).Add(5, 6).Build(); | |
240 ranges().AllocateRange(range); | |
241 range = TestRangeBuilder(zone()).Id(2).Build(40, 50); | |
242 ranges().AllocateRange(range); | |
243 LiveRange* query = TestRangeBuilder(zone()).Id(3).Build(3, 7); | |
244 RemoveConflicts(query); | |
245 query = TestRangeBuilder(zone()).Id(4).Build(0, 60); | |
246 ASSERT_TRUE(CheckConflictsMatch(query, Conflicts(1, 2))); | |
247 } | |
248 | |
249 | |
250 TEST_F(CoalescedLiveRangesTest, DeleteConflictAfter) { | |
251 LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(1, 5); | |
252 ranges().AllocateRange(range); | |
253 range = TestRangeBuilder(zone()).Id(2).Add(40, 50).Add(60, 70).Build(); | |
254 ranges().AllocateRange(range); | |
255 LiveRange* query = TestRangeBuilder(zone()).Id(3).Build(45, 60); | |
256 RemoveConflicts(query); | |
257 query = TestRangeBuilder(zone()).Id(4).Build(0, 60); | |
258 ASSERT_TRUE(CheckConflictsMatch(query, Conflicts(1, 1))); | |
259 } | |
260 | |
261 | |
262 TEST_F(CoalescedLiveRangesTest, DeleteConflictStraddle) { | |
263 LiveRange* range = | |
264 TestRangeBuilder(zone()).Id(1).Add(1, 5).Add(10, 20).Build(); | |
265 ranges().AllocateRange(range); | |
266 range = TestRangeBuilder(zone()).Id(2).Build(40, 50); | |
267 ranges().AllocateRange(range); | |
268 LiveRange* query = TestRangeBuilder(zone()).Id(3).Build(4, 15); | |
269 RemoveConflicts(query); | |
270 query = TestRangeBuilder(zone()).Id(4).Build(0, 60); | |
271 ASSERT_TRUE(CheckConflictsMatch(query, Conflicts(1, 2))); | |
272 } | |
273 | |
274 | |
275 TEST_F(CoalescedLiveRangesTest, DeleteConflictManyOverlapsBefore) { | |
276 LiveRange* range = | |
277 TestRangeBuilder(zone()).Id(1).Add(1, 5).Add(6, 10).Add(10, 20).Build(); | |
278 ranges().AllocateRange(range); | |
279 range = TestRangeBuilder(zone()).Id(2).Build(40, 50); | |
280 ranges().AllocateRange(range); | |
281 LiveRange* query = TestRangeBuilder(zone()).Id(3).Build(4, 15); | |
282 RemoveConflicts(query); | |
283 query = TestRangeBuilder(zone()).Id(4).Build(0, 60); | |
284 ASSERT_TRUE(CheckConflictsMatch(query, Conflicts(1, 2))); | |
285 } | |
286 | |
287 | |
288 } // namespace compiler | |
289 } // namespace internal | |
290 } // namespace v8 | |
OLD | NEW |