blob: e4fc2ca15143a827bfdd96837cd82dfb347316de [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
3// found in the LICENSE file.
4
5
6#include "test/unittests/compiler/live-range-builder.h"
7#include "test/unittests/test-utils.h"
8
9
10// TODO(mtrofin): would we want to centralize this definition?
11#ifdef DEBUG
12#define V8_ASSERT_DEBUG_DEATH(statement, regex) \
13 ASSERT_DEATH_IF_SUPPORTED(statement, regex)
14#define DISABLE_IN_RELEASE(Name) Name
15
16#else
17#define V8_ASSERT_DEBUG_DEATH(statement, regex) statement
18#define DISABLE_IN_RELEASE(Name) DISABLED_##Name
19#endif // DEBUG
20
21namespace v8 {
22namespace internal {
23namespace compiler {
24
25class LiveRangeUnitTest : public TestWithZone {
26 public:
27 // Split helper, to avoid int->LifetimePosition conversion nuisance.
28 LiveRange* Split(LiveRange* range, int pos) {
29 return range->SplitAt(LifetimePosition::FromInt(pos), zone());
30 }
31
32
33 TopLevelLiveRange* Splinter(TopLevelLiveRange* top, int start, int end,
34 int new_id = 0) {
35 if (top->splinter() == nullptr) {
36 TopLevelLiveRange* ret = new (zone())
37 TopLevelLiveRange(new_id, MachineRepresentation::kTagged);
38 top->SetSplinter(ret);
39 }
40 top->Splinter(LifetimePosition::FromInt(start),
41 LifetimePosition::FromInt(end), zone());
42 return top->splinter();
43 }
44
45 // Ranges first and second match structurally.
46 bool RangesMatch(LiveRange* first, LiveRange* second) {
47 if (first->Start() != second->Start() || first->End() != second->End()) {
48 return false;
49 }
50 UseInterval* i1 = first->first_interval();
51 UseInterval* i2 = second->first_interval();
52
53 while (i1 != nullptr && i2 != nullptr) {
54 if (i1->start() != i2->start() || i1->end() != i2->end()) return false;
55 i1 = i1->next();
56 i2 = i2->next();
57 }
58 if (i1 != nullptr || i2 != nullptr) return false;
59
60 UsePosition* p1 = first->first_pos();
61 UsePosition* p2 = second->first_pos();
62
63 while (p1 != nullptr && p2 != nullptr) {
64 if (p1->pos() != p2->pos()) return false;
65 p1 = p1->next();
66 p2 = p2->next();
67 }
68 if (p1 != nullptr || p2 != nullptr) return false;
69 return true;
70 }
71};
72
73
74TEST_F(LiveRangeUnitTest, InvalidConstruction) {
75 // Build a range manually, because the builder guards against empty cases.
76 TopLevelLiveRange* range =
77 new (zone()) TopLevelLiveRange(1, MachineRepresentation::kTagged);
78 V8_ASSERT_DEBUG_DEATH(
79 range->AddUseInterval(LifetimePosition::FromInt(0),
80 LifetimePosition::FromInt(0), zone()),
81 ".*");
82}
83
84
85TEST_F(LiveRangeUnitTest, SplitInvalidStart) {
86 TopLevelLiveRange* range = TestRangeBuilder(zone()).Build(0, 1);
87 V8_ASSERT_DEBUG_DEATH(Split(range, 0), ".*");
88}
89
90
91TEST_F(LiveRangeUnitTest, DISABLE_IN_RELEASE(InvalidSplitEnd)) {
92 TopLevelLiveRange* range = TestRangeBuilder(zone()).Build(0, 1);
93 ASSERT_DEATH_IF_SUPPORTED(Split(range, 1), ".*");
94}
95
96
97TEST_F(LiveRangeUnitTest, DISABLE_IN_RELEASE(SplitInvalidPreStart)) {
98 TopLevelLiveRange* range = TestRangeBuilder(zone()).Build(1, 2);
99 ASSERT_DEATH_IF_SUPPORTED(Split(range, 0), ".*");
100}
101
102
103TEST_F(LiveRangeUnitTest, DISABLE_IN_RELEASE(SplitInvalidPostEnd)) {
104 TopLevelLiveRange* range = TestRangeBuilder(zone()).Build(0, 1);
105 ASSERT_DEATH_IF_SUPPORTED(Split(range, 2), ".*");
106}
107
108
109TEST_F(LiveRangeUnitTest, SplitSingleIntervalNoUsePositions) {
110 TopLevelLiveRange* range = TestRangeBuilder(zone()).Build(0, 2);
111 LiveRange* child = Split(range, 1);
112
113 EXPECT_NE(nullptr, range->next());
114 EXPECT_EQ(child, range->next());
115
116 LiveRange* expected_top = TestRangeBuilder(zone()).Build(0, 1);
117 LiveRange* expected_bottom = TestRangeBuilder(zone()).Build(1, 2);
118 EXPECT_TRUE(RangesMatch(expected_top, range));
119 EXPECT_TRUE(RangesMatch(expected_bottom, child));
120}
121
122
123TEST_F(LiveRangeUnitTest, SplitManyIntervalNoUsePositionsBetween) {
124 TopLevelLiveRange* range =
125 TestRangeBuilder(zone()).Add(0, 2).Add(4, 6).Build();
126 LiveRange* child = Split(range, 3);
127
128 EXPECT_NE(nullptr, range->next());
129 EXPECT_EQ(child, range->next());
130
131 LiveRange* expected_top = TestRangeBuilder(zone()).Build(0, 2);
132 LiveRange* expected_bottom = TestRangeBuilder(zone()).Build(4, 6);
133 EXPECT_TRUE(RangesMatch(expected_top, range));
134 EXPECT_TRUE(RangesMatch(expected_bottom, child));
135}
136
137
138TEST_F(LiveRangeUnitTest, SplitManyIntervalNoUsePositionsFront) {
139 TopLevelLiveRange* range =
140 TestRangeBuilder(zone()).Add(0, 2).Add(4, 6).Build();
141 LiveRange* child = Split(range, 1);
142
143 EXPECT_NE(nullptr, range->next());
144 EXPECT_EQ(child, range->next());
145
146 LiveRange* expected_top = TestRangeBuilder(zone()).Build(0, 1);
147 LiveRange* expected_bottom =
148 TestRangeBuilder(zone()).Add(1, 2).Add(4, 6).Build();
149 EXPECT_TRUE(RangesMatch(expected_top, range));
150 EXPECT_TRUE(RangesMatch(expected_bottom, child));
151}
152
153
154TEST_F(LiveRangeUnitTest, SplitManyIntervalNoUsePositionsAfter) {
155 TopLevelLiveRange* range =
156 TestRangeBuilder(zone()).Add(0, 2).Add(4, 6).Build();
157 LiveRange* child = Split(range, 5);
158
159 EXPECT_NE(nullptr, range->next());
160 EXPECT_EQ(child, range->next());
161
162 LiveRange* expected_top =
163 TestRangeBuilder(zone()).Add(0, 2).Add(4, 5).Build();
164 LiveRange* expected_bottom = TestRangeBuilder(zone()).Build(5, 6);
165 EXPECT_TRUE(RangesMatch(expected_top, range));
166 EXPECT_TRUE(RangesMatch(expected_bottom, child));
167}
168
169
170TEST_F(LiveRangeUnitTest, SplitSingleIntervalUsePositions) {
171 TopLevelLiveRange* range =
172 TestRangeBuilder(zone()).Add(0, 3).AddUse(0).AddUse(2).Build();
173
174 LiveRange* child = Split(range, 1);
175
176 EXPECT_NE(nullptr, range->next());
177 EXPECT_EQ(child, range->next());
178
179 LiveRange* expected_top =
180 TestRangeBuilder(zone()).Add(0, 1).AddUse(0).Build();
181 LiveRange* expected_bottom =
182 TestRangeBuilder(zone()).Add(1, 3).AddUse(2).Build();
183 EXPECT_TRUE(RangesMatch(expected_top, range));
184 EXPECT_TRUE(RangesMatch(expected_bottom, child));
185}
186
187
188TEST_F(LiveRangeUnitTest, SplitSingleIntervalUsePositionsAtPos) {
189 TopLevelLiveRange* range =
190 TestRangeBuilder(zone()).Add(0, 3).AddUse(0).AddUse(2).Build();
191
192 LiveRange* child = Split(range, 2);
193
194 EXPECT_NE(nullptr, range->next());
195 EXPECT_EQ(child, range->next());
196
197 LiveRange* expected_top =
198 TestRangeBuilder(zone()).Add(0, 2).AddUse(0).AddUse(2).Build();
199 LiveRange* expected_bottom = TestRangeBuilder(zone()).Build(2, 3);
200 EXPECT_TRUE(RangesMatch(expected_top, range));
201 EXPECT_TRUE(RangesMatch(expected_bottom, child));
202}
203
204
205TEST_F(LiveRangeUnitTest, SplitManyIntervalUsePositionsBetween) {
206 TopLevelLiveRange* range =
207 TestRangeBuilder(zone()).Add(0, 2).Add(4, 6).AddUse(1).AddUse(5).Build();
208 LiveRange* child = Split(range, 3);
209
210 EXPECT_NE(nullptr, range->next());
211 EXPECT_EQ(child, range->next());
212
213 LiveRange* expected_top =
214 TestRangeBuilder(zone()).Add(0, 2).AddUse(1).Build();
215 LiveRange* expected_bottom =
216 TestRangeBuilder(zone()).Add(4, 6).AddUse(5).Build();
217 EXPECT_TRUE(RangesMatch(expected_top, range));
218 EXPECT_TRUE(RangesMatch(expected_bottom, child));
219}
220
221
222TEST_F(LiveRangeUnitTest, SplitManyIntervalUsePositionsAtInterval) {
223 TopLevelLiveRange* range =
224 TestRangeBuilder(zone()).Add(0, 2).Add(4, 6).AddUse(1).AddUse(4).Build();
225 LiveRange* child = Split(range, 4);
226
227 EXPECT_NE(nullptr, range->next());
228 EXPECT_EQ(child, range->next());
229
230 LiveRange* expected_top =
231 TestRangeBuilder(zone()).Add(0, 2).AddUse(1).Build();
232 LiveRange* expected_bottom =
233 TestRangeBuilder(zone()).Add(4, 6).AddUse(4).Build();
234 EXPECT_TRUE(RangesMatch(expected_top, range));
235 EXPECT_TRUE(RangesMatch(expected_bottom, child));
236}
237
238
239TEST_F(LiveRangeUnitTest, SplitManyIntervalUsePositionsFront) {
240 TopLevelLiveRange* range =
241 TestRangeBuilder(zone()).Add(0, 2).Add(4, 6).AddUse(1).AddUse(5).Build();
242 LiveRange* child = Split(range, 1);
243
244 EXPECT_NE(nullptr, range->next());
245 EXPECT_EQ(child, range->next());
246
247 LiveRange* expected_top =
248 TestRangeBuilder(zone()).Add(0, 1).AddUse(1).Build();
249 LiveRange* expected_bottom =
250 TestRangeBuilder(zone()).Add(1, 2).Add(4, 6).AddUse(5).Build();
251 EXPECT_TRUE(RangesMatch(expected_top, range));
252 EXPECT_TRUE(RangesMatch(expected_bottom, child));
253}
254
255
256TEST_F(LiveRangeUnitTest, SplitManyIntervalUsePositionsAfter) {
257 TopLevelLiveRange* range =
258 TestRangeBuilder(zone()).Add(0, 2).Add(4, 6).AddUse(1).AddUse(5).Build();
259 LiveRange* child = Split(range, 5);
260
261 EXPECT_NE(nullptr, range->next());
262 EXPECT_EQ(child, range->next());
263
264 LiveRange* expected_top =
265 TestRangeBuilder(zone()).Add(0, 2).Add(4, 5).AddUse(1).AddUse(5).Build();
266 LiveRange* expected_bottom = TestRangeBuilder(zone()).Build(5, 6);
267 EXPECT_TRUE(RangesMatch(expected_top, range));
268 EXPECT_TRUE(RangesMatch(expected_bottom, child));
269}
270
271
272TEST_F(LiveRangeUnitTest, SplinterSingleInterval) {
273 TopLevelLiveRange* range = TestRangeBuilder(zone()).Build(0, 6);
274 TopLevelLiveRange* splinter = Splinter(range, 3, 5);
275 EXPECT_EQ(nullptr, range->next());
276 EXPECT_EQ(nullptr, splinter->next());
277 EXPECT_EQ(range, splinter->splintered_from());
278
279 TopLevelLiveRange* expected_source =
280 TestRangeBuilder(zone()).Add(0, 3).Add(5, 6).Build();
281 TopLevelLiveRange* expected_splinter = TestRangeBuilder(zone()).Build(3, 5);
282 EXPECT_TRUE(RangesMatch(expected_source, range));
283 EXPECT_TRUE(RangesMatch(expected_splinter, splinter));
284}
285
286
287TEST_F(LiveRangeUnitTest, MergeSingleInterval) {
288 TopLevelLiveRange* original = TestRangeBuilder(zone()).Build(0, 6);
289 TopLevelLiveRange* splinter = Splinter(original, 3, 5);
290
291 original->Merge(splinter, zone());
292 TopLevelLiveRange* result = TestRangeBuilder(zone()).Build(0, 6);
293 LiveRange* child_1 = Split(result, 3);
294 Split(child_1, 5);
295
296 EXPECT_TRUE(RangesMatch(result, original));
297}
298
299
300TEST_F(LiveRangeUnitTest, SplinterMultipleIntervalsOutside) {
301 TopLevelLiveRange* range =
302 TestRangeBuilder(zone()).Add(0, 3).Add(5, 8).Build();
303 TopLevelLiveRange* splinter = Splinter(range, 2, 6);
304 EXPECT_EQ(nullptr, range->next());
305 EXPECT_EQ(nullptr, splinter->next());
306 EXPECT_EQ(range, splinter->splintered_from());
307
308 TopLevelLiveRange* expected_source =
309 TestRangeBuilder(zone()).Add(0, 2).Add(6, 8).Build();
310 TopLevelLiveRange* expected_splinter =
311 TestRangeBuilder(zone()).Add(2, 3).Add(5, 6).Build();
312 EXPECT_TRUE(RangesMatch(expected_source, range));
313 EXPECT_TRUE(RangesMatch(expected_splinter, splinter));
314}
315
316
317TEST_F(LiveRangeUnitTest, MergeMultipleIntervalsOutside) {
318 TopLevelLiveRange* original =
319 TestRangeBuilder(zone()).Add(0, 3).Add(5, 8).Build();
320 TopLevelLiveRange* splinter = Splinter(original, 2, 6);
321 original->Merge(splinter, zone());
322
323 TopLevelLiveRange* result =
324 TestRangeBuilder(zone()).Add(0, 3).Add(5, 8).Build();
325 LiveRange* child_1 = Split(result, 2);
326 Split(child_1, 6);
327 EXPECT_TRUE(RangesMatch(result, original));
328}
329
330
331TEST_F(LiveRangeUnitTest, SplinterMultipleIntervalsInside) {
332 TopLevelLiveRange* range =
333 TestRangeBuilder(zone()).Add(0, 3).Add(5, 8).Build();
334 V8_ASSERT_DEBUG_DEATH(Splinter(range, 3, 5), ".*");
335}
336
337
338TEST_F(LiveRangeUnitTest, SplinterMultipleIntervalsLeft) {
339 TopLevelLiveRange* range =
340 TestRangeBuilder(zone()).Add(0, 3).Add(5, 8).Build();
341 TopLevelLiveRange* splinter = Splinter(range, 2, 4);
342 EXPECT_EQ(nullptr, range->next());
343 EXPECT_EQ(nullptr, splinter->next());
344 EXPECT_EQ(range, splinter->splintered_from());
345
346 TopLevelLiveRange* expected_source =
347 TestRangeBuilder(zone()).Add(0, 2).Add(5, 8).Build();
348 TopLevelLiveRange* expected_splinter = TestRangeBuilder(zone()).Build(2, 3);
349 EXPECT_TRUE(RangesMatch(expected_source, range));
350 EXPECT_TRUE(RangesMatch(expected_splinter, splinter));
351}
352
353
354TEST_F(LiveRangeUnitTest, MergeMultipleIntervalsLeft) {
355 TopLevelLiveRange* original =
356 TestRangeBuilder(zone()).Add(0, 3).Add(5, 8).Build();
357 TopLevelLiveRange* splinter = Splinter(original, 2, 4);
358 original->Merge(splinter, zone());
359
360 TopLevelLiveRange* result =
361 TestRangeBuilder(zone()).Add(0, 3).Add(5, 8).Build();
362 Split(result, 2);
363 EXPECT_TRUE(RangesMatch(result, original));
364}
365
366
367TEST_F(LiveRangeUnitTest, SplinterMultipleIntervalsRight) {
368 TopLevelLiveRange* range =
369 TestRangeBuilder(zone()).Add(0, 3).Add(5, 8).Build();
370 TopLevelLiveRange* splinter = Splinter(range, 4, 6);
371 EXPECT_EQ(nullptr, range->next());
372 EXPECT_EQ(nullptr, splinter->next());
373 EXPECT_EQ(range, splinter->splintered_from());
374
375 TopLevelLiveRange* expected_source =
376 TestRangeBuilder(zone()).Add(0, 3).Add(6, 8).Build();
377 TopLevelLiveRange* expected_splinter = TestRangeBuilder(zone()).Build(5, 6);
378 EXPECT_TRUE(RangesMatch(expected_source, range));
379 EXPECT_TRUE(RangesMatch(expected_splinter, splinter));
380}
381
382
383TEST_F(LiveRangeUnitTest, SplinterMergeMultipleTimes) {
384 TopLevelLiveRange* range =
385 TestRangeBuilder(zone()).Add(0, 3).Add(5, 10).Add(12, 16).Build();
386 Splinter(range, 4, 6);
387 Splinter(range, 8, 14);
388 TopLevelLiveRange* splinter = range->splinter();
389 EXPECT_EQ(nullptr, range->next());
390 EXPECT_EQ(nullptr, splinter->next());
391 EXPECT_EQ(range, splinter->splintered_from());
392
393 TopLevelLiveRange* expected_source =
394 TestRangeBuilder(zone()).Add(0, 3).Add(6, 8).Add(14, 16).Build();
395 TopLevelLiveRange* expected_splinter =
396 TestRangeBuilder(zone()).Add(5, 6).Add(8, 10).Add(12, 14).Build();
397 EXPECT_TRUE(RangesMatch(expected_source, range));
398 EXPECT_TRUE(RangesMatch(expected_splinter, splinter));
399}
400
401
402TEST_F(LiveRangeUnitTest, MergeMultipleIntervalsRight) {
403 TopLevelLiveRange* original =
404 TestRangeBuilder(zone()).Add(0, 3).Add(5, 8).Build();
405 TopLevelLiveRange* splinter = Splinter(original, 4, 6);
406 original->Merge(splinter, zone());
407
408 TopLevelLiveRange* result =
409 TestRangeBuilder(zone()).Add(0, 3).Add(5, 8).Build();
410 LiveRange* child_1 = Split(result, 5);
411 Split(child_1, 6);
412
413 EXPECT_TRUE(RangesMatch(result, original));
414}
415
416
417TEST_F(LiveRangeUnitTest, MergeAfterSplitting) {
418 TopLevelLiveRange* original = TestRangeBuilder(zone()).Build(0, 8);
419 TopLevelLiveRange* splinter = Splinter(original, 4, 6);
420 LiveRange* original_child = Split(original, 2);
421 Split(original_child, 7);
422 original->Merge(splinter, zone());
423
424 TopLevelLiveRange* result = TestRangeBuilder(zone()).Build(0, 8);
425 LiveRange* child_1 = Split(result, 2);
426 LiveRange* child_2 = Split(child_1, 4);
427 LiveRange* child_3 = Split(child_2, 6);
428 Split(child_3, 7);
429
430 EXPECT_TRUE(RangesMatch(result, original));
431}
432
433
434TEST_F(LiveRangeUnitTest, IDGeneration) {
435 TopLevelLiveRange* vreg = TestRangeBuilder(zone()).Id(2).Build(0, 100);
436 EXPECT_EQ(2, vreg->vreg());
437 EXPECT_EQ(0, vreg->relative_id());
438
439 TopLevelLiveRange* splinter =
440 new (zone()) TopLevelLiveRange(101, MachineRepresentation::kTagged);
441 vreg->SetSplinter(splinter);
442 vreg->Splinter(LifetimePosition::FromInt(4), LifetimePosition::FromInt(12),
443 zone());
444
445 EXPECT_EQ(101, splinter->vreg());
446 EXPECT_EQ(1, splinter->relative_id());
447
448 LiveRange* child = vreg->SplitAt(LifetimePosition::FromInt(50), zone());
449
450 EXPECT_EQ(2, child->relative_id());
451
452 LiveRange* splinter_child =
453 splinter->SplitAt(LifetimePosition::FromInt(8), zone());
454
455 EXPECT_EQ(1, splinter->relative_id());
456 EXPECT_EQ(3, splinter_child->relative_id());
457
458 vreg->Merge(splinter, zone());
459 EXPECT_EQ(1, splinter->relative_id());
460}
461
462} // namespace compiler
463} // namespace internal
464} // namespace v8