1 //===- RegionTest.cpp -----------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/SandboxIR/Region.h"
10 #include "llvm/AsmParser/Parser.h"
11 #include "llvm/SandboxIR/Context.h"
12 #include "llvm/SandboxIR/Function.h"
13 #include "llvm/SandboxIR/Instruction.h"
14 #include "llvm/Support/SourceMgr.h"
15 #include "gmock/gmock-matchers.h"
16 #include "gtest/gtest.h"
20 struct RegionTest
: public testing::Test
{
22 std::unique_ptr
<Module
> M
;
24 void parseIR(LLVMContext
&C
, const char *IR
) {
26 M
= parseAssemblyString(IR
, Err
, C
);
28 Err
.print("RegionTest", errs());
32 TEST_F(RegionTest
, Basic
) {
34 define i8 @foo(i8 %v0, i8 %v1) {
40 llvm::Function
*LLVMF
= &*M
->getFunction("foo");
41 sandboxir::Context
Ctx(C
);
42 auto *F
= Ctx
.createFunction(LLVMF
);
43 auto *BB
= &*F
->begin();
44 auto It
= BB
->begin();
45 auto *T0
= cast
<sandboxir::Instruction
>(&*It
++);
46 auto *T1
= cast
<sandboxir::Instruction
>(&*It
++);
47 auto *Ret
= cast
<sandboxir::Instruction
>(&*It
++);
48 sandboxir::Region
Rgn(Ctx
);
51 EXPECT_EQ(&Ctx
, &Rgn
.getContext());
53 // Check add / remove / empty.
54 EXPECT_TRUE(Rgn
.empty());
56 EXPECT_FALSE(Rgn
.empty());
58 EXPECT_TRUE(Rgn
.empty());
64 // Use an ordered matcher because we're supposed to preserve the insertion
65 // order for determinism.
66 EXPECT_THAT(Rgn
.insts(), testing::ElementsAre(T0
, T1
, Ret
));
69 EXPECT_TRUE(Rgn
.contains(T0
));
71 EXPECT_FALSE(Rgn
.contains(T0
));
74 // Check equality comparison. Insert in reverse order into `Other` to check
75 // that comparison is order-independent.
76 sandboxir::Region
Other(Ctx
);
78 EXPECT_NE(Rgn
, Other
);
80 EXPECT_EQ(Rgn
, Other
);
84 TEST_F(RegionTest
, CallbackUpdates
) {
86 define i8 @foo(i8 %v0, i8 %v1, ptr %ptr) {
92 llvm::Function
*LLVMF
= &*M
->getFunction("foo");
93 sandboxir::Context
Ctx(C
);
94 auto *F
= Ctx
.createFunction(LLVMF
);
95 auto *Ptr
= F
->getArg(2);
96 auto *BB
= &*F
->begin();
97 auto It
= BB
->begin();
98 auto *T0
= cast
<sandboxir::Instruction
>(&*It
++);
99 auto *T1
= cast
<sandboxir::Instruction
>(&*It
++);
100 auto *Ret
= cast
<sandboxir::Instruction
>(&*It
++);
101 sandboxir::Region
Rgn(Ctx
);
106 auto *NewI
= sandboxir::StoreInst::create(T0
, Ptr
, /*Align=*/std::nullopt
,
107 Ret
->getIterator(), Ctx
);
108 EXPECT_THAT(Rgn
.insts(), testing::ElementsAre(T0
, T1
, NewI
));
111 T1
->eraseFromParent();
112 EXPECT_THAT(Rgn
.insts(), testing::ElementsAre(T0
, NewI
));
115 TEST_F(RegionTest
, MetadataFromIR
) {
117 define i8 @foo(i8 %v0, i8 %v1) {
118 %t0 = add i8 %v0, 1, !sandboxvec !0
119 %t1 = add i8 %t0, %v1, !sandboxvec !1
120 %t2 = add i8 %t1, %v1, !sandboxvec !1
124 !0 = distinct !{!"sandboxregion
"}
125 !1 = distinct !{!"sandboxregion
"}
127 llvm::Function
*LLVMF
= &*M
->getFunction("foo");
128 sandboxir::Context
Ctx(C
);
129 auto *F
= Ctx
.createFunction(LLVMF
);
130 auto *BB
= &*F
->begin();
131 auto It
= BB
->begin();
132 auto *T0
= cast
<sandboxir::Instruction
>(&*It
++);
133 auto *T1
= cast
<sandboxir::Instruction
>(&*It
++);
134 auto *T2
= cast
<sandboxir::Instruction
>(&*It
++);
136 SmallVector
<std::unique_ptr
<sandboxir::Region
>> Regions
=
137 sandboxir::Region::createRegionsFromMD(*F
);
138 EXPECT_THAT(Regions
[0]->insts(), testing::UnorderedElementsAre(T0
));
139 EXPECT_THAT(Regions
[1]->insts(), testing::UnorderedElementsAre(T1
, T2
));
142 TEST_F(RegionTest
, NonContiguousRegion
) {
144 define i8 @foo(i8 %v0, i8 %v1) {
145 %t0 = add i8 %v0, 1, !sandboxvec !0
146 %t1 = add i8 %t0, %v1
147 %t2 = add i8 %t1, %v1, !sandboxvec !0
151 !0 = distinct !{!"sandboxregion
"}
153 llvm::Function
*LLVMF
= &*M
->getFunction("foo");
154 sandboxir::Context
Ctx(C
);
155 auto *F
= Ctx
.createFunction(LLVMF
);
156 auto *BB
= &*F
->begin();
157 auto It
= BB
->begin();
158 auto *T0
= cast
<sandboxir::Instruction
>(&*It
++);
159 [[maybe_unused
]] auto *T1
= cast
<sandboxir::Instruction
>(&*It
++);
160 auto *T2
= cast
<sandboxir::Instruction
>(&*It
++);
162 SmallVector
<std::unique_ptr
<sandboxir::Region
>> Regions
=
163 sandboxir::Region::createRegionsFromMD(*F
);
164 EXPECT_THAT(Regions
[0]->insts(), testing::UnorderedElementsAre(T0
, T2
));
167 TEST_F(RegionTest
, DumpedMetadata
) {
169 define i8 @foo(i8 %v0, i8 %v1) {
171 %t1 = add i8 %t0, %v1
172 %t2 = add i8 %t1, %v1
176 llvm::Function
*LLVMF
= &*M
->getFunction("foo");
177 sandboxir::Context
Ctx(C
);
178 auto *F
= Ctx
.createFunction(LLVMF
);
179 auto *BB
= &*F
->begin();
180 auto It
= BB
->begin();
181 auto *T0
= cast
<sandboxir::Instruction
>(&*It
++);
182 [[maybe_unused
]] auto *T1
= cast
<sandboxir::Instruction
>(&*It
++);
183 auto *T2
= cast
<sandboxir::Instruction
>(&*It
++);
184 [[maybe_unused
]] auto *Ret
= cast
<sandboxir::Instruction
>(&*It
++);
185 sandboxir::Region
Rgn(Ctx
);
187 sandboxir::Region
Rgn2(Ctx
);
191 llvm::raw_string_ostream
RSO(output
);
192 M
->print(RSO
, nullptr, /*ShouldPreserveUseListOrder=*/true,
193 /*IsForDebug=*/true);
195 // TODO: Replace this with a lit test, which is more suitable for this kind
197 std::string expected
= R
"(; ModuleID = '<string>'
198 source_filename = "<string
>"
200 define i8 @foo(i8 %v0, i8 %v1) {
201 %t0 = add i8 %v0, 1, !sandboxvec !0
202 %t1 = add i8 %t0, %v1
203 %t2 = add i8 %t1, %v1, !sandboxvec !1
207 !0 = distinct !{!"sandboxregion
"}
208 !1 = distinct !{!"sandboxregion
"}
210 EXPECT_EQ(expected
, output
);
213 TEST_F(RegionTest
, MetadataRoundTrip
) {
215 define i8 @foo(i8 %v0, i8 %v1) {
217 %t1 = add i8 %t0, %v1
221 llvm::Function
*LLVMF
= &*M
->getFunction("foo");
222 sandboxir::Context
Ctx(C
);
223 auto *F
= Ctx
.createFunction(LLVMF
);
224 auto *BB
= &*F
->begin();
225 auto It
= BB
->begin();
226 auto *T0
= cast
<sandboxir::Instruction
>(&*It
++);
227 auto *T1
= cast
<sandboxir::Instruction
>(&*It
++);
229 sandboxir::Region
Rgn(Ctx
);
233 SmallVector
<std::unique_ptr
<sandboxir::Region
>> Regions
=
234 sandboxir::Region::createRegionsFromMD(*F
);
235 ASSERT_EQ(1U, Regions
.size());
237 EXPECT_EQ(Rgn
, *Regions
[0].get());