-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[SandboxVec][Interval] Convert InstrInterval class to a class template #110021
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-llvm-transforms Author: vporpo (vporpo) ChangesThis patch converts InstrInterval class to a class template and renames InstrInterval to Itnerval. This change will allow us to reuse the Interval for dependency graph nodes. Full diff: https://github.com/llvm/llvm-project/pull/110021.diff 6 Files Affected:
diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.h
index 0120d9cf51fe9f..5437853c366ae6 100644
--- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.h
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.h
@@ -25,7 +25,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/SandboxIR/SandboxIR.h"
-#include "llvm/Transforms/Vectorize/SandboxVectorizer/InstrInterval.h"
+#include "llvm/Transforms/Vectorize/SandboxVectorizer/Interval.h"
namespace llvm::sandboxir {
@@ -85,7 +85,7 @@ class DependencyGraph {
}
/// Build/extend the dependency graph such that it includes \p Instrs. Returns
/// the interval spanning \p Instrs.
- InstrInterval extend(ArrayRef<Instruction *> Instrs);
+ Interval<Instruction> extend(ArrayRef<Instruction *> Instrs);
#ifndef NDEBUG
void print(raw_ostream &OS) const;
LLVM_DUMP_METHOD void dump() const;
diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/InstrInterval.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/InstrInterval.h
deleted file mode 100644
index 1343f521b29bb4..00000000000000
--- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/InstrInterval.h
+++ /dev/null
@@ -1,124 +0,0 @@
-//===- InstrInterval.h ------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// The InstrInterval class is an interval of instructions in a block.
-// It provides an API for some basic operations on the interval, including some
-// simple set operations, like union, interseciton and others.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_INSTRINTERVAL_H
-#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_INSTRINTERVAL_H
-
-#include "llvm/SandboxIR/SandboxIR.h"
-#include <iterator>
-
-namespace llvm::sandboxir {
-
-/// A simple iterator for iterating the interval.
-template <typename DerefType, typename InstrIntervalType>
-class InstrIntervalIterator {
- sandboxir::Instruction *I;
- InstrIntervalType &R;
-
-public:
- using difference_type = std::ptrdiff_t;
- using value_type = sandboxir::Instruction;
- using pointer = value_type *;
- using reference = sandboxir::Instruction &;
- using iterator_category = std::bidirectional_iterator_tag;
-
- InstrIntervalIterator(sandboxir::Instruction *I, InstrIntervalType &R)
- : I(I), R(R) {}
- bool operator==(const InstrIntervalIterator &Other) const {
- assert(&R == &Other.R && "Iterators belong to different regions!");
- return Other.I == I;
- }
- bool operator!=(const InstrIntervalIterator &Other) const {
- return !(*this == Other);
- }
- InstrIntervalIterator &operator++() {
- assert(I != nullptr && "already at end()!");
- I = I->getNextNode();
- return *this;
- }
- InstrIntervalIterator operator++(int) {
- auto ItCopy = *this;
- ++*this;
- return ItCopy;
- }
- InstrIntervalIterator &operator--() {
- // `I` is nullptr for end() when ToI is the BB terminator.
- I = I != nullptr ? I->getPrevNode() : R.ToI;
- return *this;
- }
- InstrIntervalIterator operator--(int) {
- auto ItCopy = *this;
- --*this;
- return ItCopy;
- }
- template <typename T =
- std::enable_if<std::is_same<DerefType, Instruction *&>::value>>
- sandboxir::Instruction &operator*() {
- return *I;
- }
- DerefType operator*() const { return *I; }
-};
-
-class InstrInterval {
- Instruction *FromI;
- Instruction *ToI;
-
-public:
- InstrInterval() : FromI(nullptr), ToI(nullptr) {}
- InstrInterval(Instruction *FromI, Instruction *ToI) : FromI(FromI), ToI(ToI) {
- assert((FromI == ToI || FromI->comesBefore(ToI)) &&
- "FromI should come before TopI!");
- }
- InstrInterval(ArrayRef<Instruction *> Instrs) {
- assert(!Instrs.empty() && "Expected non-empty Instrs!");
- FromI = Instrs[0];
- ToI = Instrs[0];
- for (auto *I : drop_begin(Instrs)) {
- if (I->comesBefore(FromI))
- FromI = I;
- else if (ToI->comesBefore(I))
- ToI = I;
- }
- }
- bool empty() const {
- assert(((FromI == nullptr && ToI == nullptr) ||
- (FromI != nullptr && ToI != nullptr)) &&
- "Either none or both should be null");
- return FromI == nullptr;
- }
- bool contains(Instruction *I) const {
- if (empty())
- return false;
- return (FromI == I || FromI->comesBefore(I)) &&
- (I == ToI || I->comesBefore(ToI));
- }
- Instruction *top() const { return FromI; }
- Instruction *bottom() const { return ToI; }
-
- using iterator =
- InstrIntervalIterator<sandboxir::Instruction &, InstrInterval>;
- using const_iterator = InstrIntervalIterator<const sandboxir::Instruction &,
- const InstrInterval>;
- iterator begin() { return iterator(FromI, *this); }
- iterator end() {
- return iterator(ToI != nullptr ? ToI->getNextNode() : nullptr, *this);
- }
- const_iterator begin() const { return const_iterator(FromI, *this); }
- const_iterator end() const {
- return const_iterator(ToI != nullptr ? ToI->getNextNode() : nullptr, *this);
- }
-};
-} // namespace llvm::sandboxir
-
-#endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_INSTRINTERVAL_H
diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Interval.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Interval.h
new file mode 100644
index 00000000000000..a6ddc0dd5b1a4d
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Interval.h
@@ -0,0 +1,125 @@
+//===- Interval.h -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// The Interval class is a generic interval of ordered objects that implement:
+// - T * T::getPrevNode()
+// - T * T::getNextNode()
+// - bool T::comesBefore(const T *) const
+//
+// This is currently used for Instruction intervals.
+// It provides an API for some basic operations on the interval, including some
+// simple set operations, like union, interseciton and others.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_INSTRINTERVAL_H
+#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_INSTRINTERVAL_H
+
+#include "llvm/SandboxIR/SandboxIR.h"
+#include <iterator>
+
+namespace llvm::sandboxir {
+
+/// A simple iterator for iterating the interval.
+template <typename T, typename IntervalType> class IntervalIterator {
+ T *I;
+ IntervalType &R;
+
+public:
+ using difference_type = std::ptrdiff_t;
+ using value_type = T;
+ using pointer = value_type *;
+ using reference = T &;
+ using iterator_category = std::bidirectional_iterator_tag;
+
+ IntervalIterator(T *I, IntervalType &R) : I(I), R(R) {}
+ bool operator==(const IntervalIterator &Other) const {
+ assert(&R == &Other.R && "Iterators belong to different regions!");
+ return Other.I == I;
+ }
+ bool operator!=(const IntervalIterator &Other) const {
+ return !(*this == Other);
+ }
+ IntervalIterator &operator++() {
+ assert(I != nullptr && "already at end()!");
+ I = I->getNextNode();
+ return *this;
+ }
+ IntervalIterator operator++(int) {
+ auto ItCopy = *this;
+ ++*this;
+ return ItCopy;
+ }
+ IntervalIterator &operator--() {
+ // `I` is nullptr for end() when ToI is the BB terminator.
+ I = I != nullptr ? I->getPrevNode() : R.ToI;
+ return *this;
+ }
+ IntervalIterator operator--(int) {
+ auto ItCopy = *this;
+ --*this;
+ return ItCopy;
+ }
+ template <typename HT = std::enable_if<std::is_same<T, T *&>::value>>
+ T &operator*() {
+ return *I;
+ }
+ T &operator*() const { return *I; }
+};
+
+template <typename T> class Interval {
+ T *From;
+ T *To;
+
+public:
+ Interval() : From(nullptr), To(nullptr) {}
+ Interval(T *From, T *To) : From(From), To(To) {
+ assert((From == To || From->comesBefore(To)) &&
+ "From should come before TopI!");
+ }
+ Interval(ArrayRef<T *> Instrs) {
+ assert(!Instrs.empty() && "Expected non-empty Instrs!");
+ From = Instrs[0];
+ To = Instrs[0];
+ for (auto *I : drop_begin(Instrs)) {
+ if (I->comesBefore(From))
+ From = I;
+ else if (To->comesBefore(I))
+ To = I;
+ }
+ }
+ bool empty() const {
+ assert(((From == nullptr && To == nullptr) ||
+ (From != nullptr && To != nullptr)) &&
+ "Either none or both should be null");
+ return From == nullptr;
+ }
+ bool contains(T *I) const {
+ if (empty())
+ return false;
+ return (From == I || From->comesBefore(I)) &&
+ (I == To || I->comesBefore(To));
+ }
+ T *top() const { return From; }
+ T *bottom() const { return To; }
+
+ using iterator = IntervalIterator<T, Interval>;
+ using const_iterator = IntervalIterator<const T, const Interval>;
+ iterator begin() { return iterator(From, *this); }
+ iterator end() {
+ return iterator(To != nullptr ? To->getNextNode() : nullptr, *this);
+ }
+ const_iterator begin() const { return const_iterator(From, *this); }
+ const_iterator end() const {
+ return const_iterator(To != nullptr ? To->getNextNode() : nullptr, *this);
+ }
+};
+
+} // namespace llvm::sandboxir
+
+#endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_INSTRINTERVAL_H
diff --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.cpp
index 139e581ce03d96..67b56451c7b594 100644
--- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.cpp
+++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.cpp
@@ -31,11 +31,11 @@ void DGNode::dump() const {
}
#endif // NDEBUG
-InstrInterval DependencyGraph::extend(ArrayRef<Instruction *> Instrs) {
+Interval<Instruction> DependencyGraph::extend(ArrayRef<Instruction *> Instrs) {
if (Instrs.empty())
return {};
// TODO: For now create a chain of dependencies.
- InstrInterval Interval(Instrs);
+ Interval<Instruction> Interval(Instrs);
auto *TopI = Interval.top();
auto *BotI = Interval.bottom();
DGNode *LastN = getOrCreateNode(TopI);
diff --git a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt
index 86b1d968094cab..deb3cd398d02d2 100644
--- a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt
+++ b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt
@@ -9,7 +9,7 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(SandboxVectorizerTests
DependencyGraphTest.cpp
- InstrIntervalTest.cpp
+ IntervalTest.cpp
LegalityTest.cpp
RegionTest.cpp
)
diff --git a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/InstrIntervalTest.cpp b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/IntervalTest.cpp
similarity index 65%
rename from llvm/unittests/Transforms/Vectorize/SandboxVectorizer/InstrIntervalTest.cpp
rename to llvm/unittests/Transforms/Vectorize/SandboxVectorizer/IntervalTest.cpp
index e22bb78a07d300..bf6c200e26a60c 100644
--- a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/InstrIntervalTest.cpp
+++ b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/IntervalTest.cpp
@@ -6,16 +6,16 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Transforms/Vectorize/SandboxVectorizer/InstrInterval.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/SandboxIR/SandboxIR.h"
#include "llvm/Support/SourceMgr.h"
+#include "llvm/Transforms/Vectorize/SandboxVectorizer/Interval.h"
#include "gmock/gmock-matchers.h"
#include "gtest/gtest.h"
using namespace llvm;
-struct InstrIntervalTest : public testing::Test {
+struct IntervalTest : public testing::Test {
LLVMContext C;
std::unique_ptr<Module> M;
@@ -27,7 +27,7 @@ struct InstrIntervalTest : public testing::Test {
}
};
-TEST_F(InstrIntervalTest, Basic) {
+TEST_F(IntervalTest, Basic) {
parseIR(C, R"IR(
define void @foo(i8 %v0) {
%add0 = add i8 %v0, %v0
@@ -46,39 +46,40 @@ define void @foo(i8 %v0) {
auto *I2 = &*It++;
auto *Ret = &*It++;
- sandboxir::InstrInterval Interval(I0, Ret);
+ sandboxir::Interval<sandboxir::Instruction> Intvl(I0, Ret);
#ifndef NDEBUG
- EXPECT_DEATH(sandboxir::InstrInterval(I1, I0), ".*before.*");
+ EXPECT_DEATH(sandboxir::Interval<sandboxir::Instruction>(I1, I0),
+ ".*before.*");
#endif // NDEBUG
- // Check InstrInterval(ArrayRef), from(), to().
+ // Check Interval<sandboxir::Instruction>(ArrayRef), from(), to().
{
- sandboxir::InstrInterval Interval(
+ sandboxir::Interval<sandboxir::Instruction> Intvl(
SmallVector<sandboxir::Instruction *>({I0, Ret}));
- EXPECT_EQ(Interval.top(), I0);
- EXPECT_EQ(Interval.bottom(), Ret);
+ EXPECT_EQ(Intvl.top(), I0);
+ EXPECT_EQ(Intvl.bottom(), Ret);
}
{
- sandboxir::InstrInterval Interval(
+ sandboxir::Interval<sandboxir::Instruction> Intvl(
SmallVector<sandboxir::Instruction *>({Ret, I0}));
- EXPECT_EQ(Interval.top(), I0);
- EXPECT_EQ(Interval.bottom(), Ret);
+ EXPECT_EQ(Intvl.top(), I0);
+ EXPECT_EQ(Intvl.bottom(), Ret);
}
{
- sandboxir::InstrInterval Interval(
+ sandboxir::Interval<sandboxir::Instruction> Intvl(
SmallVector<sandboxir::Instruction *>({I0, I0}));
- EXPECT_EQ(Interval.top(), I0);
- EXPECT_EQ(Interval.bottom(), I0);
+ EXPECT_EQ(Intvl.top(), I0);
+ EXPECT_EQ(Intvl.bottom(), I0);
}
// Check empty().
- EXPECT_FALSE(Interval.empty());
- sandboxir::InstrInterval Empty;
+ EXPECT_FALSE(Intvl.empty());
+ sandboxir::Interval<sandboxir::Instruction> Empty;
EXPECT_TRUE(Empty.empty());
- sandboxir::InstrInterval One(I0, I0);
+ sandboxir::Interval<sandboxir::Instruction> One(I0, I0);
EXPECT_FALSE(One.empty());
// Check contains().
for (auto &I : *BB) {
- EXPECT_TRUE(Interval.contains(&I));
+ EXPECT_TRUE(Intvl.contains(&I));
EXPECT_FALSE(Empty.contains(&I));
}
EXPECT_FALSE(One.contains(I1));
@@ -86,6 +87,6 @@ define void @foo(i8 %v0) {
EXPECT_FALSE(One.contains(Ret));
// Check iterator.
auto BBIt = BB->begin();
- for (auto &I : Interval)
+ for (auto &I : Intvl)
EXPECT_EQ(&I, &*BBIt++);
}
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
Fixed the clang-format issue. |
Rebase |
Interval() : From(nullptr), To(nullptr) {} | ||
Interval(T *From, T *To) : From(From), To(To) { | ||
assert((From == To || From->comesBefore(To)) && | ||
"From should come before TopI!"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo, "before To!"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. This should be From
, left over from a previous refactoring.
"From should come before TopI!"); | ||
} | ||
Interval(ArrayRef<T *> Instrs) { | ||
assert(!Instrs.empty() && "Expected non-empty Instrs!"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't Instrs be re-named here? Like Say Items?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch!
This patch converts InstrInterval class to a class template and renames InstrInterval to Itnerval. This change will allow us to reuse the Interval for dependency graph nodes.
llvm#110021) This patch converts InstrInterval class to a class template and renames InstrInterval to Itnerval. This change will allow us to reuse the Interval for dependency graph nodes.
This patch converts InstrInterval class to a class template and renames InstrInterval to Itnerval.
This change will allow us to reuse the Interval for dependency graph nodes.