[llvm] [SandboxVec] Simple Instruction Interval class (PR #108882)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 18 08:29:03 PDT 2024
https://github.com/vporpo updated https://github.com/llvm/llvm-project/pull/108882
>From 3f7a8e6c1be989d489db2dd671f6b2e8b7d7c949 Mon Sep 17 00:00:00 2001
From: Vasileios Porpodas <vporpodas at google.com>
Date: Mon, 16 Sep 2024 11:51:00 -0700
Subject: [PATCH] [SandboxVec] Simple Instruction Interval class
An InstrInterval is a range of instructions in a block.
The class will eventually have an API for set operations, like union,
intersection etc.
---
.../SandboxVectorizer/InstrInterval.h | 109 ++++++++++++++++++
.../SandboxVectorizer/CMakeLists.txt | 1 +
.../SandboxVectorizer/InstrIntervalTest.cpp | 68 +++++++++++
3 files changed, 178 insertions(+)
create mode 100644 llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/InstrInterval.h
create mode 100644 llvm/unittests/Transforms/Vectorize/SandboxVectorizer/InstrIntervalTest.cpp
diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/InstrInterval.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/InstrInterval.h
new file mode 100644
index 00000000000000..0f16dec94c88c8
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/InstrInterval.h
@@ -0,0 +1,109 @@
+//===- 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) {}
+ 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));
+ }
+
+ 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/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt
index 2c7bf7d7e87541..b0ef71ba2114a1 100644
--- a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt
+++ b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt
@@ -9,5 +9,6 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(SandboxVectorizerTests
DependencyGraphTest.cpp
+ InstrIntervalTest.cpp
LegalityTest.cpp
)
diff --git a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/InstrIntervalTest.cpp b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/InstrIntervalTest.cpp
new file mode 100644
index 00000000000000..b8b8e4e982be56
--- /dev/null
+++ b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/InstrIntervalTest.cpp
@@ -0,0 +1,68 @@
+//===- InstrIntervalTest.cpp ----------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Vectorize/SandboxVectorizer/InstrInterval.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/SandboxIR/SandboxIR.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gmock/gmock-matchers.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+struct InstrIntervalTest : public testing::Test {
+ LLVMContext C;
+ std::unique_ptr<Module> M;
+
+ void parseIR(LLVMContext &C, const char *IR) {
+ SMDiagnostic Err;
+ M = parseAssemblyString(IR, Err, C);
+ if (!M)
+ Err.print("InstrIntervalTest", errs());
+ }
+};
+
+TEST_F(InstrIntervalTest, Basic) {
+ parseIR(C, R"IR(
+define void @foo(i8 %v0) {
+ %add0 = add i8 %v0, %v0
+ %add1 = add i8 %v0, %v0
+ %add2 = add i8 %v0, %v0
+ ret void
+}
+)IR");
+ Function &LLVMF = *M->getFunction("foo");
+ sandboxir::Context Ctx(C);
+ auto &F = *Ctx.createFunction(&LLVMF);
+ auto *BB = &*F.begin();
+ auto It = BB->begin();
+ auto *I0 = &*It++;
+ auto *I1 = &*It++;
+ auto *I2 = &*It++;
+ auto *Ret = &*It++;
+
+ sandboxir::InstrInterval Interval(I0, Ret);
+ // Check empty().
+ EXPECT_FALSE(Interval.empty());
+ sandboxir::InstrInterval Empty;
+ EXPECT_TRUE(Empty.empty());
+ sandboxir::InstrInterval One(I0, I0);
+ EXPECT_FALSE(One.empty());
+ // Check contains().
+ for (auto &I : *BB) {
+ EXPECT_TRUE(Interval.contains(&I));
+ EXPECT_FALSE(Empty.contains(&I));
+ }
+ EXPECT_FALSE(One.contains(I1));
+ EXPECT_FALSE(One.contains(I2));
+ EXPECT_FALSE(One.contains(Ret));
+ // Check iterator.
+ auto BBIt = BB->begin();
+ for (auto &I : Interval)
+ EXPECT_EQ(&I, &*BBIt++);
+}
More information about the llvm-commits
mailing list