[llvm] [SandboxVec][Interval] Convert InstrInterval class to a class template (PR #110021)

via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 25 11:10:07 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: vporpo (vporpo)

<details>
<summary>Changes</summary>

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
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++);
 }

``````````

</details>


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


More information about the llvm-commits mailing list