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 Interval 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 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.RemoveCurrentAndGetNext()) { |
| 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().VerifyAllocationsAreValidForTesting(); |
| 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 |