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