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
, MetadataFromIR
) {
86 define i8 @foo(i8 %v0, i8 %v1) {
87 %t0 = add i8 %v0, 1, !sandboxvec !0
88 %t1 = add i8 %t0, %v1, !sandboxvec !1
89 %t2 = add i8 %t1, %v1, !sandboxvec !1
93 !0 = distinct !{!"sandboxregion
"}
94 !1 = distinct !{!"sandboxregion
"}
96 llvm::Function
*LLVMF
= &*M
->getFunction("foo");
97 sandboxir::Context
Ctx(C
);
98 auto *F
= Ctx
.createFunction(LLVMF
);
99 auto *BB
= &*F
->begin();
100 auto It
= BB
->begin();
101 auto *T0
= cast
<sandboxir::Instruction
>(&*It
++);
102 auto *T1
= cast
<sandboxir::Instruction
>(&*It
++);
103 auto *T2
= cast
<sandboxir::Instruction
>(&*It
++);
105 SmallVector
<std::unique_ptr
<sandboxir::Region
>> Regions
=
106 sandboxir::Region::createRegionsFromMD(*F
);
107 EXPECT_THAT(Regions
[0]->insts(), testing::UnorderedElementsAre(T0
));
108 EXPECT_THAT(Regions
[1]->insts(), testing::UnorderedElementsAre(T1
, T2
));
111 TEST_F(RegionTest
, NonContiguousRegion
) {
113 define i8 @foo(i8 %v0, i8 %v1) {
114 %t0 = add i8 %v0, 1, !sandboxvec !0
115 %t1 = add i8 %t0, %v1
116 %t2 = add i8 %t1, %v1, !sandboxvec !0
120 !0 = distinct !{!"sandboxregion
"}
122 llvm::Function
*LLVMF
= &*M
->getFunction("foo");
123 sandboxir::Context
Ctx(C
);
124 auto *F
= Ctx
.createFunction(LLVMF
);
125 auto *BB
= &*F
->begin();
126 auto It
= BB
->begin();
127 auto *T0
= cast
<sandboxir::Instruction
>(&*It
++);
128 [[maybe_unused
]] auto *T1
= cast
<sandboxir::Instruction
>(&*It
++);
129 auto *T2
= cast
<sandboxir::Instruction
>(&*It
++);
131 SmallVector
<std::unique_ptr
<sandboxir::Region
>> Regions
=
132 sandboxir::Region::createRegionsFromMD(*F
);
133 EXPECT_THAT(Regions
[0]->insts(), testing::UnorderedElementsAre(T0
, T2
));
136 TEST_F(RegionTest
, DumpedMetadata
) {
138 define i8 @foo(i8 %v0, i8 %v1) {
140 %t1 = add i8 %t0, %v1
141 %t2 = add i8 %t1, %v1
145 llvm::Function
*LLVMF
= &*M
->getFunction("foo");
146 sandboxir::Context
Ctx(C
);
147 auto *F
= Ctx
.createFunction(LLVMF
);
148 auto *BB
= &*F
->begin();
149 auto It
= BB
->begin();
150 auto *T0
= cast
<sandboxir::Instruction
>(&*It
++);
151 [[maybe_unused
]] auto *T1
= cast
<sandboxir::Instruction
>(&*It
++);
152 auto *T2
= cast
<sandboxir::Instruction
>(&*It
++);
153 [[maybe_unused
]] auto *Ret
= cast
<sandboxir::Instruction
>(&*It
++);
154 sandboxir::Region
Rgn(Ctx
);
156 sandboxir::Region
Rgn2(Ctx
);
160 llvm::raw_string_ostream
RSO(output
);
161 M
->print(RSO
, nullptr, /*ShouldPreserveUseListOrder=*/true,
162 /*IsForDebug=*/true);
164 // TODO: Replace this with a lit test, which is more suitable for this kind
166 std::string expected
= R
"(; ModuleID = '<string>'
167 source_filename = "<string
>"
169 define i8 @foo(i8 %v0, i8 %v1) {
170 %t0 = add i8 %v0, 1, !sandboxvec !0
171 %t1 = add i8 %t0, %v1
172 %t2 = add i8 %t1, %v1, !sandboxvec !1
176 !0 = distinct !{!"sandboxregion
"}
177 !1 = distinct !{!"sandboxregion
"}
179 EXPECT_EQ(expected
, output
);
182 TEST_F(RegionTest
, MetadataRoundTrip
) {
184 define i8 @foo(i8 %v0, i8 %v1) {
186 %t1 = add i8 %t0, %v1
190 llvm::Function
*LLVMF
= &*M
->getFunction("foo");
191 sandboxir::Context
Ctx(C
);
192 auto *F
= Ctx
.createFunction(LLVMF
);
193 auto *BB
= &*F
->begin();
194 auto It
= BB
->begin();
195 auto *T0
= cast
<sandboxir::Instruction
>(&*It
++);
196 auto *T1
= cast
<sandboxir::Instruction
>(&*It
++);
198 sandboxir::Region
Rgn(Ctx
);
202 SmallVector
<std::unique_ptr
<sandboxir::Region
>> Regions
=
203 sandboxir::Region::createRegionsFromMD(*F
);
204 ASSERT_EQ(1U, Regions
.size());
206 EXPECT_EQ(Rgn
, *Regions
[0].get());