File indexing completed on 2026-05-10 08:43:07
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef LLVM_ADT_INTERVALTREE_H
0017 #define LLVM_ADT_INTERVALTREE_H
0018
0019 #include "llvm/ADT/SmallVector.h"
0020 #include "llvm/Support/Allocator.h"
0021 #include "llvm/Support/Format.h"
0022 #include "llvm/Support/raw_ostream.h"
0023 #include <algorithm>
0024 #include <cassert>
0025 #include <iterator>
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189 namespace llvm {
0190
0191
0192
0193
0194
0195
0196
0197
0198 template <typename PointT, typename ValueT> class IntervalData {
0199 protected:
0200 using PointType = PointT;
0201 using ValueType = ValueT;
0202
0203 private:
0204 PointType Left;
0205 PointType Right;
0206 ValueType Value;
0207
0208 public:
0209 IntervalData() = delete;
0210 IntervalData(PointType Left, PointType Right, ValueType Value)
0211 : Left(Left), Right(Right), Value(Value) {
0212 assert(Left <= Right && "'Left' must be less or equal to 'Right'");
0213 }
0214 virtual ~IntervalData() = default;
0215 PointType left() const { return Left; }
0216 PointType right() const { return Right; }
0217 ValueType value() const { return Value; }
0218
0219
0220
0221 bool left(const PointType &Point) const { return left() <= Point; }
0222
0223
0224
0225 bool right(const PointType &Point) const { return Point <= right(); }
0226
0227
0228
0229 bool contains(const PointType &Point) const {
0230 return left(Point) && right(Point);
0231 }
0232 };
0233
0234
0235
0236
0237
0238
0239 template <typename T>
0240 using PointTypeIsValid = std::bool_constant<std::is_fundamental<T>::value>;
0241
0242 template <typename T>
0243 using ValueTypeIsValid = std::bool_constant<std::is_fundamental<T>::value ||
0244 std::is_pointer<T>::value>;
0245
0246 template <typename PointT, typename ValueT,
0247 typename DataT = IntervalData<PointT, ValueT>>
0248 class IntervalTree {
0249 static_assert(PointTypeIsValid<PointT>::value,
0250 "PointT must be a fundamental type");
0251 static_assert(ValueTypeIsValid<ValueT>::value,
0252 "ValueT must be a fundamental or pointer type");
0253
0254 public:
0255 using PointType = PointT;
0256 using ValueType = ValueT;
0257 using DataType = DataT;
0258 using Allocator = BumpPtrAllocator;
0259
0260 enum class Sorting { Ascending, Descending };
0261 using IntervalReferences = SmallVector<const DataType *, 4>;
0262
0263 private:
0264 using IntervalVector = SmallVector<DataType, 4>;
0265 using PointsVector = SmallVector<PointType, 4>;
0266
0267 class IntervalNode {
0268 PointType MiddlePoint;
0269 IntervalNode *Left = nullptr;
0270 IntervalNode *Right = nullptr;
0271 unsigned BucketIntervalsStart = 0;
0272 unsigned BucketIntervalsSize = 0;
0273
0274 public:
0275 PointType middle() const { return MiddlePoint; }
0276 unsigned start() const { return BucketIntervalsStart; }
0277 unsigned size() const { return BucketIntervalsSize; }
0278
0279 IntervalNode(PointType Point, unsigned Start)
0280 : MiddlePoint(Point), BucketIntervalsStart(Start) {}
0281
0282 friend IntervalTree;
0283 };
0284
0285 Allocator &NodeAllocator;
0286 IntervalNode *Root = nullptr;
0287 IntervalVector Intervals;
0288
0289 PointsVector EndPoints;
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299 IntervalReferences IntervalsLeft;
0300 IntervalReferences IntervalsRight;
0301
0302
0303
0304 IntervalReferences References;
0305
0306
0307 void deleteTree(IntervalNode *Node) {
0308 if (Node) {
0309 deleteTree(Node->Left);
0310 deleteTree(Node->Right);
0311 Node->~IntervalNode();
0312 NodeAllocator.Deallocate(Node);
0313 }
0314 }
0315
0316
0317 static void printList(raw_ostream &OS, IntervalReferences &IntervalSet,
0318 unsigned Start, unsigned Size, bool HexFormat = true) {
0319 assert(Start + Size <= IntervalSet.size() &&
0320 "Start + Size must be in bounds of the IntervalSet");
0321 const char *Format = HexFormat ? "[0x%08x,0x%08x] " : "[%2d,%2d] ";
0322 if (Size) {
0323 for (unsigned Position = Start; Position < Start + Size; ++Position)
0324 OS << format(Format, IntervalSet[Position]->left(),
0325 IntervalSet[Position]->right());
0326 } else {
0327 OS << "[]";
0328 }
0329 OS << "\n";
0330 }
0331
0332
0333 void printNode(raw_ostream &OS, unsigned Level, IntervalNode *Node,
0334 bool HexFormat = true) {
0335 const char *Format = HexFormat ? "MP:0x%08x " : "MP:%2d ";
0336 auto PrintNodeData = [&](StringRef Text, IntervalReferences &IntervalSet) {
0337 OS << format("%5d: ", Level);
0338 OS.indent(Level * 2);
0339 OS << format(Format, Node->middle()) << Text << " ";
0340 printList(OS, IntervalSet, Node->start(), Node->size(), HexFormat);
0341 };
0342
0343 PrintNodeData("IR", IntervalsRight);
0344 PrintNodeData("IL", IntervalsLeft);
0345 }
0346
0347
0348 void printTree(raw_ostream &OS, unsigned Level, IntervalNode *Node,
0349 bool HexFormat = true) {
0350 if (Node) {
0351 printNode(OS, Level, Node, HexFormat);
0352 ++Level;
0353 printTree(OS, Level, Node->Left, HexFormat);
0354 printTree(OS, Level, Node->Right, HexFormat);
0355 }
0356 }
0357
0358
0359
0360
0361
0362
0363
0364
0365 IntervalNode *createTree(unsigned &IntervalsSize, int PointsBeginIndex,
0366 int PointsEndIndex, int ReferencesBeginIndex,
0367 int ReferencesSize) {
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378 if (PointsBeginIndex > PointsEndIndex ||
0379 ReferencesBeginIndex >= ReferencesSize)
0380 return nullptr;
0381
0382 int MiddleIndex = (PointsBeginIndex + PointsEndIndex) / 2;
0383 PointType MiddlePoint = EndPoints[MiddleIndex];
0384
0385 unsigned NewBucketStart = IntervalsSize;
0386 unsigned NewBucketSize = 0;
0387 int ReferencesRightIndex = ReferencesSize;
0388
0389 IntervalNode *Root =
0390 new (NodeAllocator) IntervalNode(MiddlePoint, NewBucketStart);
0391
0392
0393
0394
0395 for (int Index = ReferencesBeginIndex; Index < ReferencesRightIndex;) {
0396
0397
0398 if (References[Index]->contains(MiddlePoint)) {
0399 IntervalsLeft[IntervalsSize] = References[Index];
0400 IntervalsRight[IntervalsSize] = References[Index];
0401 ++IntervalsSize;
0402 Root->BucketIntervalsSize = ++NewBucketSize;
0403
0404 if (Index < --ReferencesRightIndex)
0405 std::swap(References[Index], References[ReferencesRightIndex]);
0406 if (ReferencesRightIndex < --ReferencesSize)
0407 std::swap(References[ReferencesRightIndex],
0408 References[ReferencesSize]);
0409 continue;
0410 }
0411
0412 if (References[Index]->left() > MiddlePoint) {
0413 if (Index < --ReferencesRightIndex)
0414 std::swap(References[Index], References[ReferencesRightIndex]);
0415 continue;
0416 }
0417 ++Index;
0418 }
0419
0420
0421 if (NewBucketSize > 1) {
0422
0423 std::stable_sort(IntervalsLeft.begin() + NewBucketStart,
0424 IntervalsLeft.begin() + NewBucketStart + NewBucketSize,
0425 [](const DataType *LHS, const DataType *RHS) {
0426 return LHS->left() < RHS->left();
0427 });
0428
0429 std::stable_sort(IntervalsRight.begin() + NewBucketStart,
0430 IntervalsRight.begin() + NewBucketStart + NewBucketSize,
0431 [](const DataType *LHS, const DataType *RHS) {
0432 return LHS->right() > RHS->right();
0433 });
0434 }
0435
0436 if (PointsBeginIndex <= MiddleIndex - 1) {
0437 Root->Left = createTree(IntervalsSize, PointsBeginIndex, MiddleIndex - 1,
0438 ReferencesBeginIndex, ReferencesRightIndex);
0439 }
0440
0441 if (MiddleIndex + 1 <= PointsEndIndex) {
0442 Root->Right = createTree(IntervalsSize, MiddleIndex + 1, PointsEndIndex,
0443 ReferencesRightIndex, ReferencesSize);
0444 }
0445
0446 return Root;
0447 }
0448
0449 public:
0450 class find_iterator {
0451 public:
0452 using iterator_category = std::forward_iterator_tag;
0453 using value_type = DataType;
0454 using difference_type = DataType;
0455 using pointer = DataType *;
0456 using reference = DataType &;
0457
0458 private:
0459 const IntervalReferences *AscendingBuckets = nullptr;
0460 const IntervalReferences *DescendingBuckets = nullptr;
0461
0462
0463
0464 IntervalNode *Node = nullptr;
0465 PointType Point = {};
0466 unsigned Index = 0;
0467
0468
0469
0470
0471 void initNode() {
0472 Index = 0;
0473 while (Node) {
0474
0475
0476 if (Point == Node->middle()) {
0477 if (Node->size() == 0) {
0478
0479 Node = nullptr;
0480 }
0481 return;
0482 }
0483
0484 if (Point < Node->middle()) {
0485
0486
0487
0488 if (Node->size() && (*AscendingBuckets)[Node->start()]->left(Point)) {
0489 return;
0490 }
0491 Node = Node->Left;
0492 } else {
0493 if (Node->size() &&
0494 (*DescendingBuckets)[Node->start()]->right(Point)) {
0495 return;
0496 }
0497 Node = Node->Right;
0498 }
0499 }
0500 }
0501
0502
0503
0504
0505
0506 void nextInterval() {
0507
0508
0509
0510 if (++Index < Node->size()) {
0511 if (Node->middle() == Point)
0512 return;
0513 if (Point < Node->middle()) {
0514
0515 if (!(*AscendingBuckets)[Node->start() + Index]->left(Point)) {
0516
0517
0518 Node = Node->Left;
0519 initNode();
0520 }
0521 } else {
0522
0523 if (!(*DescendingBuckets)[Node->start() + Index]->right(Point)) {
0524
0525
0526 Node = Node->Right;
0527 initNode();
0528 }
0529 }
0530 } else {
0531
0532 if (Point == Node->middle()) {
0533 Node = nullptr;
0534 Index = 0;
0535 return;
0536 }
0537
0538 Node = Point < Node->middle() ? Node->Left : Node->Right;
0539 initNode();
0540 }
0541 }
0542
0543 find_iterator() = default;
0544 explicit find_iterator(const IntervalReferences *Left,
0545 const IntervalReferences *Right, IntervalNode *Node,
0546 PointType Point)
0547 : AscendingBuckets(Left), DescendingBuckets(Right), Node(Node),
0548 Point(Point), Index(0) {
0549 initNode();
0550 }
0551
0552 const DataType *current() const {
0553 return (Point <= Node->middle())
0554 ? (*AscendingBuckets)[Node->start() + Index]
0555 : (*DescendingBuckets)[Node->start() + Index];
0556 }
0557
0558 public:
0559 find_iterator &operator++() {
0560 nextInterval();
0561 return *this;
0562 }
0563
0564 find_iterator operator++(int) {
0565 find_iterator Iter(*this);
0566 nextInterval();
0567 return Iter;
0568 }
0569
0570
0571 const DataType *operator->() const { return current(); }
0572 const DataType &operator*() const { return *(current()); }
0573
0574
0575 friend bool operator==(const find_iterator &LHS, const find_iterator &RHS) {
0576 return (!LHS.Node && !RHS.Node && !LHS.Index && !RHS.Index) ||
0577 (LHS.Point == RHS.Point && LHS.Node == RHS.Node &&
0578 LHS.Index == RHS.Index);
0579 }
0580 friend bool operator!=(const find_iterator &LHS, const find_iterator &RHS) {
0581 return !(LHS == RHS);
0582 }
0583
0584 friend IntervalTree;
0585 };
0586
0587 private:
0588 find_iterator End;
0589
0590 public:
0591 explicit IntervalTree(Allocator &NodeAllocator)
0592 : NodeAllocator(NodeAllocator) {}
0593 ~IntervalTree() { clear(); }
0594
0595
0596 bool empty() const { return Root == nullptr; }
0597
0598
0599 void clear() {
0600 deleteTree(Root);
0601 Root = nullptr;
0602 Intervals.clear();
0603 IntervalsLeft.clear();
0604 IntervalsRight.clear();
0605 EndPoints.clear();
0606 }
0607
0608
0609 void insert(PointType Left, PointType Right, ValueType Value) {
0610 assert(empty() && "Invalid insertion. Interval tree already constructed.");
0611 Intervals.emplace_back(Left, Right, Value);
0612 }
0613
0614
0615
0616 IntervalReferences getContaining(PointType Point) const {
0617 assert(!empty() && "Interval tree it is not constructed.");
0618 IntervalReferences IntervalSet;
0619 for (find_iterator Iter = find(Point), E = find_end(); Iter != E; ++Iter)
0620 IntervalSet.push_back(const_cast<DataType *>(&(*Iter)));
0621 return IntervalSet;
0622 }
0623
0624
0625
0626
0627 static void sortIntervals(IntervalReferences &IntervalSet, Sorting Sort) {
0628 std::stable_sort(IntervalSet.begin(), IntervalSet.end(),
0629 [Sort](const DataType *RHS, const DataType *LHS) {
0630 return Sort == Sorting::Ascending
0631 ? (LHS->right() - LHS->left()) >
0632 (RHS->right() - RHS->left())
0633 : (LHS->right() - LHS->left()) <
0634 (RHS->right() - RHS->left());
0635 });
0636 }
0637
0638
0639
0640
0641 void print(raw_ostream &OS, bool HexFormat = true) {
0642 printTree(OS, 0, Root, HexFormat);
0643 }
0644
0645
0646 void create() {
0647 assert(empty() && "Interval tree already constructed.");
0648
0649
0650 SmallVector<PointType, 4> Points;
0651 for (const DataType &Data : Intervals) {
0652 Points.push_back(Data.left());
0653 Points.push_back(Data.right());
0654 References.push_back(std::addressof(Data));
0655 }
0656 std::stable_sort(Points.begin(), Points.end());
0657 auto Last = llvm::unique(Points);
0658 Points.erase(Last, Points.end());
0659
0660 EndPoints.assign(Points.begin(), Points.end());
0661
0662 IntervalsLeft.resize(Intervals.size());
0663 IntervalsRight.resize(Intervals.size());
0664
0665
0666
0667
0668 unsigned IntervalsSize = 0;
0669 Root =
0670 createTree(IntervalsSize, 0, EndPoints.size() - 1,
0671 0, References.size());
0672
0673
0674 References.clear();
0675 }
0676
0677
0678
0679
0680 find_iterator find(PointType Point) const {
0681 return empty()
0682 ? find_end()
0683 : find_iterator(&IntervalsLeft, &IntervalsRight, Root, Point);
0684 }
0685
0686
0687 find_iterator find_end() const { return End; }
0688 };
0689
0690 }
0691
0692 #endif