Skip to content

Commit a96c9f7

Browse files
committed
[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.
1 parent 6cbb245 commit a96c9f7

File tree

4 files changed

+191
-0
lines changed

4 files changed

+191
-0
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
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)
80+
: FromI(FromI), ToI(ToI) {}
81+
bool empty() const {
82+
assert(((FromI == nullptr && ToI == nullptr) ||
83+
(FromI != nullptr && ToI != nullptr)) &&
84+
"Either none or both should be null");
85+
return FromI == nullptr;
86+
}
87+
bool contains(Instruction *I) const {
88+
if (empty())
89+
return false;
90+
return (FromI == I || FromI->comesBefore(I)) &&
91+
(I == ToI || I->comesBefore(ToI));
92+
}
93+
94+
using iterator =
95+
InstrIntervalIterator<sandboxir::Instruction &, InstrInterval>;
96+
using const_iterator = InstrIntervalIterator<const sandboxir::Instruction &,
97+
const InstrInterval>;
98+
iterator begin() { return iterator(FromI, *this); }
99+
iterator end() {
100+
return iterator(ToI != nullptr ? ToI->getNextNode() : nullptr, *this);
101+
}
102+
const_iterator begin() const { return const_iterator(FromI, *this); }
103+
const_iterator end() const {
104+
return const_iterator(ToI != nullptr ? ToI->getNextNode() : nullptr, *this);
105+
}
106+
};
107+
} // namespace llvm::sandboxir
108+
109+
#endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_INSTRINTERVAL_H

llvm/unittests/Transforms/Vectorize/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
add_subdirectory(SandboxVectorizer)
2+
13
set(LLVM_LINK_COMPONENTS
24
Analysis
35
Core
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
set(LLVM_LINK_COMPONENTS
2+
Analysis
3+
Core
4+
Vectorize
5+
AsmParser
6+
TargetParser
7+
SandboxIR
8+
)
9+
10+
add_llvm_unittest(SandboxVectorizerTests
11+
InstrIntervalTest.cpp
12+
)
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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+
// Check empty().
51+
EXPECT_FALSE(Interval.empty());
52+
sandboxir::InstrInterval Empty;
53+
EXPECT_TRUE(Empty.empty());
54+
sandboxir::InstrInterval One(I0, I0);
55+
EXPECT_FALSE(One.empty());
56+
// Check contains().
57+
for (auto &I : *BB) {
58+
EXPECT_TRUE(Interval.contains(&I));
59+
EXPECT_FALSE(Empty.contains(&I));
60+
}
61+
EXPECT_FALSE(One.contains(I1));
62+
EXPECT_FALSE(One.contains(I2));
63+
EXPECT_FALSE(One.contains(Ret));
64+
// Check iterator.
65+
auto BBIt = BB->begin();
66+
for (auto &I : Interval)
67+
EXPECT_EQ(&I, &*BBIt++);
68+
}

0 commit comments

Comments
 (0)