Chromium Code Reviews| 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 |