Skip to content

[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

Merged
merged 1 commit into from
Sep 27, 2024

Conversation

vporpo
Copy link
Contributor

@vporpo vporpo commented Sep 25, 2024

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.

@llvmbot
Copy link
Member

llvmbot commented Sep 25, 2024

@llvm/pr-subscribers-llvm-transforms

Author: vporpo (vporpo)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/110021.diff

6 Files Affected:

  • (modified) llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.h (+2-2)
  • (removed) llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/InstrInterval.h (-124)
  • (added) llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Interval.h (+125)
  • (modified) llvm/lib/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.cpp (+2-2)
  • (modified) llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt (+1-1)
  • (renamed) llvm/unittests/Transforms/Vectorize/SandboxVectorizer/IntervalTest.cpp (+21-20)
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++);
 }

Copy link

github-actions bot commented Sep 25, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@vporpo
Copy link
Contributor Author

vporpo commented Sep 25, 2024

Fixed the clang-format issue.

@vporpo
Copy link
Contributor Author

vporpo commented Sep 26, 2024

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!");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo, "before To!"

Copy link
Contributor Author

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!");
Copy link
Member

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?

Copy link
Contributor Author

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.
@vporpo vporpo merged commit 3c66a51 into llvm:main Sep 27, 2024
6 of 7 checks passed
Sterling-Augustine pushed a commit to Sterling-Augustine/llvm-project that referenced this pull request Sep 27, 2024
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants