Skip to content

Commit 7688393

Browse files
authored
[SandboxVec] Simple Instruction Interval class (llvm#108882)
An InstrInterval is a range of instructions in a block. The class will eventually have an API for set operations, like union, intersection etc.
1 parent d5b7050 commit 7688393

File tree

3 files changed

+183
-0
lines changed

3 files changed

+183
-0
lines changed
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
//===- InstrInterval.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 InstrInterval class is an interval of instructions in a block.
10+
// It provides an API for some basic operations on the interval, including some
11+
// simple set operations, like union, interseciton and others.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_INSTRINTERVAL_H
16+
#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_INSTRINTERVAL_H
17+
18+
#include "llvm/SandboxIR/SandboxIR.h"
19+
#include <iterator>
20+
21+
namespace llvm::sandboxir {
22+
23+
/// A simple iterator for iterating the interval.
24+
template <typename DerefType, typename InstrIntervalType>
25+
class InstrIntervalIterator {
26+
sandboxir::Instruction *I;
27+
InstrIntervalType &R;
28+
29+
public:
30+
using difference_type = std::ptrdiff_t;
31+
using value_type = sandboxir::Instruction;
32+
using pointer = value_type *;
33+
using reference = sandboxir::Instruction &;
34+
using iterator_category = std::bidirectional_iterator_tag;
35+
36+
InstrIntervalIterator(sandboxir::Instruction *I, InstrIntervalType &R)
37+
: I(I), R(R) {}
38+
bool operator==(const InstrIntervalIterator &Other) const {
39+
assert(&R == &Other.R && "Iterators belong to different regions!");
40+
return Other.I == I;
41+
}
42+
bool operator!=(const InstrIntervalIterator &Other) const {
43+
return !(*this == Other);
44+
}
45+
InstrIntervalIterator &operator++() {
46+
assert(I != nullptr && "already at end()!");
47+
I = I->getNextNode();
48+
return *this;
49+
}
50+
InstrIntervalIterator operator++(int) {
51+
auto ItCopy = *this;
52+
++*this;
53+
return ItCopy;
54+
}
55+
InstrIntervalIterator &operator--() {
56+
// `I` is nullptr for end() when ToI is the BB terminator.
57+
I = I != nullptr ? I->getPrevNode() : R.ToI;
58+
return *this;
59+
}
60+
InstrIntervalIterator operator--(int) {
61+
auto ItCopy = *this;
62+
--*this;
63+
return ItCopy;
64+
}
65+
template <typename T =
66+
std::enable_if<std::is_same<DerefType, Instruction *&>::value>>
67+
sandboxir::Instruction &operator*() {
68+
return *I;
69+
}
70+
DerefType operator*() const { return *I; }
71+
};
72+
73+
class InstrInterval {
74+
Instruction *FromI;
75+
Instruction *ToI;
76+
77+
public:
78+
InstrInterval() : FromI(nullptr), ToI(nullptr) {}
79+
InstrInterval(Instruction *FromI, Instruction *ToI) : FromI(FromI), ToI(ToI) {
80+
assert((FromI == ToI || FromI->comesBefore(ToI)) &&
81+
"FromI should come before TopI!");
82+
}
83+
bool empty() const {
84+
assert(((FromI == nullptr && ToI == nullptr) ||
85+
(FromI != nullptr && ToI != nullptr)) &&
86+
"Either none or both should be null");
87+
return FromI == nullptr;
88+
}
89+
bool contains(Instruction *I) const {
90+
if (empty())
91+
return false;
92+
return (FromI == I || FromI->comesBefore(I)) &&
93+
(I == ToI || I->comesBefore(ToI));
94+
}
95+
96+
using iterator =
97+
InstrIntervalIterator<sandboxir::Instruction &, InstrInterval>;
98+
using const_iterator = InstrIntervalIterator<const sandboxir::Instruction &,
99+
const InstrInterval>;
100+
iterator begin() { return iterator(FromI, *this); }
101+
iterator end() {
102+
return iterator(ToI != nullptr ? ToI->getNextNode() : nullptr, *this);
103+
}
104+
const_iterator begin() const { return const_iterator(FromI, *this); }
105+
const_iterator end() const {
106+
return const_iterator(ToI != nullptr ? ToI->getNextNode() : nullptr, *this);
107+
}
108+
};
109+
} // namespace llvm::sandboxir
110+
111+
#endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_INSTRINTERVAL_H

llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ set(LLVM_LINK_COMPONENTS
99

1010
add_llvm_unittest(SandboxVectorizerTests
1111
DependencyGraphTest.cpp
12+
InstrIntervalTest.cpp
1213
LegalityTest.cpp
1314
RegionTest.cpp
1415
)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
//===- InstrIntervalTest.cpp ----------------------------------------------===//
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+
#include "llvm/Transforms/Vectorize/SandboxVectorizer/InstrInterval.h"
10+
#include "llvm/AsmParser/Parser.h"
11+
#include "llvm/SandboxIR/SandboxIR.h"
12+
#include "llvm/Support/SourceMgr.h"
13+
#include "gmock/gmock-matchers.h"
14+
#include "gtest/gtest.h"
15+
16+
using namespace llvm;
17+
18+
struct InstrIntervalTest : public testing::Test {
19+
LLVMContext C;
20+
std::unique_ptr<Module> M;
21+
22+
void parseIR(LLVMContext &C, const char *IR) {
23+
SMDiagnostic Err;
24+
M = parseAssemblyString(IR, Err, C);
25+
if (!M)
26+
Err.print("InstrIntervalTest", errs());
27+
}
28+
};
29+
30+
TEST_F(InstrIntervalTest, Basic) {
31+
parseIR(C, R"IR(
32+
define void @foo(i8 %v0) {
33+
%add0 = add i8 %v0, %v0
34+
%add1 = add i8 %v0, %v0
35+
%add2 = add i8 %v0, %v0
36+
ret void
37+
}
38+
)IR");
39+
Function &LLVMF = *M->getFunction("foo");
40+
sandboxir::Context Ctx(C);
41+
auto &F = *Ctx.createFunction(&LLVMF);
42+
auto *BB = &*F.begin();
43+
auto It = BB->begin();
44+
auto *I0 = &*It++;
45+
auto *I1 = &*It++;
46+
auto *I2 = &*It++;
47+
auto *Ret = &*It++;
48+
49+
sandboxir::InstrInterval Interval(I0, Ret);
50+
#ifndef NDEBUG
51+
EXPECT_DEATH(sandboxir::InstrInterval(I1, I0), ".*before.*");
52+
#endif // NDEBUG
53+
// Check empty().
54+
EXPECT_FALSE(Interval.empty());
55+
sandboxir::InstrInterval Empty;
56+
EXPECT_TRUE(Empty.empty());
57+
sandboxir::InstrInterval One(I0, I0);
58+
EXPECT_FALSE(One.empty());
59+
// Check contains().
60+
for (auto &I : *BB) {
61+
EXPECT_TRUE(Interval.contains(&I));
62+
EXPECT_FALSE(Empty.contains(&I));
63+
}
64+
EXPECT_FALSE(One.contains(I1));
65+
EXPECT_FALSE(One.contains(I2));
66+
EXPECT_FALSE(One.contains(Ret));
67+
// Check iterator.
68+
auto BBIt = BB->begin();
69+
for (auto &I : Interval)
70+
EXPECT_EQ(&I, &*BBIt++);
71+
}

0 commit comments

Comments
 (0)