LLVM 21.0.0git
Interval.h
Go to the documentation of this file.
1//===- Interval.h -----------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// The Interval class is a generic interval of ordered objects that implement:
10// - T * T::getPrevNode()
11// - T * T::getNextNode()
12// - bool T::comesBefore(const T *) const
13//
14// This is currently used for Instruction intervals.
15// It provides an API for some basic operations on the interval, including some
16// simple set operations, like union, intersection and others.
17//
18//===----------------------------------------------------------------------===//
19
20#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_INSTRINTERVAL_H
21#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_INSTRINTERVAL_H
22
23#include "llvm/ADT/ArrayRef.h"
26#include <iterator>
27#include <type_traits>
28
29namespace llvm::sandboxir {
30
31/// A simple iterator for iterating the interval.
32template <typename T, typename IntervalType> class IntervalIterator {
33 T *I;
34 IntervalType &R;
35
36public:
37 using difference_type = std::ptrdiff_t;
38 using value_type = T;
40 using reference = T &;
41 using iterator_category = std::bidirectional_iterator_tag;
42
43 IntervalIterator(T *I, IntervalType &R) : I(I), R(R) {}
44 bool operator==(const IntervalIterator &Other) const {
45 assert(&R == &Other.R && "Iterators belong to different regions!");
46 return Other.I == I;
47 }
48 bool operator!=(const IntervalIterator &Other) const {
49 return !(*this == Other);
50 }
52 assert(I != nullptr && "already at end()!");
53 I = I->getNextNode();
54 return *this;
55 }
57 auto ItCopy = *this;
58 ++*this;
59 return ItCopy;
60 }
62 // `I` is nullptr for end() when To is the BB terminator.
63 I = I != nullptr ? I->getPrevNode() : R.bottom();
64 return *this;
65 }
67 auto ItCopy = *this;
68 --*this;
69 return ItCopy;
70 }
71 template <typename HT = std::enable_if<std::is_same<T, T *&>::value>>
73 return *I;
74 }
75 T &operator*() const { return *I; }
76};
77
78template <typename T> class Interval {
79 T *Top;
80 T *Bottom;
81
82public:
83 Interval() : Top(nullptr), Bottom(nullptr) {}
84 Interval(T *Top, T *Bottom) : Top(Top), Bottom(Bottom) {
85 assert((Top == Bottom || Top->comesBefore(Bottom)) &&
86 "Top should come before Bottom!");
87 }
89 assert(!Elems.empty() && "Expected non-empty Elems!");
90 Top = Elems[0];
91 Bottom = Elems[0];
92 for (auto *I : drop_begin(Elems)) {
93 if (I->comesBefore(Top))
94 Top = I;
95 else if (Bottom->comesBefore(I))
96 Bottom = I;
97 }
98 }
99 bool empty() const {
100 assert(((Top == nullptr && Bottom == nullptr) ||
101 (Top != nullptr && Bottom != nullptr)) &&
102 "Either none or both should be null");
103 return Top == nullptr;
104 }
105 bool contains(T *I) const {
106 if (empty())
107 return false;
108 return (Top == I || Top->comesBefore(I)) &&
109 (I == Bottom || I->comesBefore(Bottom));
110 }
111 /// \Returns true if \p Elm is right before the top or right after the bottom.
112 bool touches(T *Elm) const {
113 return Top == Elm->getNextNode() || Bottom == Elm->getPrevNode();
114 }
115 T *top() const { return Top; }
116 T *bottom() const { return Bottom; }
117
119 iterator begin() { return iterator(Top, *this); }
121 return iterator(Bottom != nullptr ? Bottom->getNextNode() : nullptr, *this);
122 }
123 iterator begin() const {
124 return iterator(Top, const_cast<Interval &>(*this));
125 }
126 iterator end() const {
127 return iterator(Bottom != nullptr ? Bottom->getNextNode() : nullptr,
128 const_cast<Interval &>(*this));
129 }
130 /// Equality.
131 bool operator==(const Interval &Other) const {
132 return Top == Other.Top && Bottom == Other.Bottom;
133 }
134 /// Inequality.
135 bool operator!=(const Interval &Other) const { return !(*this == Other); }
136 /// \Returns true if this interval comes before \p Other in program order.
137 /// This expects disjoint intervals.
138 bool comesBefore(const Interval &Other) const {
139 assert(disjoint(Other) && "Expect disjoint intervals!");
140 return bottom()->comesBefore(Other.top());
141 }
142 /// \Returns true if this and \p Other have nothing in common.
143 bool disjoint(const Interval &Other) const;
144 /// \Returns the intersection between this and \p Other.
145 // Example:
146 // |----| this
147 // |---| Other
148 // |-| this->getIntersection(Other)
150 if (empty())
151 return *this;
152 if (Other.empty())
153 return Interval();
154 // 1. No overlap
155 // A---B this
156 // C--D Other
157 if (Bottom->comesBefore(Other.Top) || Other.Bottom->comesBefore(Top))
158 return Interval();
159 // 2. Overlap.
160 // A---B this
161 // C--D Other
162 auto NewTopI = Top->comesBefore(Other.Top) ? Other.Top : Top;
163 auto NewBottomI = Bottom->comesBefore(Other.Bottom) ? Bottom : Other.Bottom;
164 return Interval(NewTopI, NewBottomI);
165 }
166 /// Difference operation. This returns up to two intervals.
167 // Example:
168 // |--------| this
169 // |-| Other
170 // |-| |--| this - Other
172 if (disjoint(Other))
173 return {*this};
174 if (Other.empty())
175 return {*this};
176 if (*this == Other)
177 return {Interval()};
178 Interval Intersection = intersection(Other);
180 // Part 1, skip if empty.
181 if (Top != Intersection.Top)
182 Result.emplace_back(Top, Intersection.Top->getPrevNode());
183 // Part 2, skip if empty.
184 if (Intersection.Bottom != Bottom)
185 Result.emplace_back(Intersection.Bottom->getNextNode(), Bottom);
186 return Result;
187 }
188 /// \Returns the interval difference `this - Other`. This will crash in Debug
189 /// if the result is not a single interval.
191 auto Diff = *this - Other;
192 assert(Diff.size() == 1 && "Expected a single interval!");
193 return Diff[0];
194 }
195 /// \Returns a single interval that spans across both this and \p Other.
196 // For example:
197 // |---| this
198 // |---| Other
199 // |----------| this->getUnionInterval(Other)
201 if (empty())
202 return Other;
203 if (Other.empty())
204 return *this;
205 auto *NewTop = Top->comesBefore(Other.Top) ? Top : Other.Top;
206 auto *NewBottom = Bottom->comesBefore(Other.Bottom) ? Other.Bottom : Bottom;
207 return {NewTop, NewBottom};
208 }
209
210 /// Update the interval when \p I is about to be moved before \p Before.
211 // SFINAE disables this for non-Instructions.
212 template <typename HelperT = T>
213 std::enable_if_t<std::is_same<HelperT, Instruction>::value, void>
214 notifyMoveInstr(HelperT *I, decltype(I->getIterator()) BeforeIt) {
215 assert(contains(I) && "Expect `I` in interval!");
216 assert(I->getIterator() != BeforeIt && "Can't move `I` before itself!");
217
218 // Nothing to do if the instruction won't move.
219 if (std::next(I->getIterator()) == BeforeIt)
220 return;
221
222 T *NewTop = Top->getIterator() == BeforeIt ? I
223 : I == Top ? Top->getNextNode()
224 : Top;
225 T *NewBottom = std::next(Bottom->getIterator()) == BeforeIt ? I
226 : I == Bottom ? Bottom->getPrevNode()
227 : Bottom;
228 Top = NewTop;
229 Bottom = NewBottom;
230 }
231
232#ifndef NDEBUG
233 void print(raw_ostream &OS) const;
234 LLVM_DUMP_METHOD void dump() const;
235#endif
236};
237
238} // namespace llvm::sandboxir
239
240#endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_INSTRINTERVAL_H
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:622
#define I(x, y, z)
Definition: MD5.cpp:58
#define T
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:163
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
A simple iterator for iterating the interval.
Definition: Interval.h:32
bool operator!=(const IntervalIterator &Other) const
Definition: Interval.h:48
IntervalIterator & operator--()
Definition: Interval.h:61
IntervalIterator(T *I, IntervalType &R)
Definition: Interval.h:43
std::bidirectional_iterator_tag iterator_category
Definition: Interval.h:41
bool operator==(const IntervalIterator &Other) const
Definition: Interval.h:44
IntervalIterator operator++(int)
Definition: Interval.h:56
std::ptrdiff_t difference_type
Definition: Interval.h:37
IntervalIterator & operator++()
Definition: Interval.h:51
IntervalIterator operator--(int)
Definition: Interval.h:66
Interval(T *Top, T *Bottom)
Definition: Interval.h:84
SmallVector< Interval, 2 > operator-(const Interval &Other)
Difference operation. This returns up to two intervals.
Definition: Interval.h:171
bool operator==(const Interval &Other) const
Equality.
Definition: Interval.h:131
bool touches(T *Elm) const
\Returns true if Elm is right before the top or right after the bottom.
Definition: Interval.h:112
Interval getUnionInterval(const Interval &Other)
\Returns a single interval that spans across both this and Other.
Definition: Interval.h:200
LLVM_DUMP_METHOD void dump() const
Definition: Interval.cpp:42
bool contains(T *I) const
Definition: Interval.h:105
Interval getSingleDiff(const Interval &Other)
\Returns the interval difference this - Other.
Definition: Interval.h:190
bool operator!=(const Interval &Other) const
Inequality.
Definition: Interval.h:135
Interval(ArrayRef< T * > Elems)
Definition: Interval.h:88
IntervalIterator< T, Interval > iterator
Definition: Interval.h:118
iterator end() const
Definition: Interval.h:126
bool empty() const
Definition: Interval.h:99
bool disjoint(const Interval &Other) const
\Returns true if this and Other have nothing in common.
Definition: Interval.cpp:16
bool comesBefore(const Interval &Other) const
\Returns true if this interval comes before Other in program order.
Definition: Interval.h:138
void print(raw_ostream &OS) const
Definition: Interval.cpp:25
iterator begin() const
Definition: Interval.h:123
Interval intersection(const Interval &Other) const
\Returns the intersection between this and Other.
Definition: Interval.h:149
std::enable_if_t< std::is_same< HelperT, Instruction >::value, void > notifyMoveInstr(HelperT *I, decltype(I->getIterator()) BeforeIt)
Update the interval when I is about to be moved before Before.
Definition: Interval.h:214
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition: STLExtras.h:329
@ Other
Any other memory.