1f4cf51c9SYitzhak Mandelbaum //===- unittests/Analysis/IntervalPartitionTest.cpp -----------------------===//
2f4cf51c9SYitzhak Mandelbaum //
3f4cf51c9SYitzhak Mandelbaum // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4f4cf51c9SYitzhak Mandelbaum // See https://llvm.org/LICENSE.txt for license information.
5f4cf51c9SYitzhak Mandelbaum // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f4cf51c9SYitzhak Mandelbaum //
7f4cf51c9SYitzhak Mandelbaum //===----------------------------------------------------------------------===//
8f4cf51c9SYitzhak Mandelbaum
9f4cf51c9SYitzhak Mandelbaum #include "clang/Analysis/Analyses/IntervalPartition.h"
10f4cf51c9SYitzhak Mandelbaum #include "CFGBuildResult.h"
1126db5e65SYitzhak Mandelbaum #include "clang/Analysis/CFG.h"
1226db5e65SYitzhak Mandelbaum #include "llvm/Support/raw_ostream.h"
13f4cf51c9SYitzhak Mandelbaum #include "gmock/gmock.h"
14f4cf51c9SYitzhak Mandelbaum #include "gtest/gtest.h"
1526db5e65SYitzhak Mandelbaum #include <type_traits>
1626db5e65SYitzhak Mandelbaum #include <variant>
17f4cf51c9SYitzhak Mandelbaum
18f4cf51c9SYitzhak Mandelbaum namespace clang {
1926db5e65SYitzhak Mandelbaum
operator <<(llvm::raw_ostream & OS,const std::vector<const CFGBlock * > & Nodes)2026db5e65SYitzhak Mandelbaum llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
2126db5e65SYitzhak Mandelbaum const std::vector<const CFGBlock *> &Nodes) {
2226db5e65SYitzhak Mandelbaum OS << "Blocks{";
2326db5e65SYitzhak Mandelbaum for (const auto *B : Nodes)
2426db5e65SYitzhak Mandelbaum OS << B->getBlockID() << ", ";
2526db5e65SYitzhak Mandelbaum OS << "}";
2626db5e65SYitzhak Mandelbaum return OS;
2726db5e65SYitzhak Mandelbaum }
2826db5e65SYitzhak Mandelbaum
PrintTo(const std::vector<const CFGBlock * > & Nodes,std::ostream * OS)2926db5e65SYitzhak Mandelbaum void PrintTo(const std::vector<const CFGBlock *> &Nodes, std::ostream *OS) {
3026db5e65SYitzhak Mandelbaum std::string Result;
3126db5e65SYitzhak Mandelbaum llvm::raw_string_ostream StringOS(Result);
3226db5e65SYitzhak Mandelbaum StringOS << Nodes;
3326db5e65SYitzhak Mandelbaum *OS << Result;
3426db5e65SYitzhak Mandelbaum }
3526db5e65SYitzhak Mandelbaum
3626db5e65SYitzhak Mandelbaum namespace internal {
operator <<(llvm::raw_ostream & OS,const CFGIntervalNode & I)3726db5e65SYitzhak Mandelbaum llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const CFGIntervalNode &I) {
3826db5e65SYitzhak Mandelbaum OS << "Interval{ID = " << I.ID << ", ";
3926db5e65SYitzhak Mandelbaum OS << "Blocks{";
4026db5e65SYitzhak Mandelbaum for (const auto *B : I.Nodes)
4126db5e65SYitzhak Mandelbaum OS << B->getBlockID() << ", ";
4226db5e65SYitzhak Mandelbaum OS << "}, Pre{";
4326db5e65SYitzhak Mandelbaum for (const auto *P : I.Predecessors)
4426db5e65SYitzhak Mandelbaum OS << P->ID << ",";
4526db5e65SYitzhak Mandelbaum OS << "}, Succ{";
4626db5e65SYitzhak Mandelbaum for (const auto *P : I.Successors)
4726db5e65SYitzhak Mandelbaum OS << P->ID << ",";
4826db5e65SYitzhak Mandelbaum OS << "}}";
4926db5e65SYitzhak Mandelbaum return OS;
5026db5e65SYitzhak Mandelbaum }
5126db5e65SYitzhak Mandelbaum
operator <<(llvm::raw_ostream & OS,const CFGIntervalGraph & G)5226db5e65SYitzhak Mandelbaum llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
5326db5e65SYitzhak Mandelbaum const CFGIntervalGraph &G) {
5426db5e65SYitzhak Mandelbaum OS << "Intervals{";
5526db5e65SYitzhak Mandelbaum for (const auto &I : G) {
5626db5e65SYitzhak Mandelbaum OS << I << ", ";
5726db5e65SYitzhak Mandelbaum }
5826db5e65SYitzhak Mandelbaum OS << "}";
5926db5e65SYitzhak Mandelbaum return OS;
6026db5e65SYitzhak Mandelbaum }
6126db5e65SYitzhak Mandelbaum
PrintTo(const CFGIntervalNode & I,std::ostream * OS)6226db5e65SYitzhak Mandelbaum void PrintTo(const CFGIntervalNode &I, std::ostream *OS) {
6326db5e65SYitzhak Mandelbaum std::string Result;
6426db5e65SYitzhak Mandelbaum llvm::raw_string_ostream StringOS(Result);
6526db5e65SYitzhak Mandelbaum StringOS << I;
6626db5e65SYitzhak Mandelbaum *OS << Result;
6726db5e65SYitzhak Mandelbaum }
6826db5e65SYitzhak Mandelbaum
PrintTo(const CFGIntervalGraph & G,std::ostream * OS)6926db5e65SYitzhak Mandelbaum void PrintTo(const CFGIntervalGraph &G, std::ostream *OS) {
7026db5e65SYitzhak Mandelbaum *OS << "Intervals{";
7126db5e65SYitzhak Mandelbaum for (const auto &I : G) {
7226db5e65SYitzhak Mandelbaum PrintTo(I, OS);
7326db5e65SYitzhak Mandelbaum *OS << ", ";
7426db5e65SYitzhak Mandelbaum }
7526db5e65SYitzhak Mandelbaum *OS << "}";
7626db5e65SYitzhak Mandelbaum }
7726db5e65SYitzhak Mandelbaum } // namespace internal
7826db5e65SYitzhak Mandelbaum
79f4cf51c9SYitzhak Mandelbaum namespace {
80f4cf51c9SYitzhak Mandelbaum
8126db5e65SYitzhak Mandelbaum using ::clang::analysis::BuildCFG;
8226db5e65SYitzhak Mandelbaum using ::clang::analysis::BuildResult;
8326db5e65SYitzhak Mandelbaum using ::clang::internal::buildInterval;
8426db5e65SYitzhak Mandelbaum using ::clang::internal::partitionIntoIntervals;
8526db5e65SYitzhak Mandelbaum using ::testing::ElementsAre;
8626db5e65SYitzhak Mandelbaum using ::testing::IsEmpty;
8726db5e65SYitzhak Mandelbaum using ::testing::Optional;
8826db5e65SYitzhak Mandelbaum using ::testing::Property;
8926db5e65SYitzhak Mandelbaum using ::testing::UnorderedElementsAre;
90f4cf51c9SYitzhak Mandelbaum
9126db5e65SYitzhak Mandelbaum MATCHER_P(intervalID, ID, "") { return arg->ID == ID; }
9226db5e65SYitzhak Mandelbaum
blockIDs(T...IDs)9326db5e65SYitzhak Mandelbaum template <typename... T> auto blockIDs(T... IDs) {
9426db5e65SYitzhak Mandelbaum return UnorderedElementsAre(Property(&CFGBlock::getBlockID, IDs)...);
9526db5e65SYitzhak Mandelbaum }
9626db5e65SYitzhak Mandelbaum
blockOrder(T...IDs)9726db5e65SYitzhak Mandelbaum template <typename... T> auto blockOrder(T... IDs) {
9826db5e65SYitzhak Mandelbaum return ElementsAre(Property(&CFGBlock::getBlockID, IDs)...);
9926db5e65SYitzhak Mandelbaum }
10026db5e65SYitzhak Mandelbaum
10126db5e65SYitzhak Mandelbaum MATCHER_P3(isInterval, ID, Preds, Succs, "") {
10226db5e65SYitzhak Mandelbaum return testing::Matches(ID)(arg.ID) &&
10326db5e65SYitzhak Mandelbaum testing::Matches(Preds)(arg.Predecessors) &&
10426db5e65SYitzhak Mandelbaum testing::Matches(Succs)(arg.Successors);
10526db5e65SYitzhak Mandelbaum }
10626db5e65SYitzhak Mandelbaum
10726db5e65SYitzhak Mandelbaum MATCHER_P4(isInterval, ID, Nodes, Preds, Succs, "") {
10826db5e65SYitzhak Mandelbaum return testing::Matches(ID)(arg.ID) && testing::Matches(Nodes)(arg.Nodes) &&
10926db5e65SYitzhak Mandelbaum testing::Matches(Preds)(arg.Predecessors) &&
11026db5e65SYitzhak Mandelbaum testing::Matches(Succs)(arg.Successors);
11126db5e65SYitzhak Mandelbaum }
11226db5e65SYitzhak Mandelbaum
TEST(BuildInterval,PartitionSimpleOneInterval)11326db5e65SYitzhak Mandelbaum TEST(BuildInterval, PartitionSimpleOneInterval) {
114f4cf51c9SYitzhak Mandelbaum const char *Code = R"(void f() {
115f4cf51c9SYitzhak Mandelbaum int x = 3;
116f4cf51c9SYitzhak Mandelbaum int y = 7;
117f4cf51c9SYitzhak Mandelbaum x = y + x;
118f4cf51c9SYitzhak Mandelbaum })";
119f4cf51c9SYitzhak Mandelbaum BuildResult Result = BuildCFG(Code);
120f4cf51c9SYitzhak Mandelbaum EXPECT_EQ(BuildResult::BuiltCFG, Result.getStatus());
121f4cf51c9SYitzhak Mandelbaum
122f4cf51c9SYitzhak Mandelbaum CFG *cfg = Result.getCFG();
123f4cf51c9SYitzhak Mandelbaum
124f4cf51c9SYitzhak Mandelbaum // Basic correctness checks.
125f4cf51c9SYitzhak Mandelbaum ASSERT_EQ(cfg->size(), 3u);
126f4cf51c9SYitzhak Mandelbaum
127f4cf51c9SYitzhak Mandelbaum auto &EntryBlock = cfg->getEntry();
128f4cf51c9SYitzhak Mandelbaum
12926db5e65SYitzhak Mandelbaum std::vector<const CFGBlock *> I = buildInterval(&EntryBlock);
13026db5e65SYitzhak Mandelbaum EXPECT_EQ(I.size(), 3u);
131f4cf51c9SYitzhak Mandelbaum }
132f4cf51c9SYitzhak Mandelbaum
TEST(BuildInterval,PartitionIfThenOneInterval)133f4cf51c9SYitzhak Mandelbaum TEST(BuildInterval, PartitionIfThenOneInterval) {
134f4cf51c9SYitzhak Mandelbaum const char *Code = R"(void f() {
135f4cf51c9SYitzhak Mandelbaum int x = 3;
136f4cf51c9SYitzhak Mandelbaum if (x > 3)
137f4cf51c9SYitzhak Mandelbaum x = 2;
138f4cf51c9SYitzhak Mandelbaum else
139f4cf51c9SYitzhak Mandelbaum x = 7;
140f4cf51c9SYitzhak Mandelbaum x = x + x;
141f4cf51c9SYitzhak Mandelbaum })";
142f4cf51c9SYitzhak Mandelbaum BuildResult Result = BuildCFG(Code);
143f4cf51c9SYitzhak Mandelbaum EXPECT_EQ(BuildResult::BuiltCFG, Result.getStatus());
144f4cf51c9SYitzhak Mandelbaum
145f4cf51c9SYitzhak Mandelbaum CFG *cfg = Result.getCFG();
146f4cf51c9SYitzhak Mandelbaum
147f4cf51c9SYitzhak Mandelbaum // Basic correctness checks.
148f4cf51c9SYitzhak Mandelbaum ASSERT_EQ(cfg->size(), 6u);
149f4cf51c9SYitzhak Mandelbaum
150f4cf51c9SYitzhak Mandelbaum auto &EntryBlock = cfg->getEntry();
151f4cf51c9SYitzhak Mandelbaum
15226db5e65SYitzhak Mandelbaum std::vector<const CFGBlock *> I = buildInterval(&EntryBlock);
15326db5e65SYitzhak Mandelbaum EXPECT_EQ(I.size(), 6u);
154f4cf51c9SYitzhak Mandelbaum }
155f4cf51c9SYitzhak Mandelbaum
TEST(BuildInterval,PartitionWhileMultipleIntervals)156f4cf51c9SYitzhak Mandelbaum TEST(BuildInterval, PartitionWhileMultipleIntervals) {
157f4cf51c9SYitzhak Mandelbaum const char *Code = R"(void f() {
158f4cf51c9SYitzhak Mandelbaum int x = 3;
159f4cf51c9SYitzhak Mandelbaum while (x >= 3)
160f4cf51c9SYitzhak Mandelbaum --x;
161f4cf51c9SYitzhak Mandelbaum x = x + x;
162f4cf51c9SYitzhak Mandelbaum })";
163f4cf51c9SYitzhak Mandelbaum BuildResult Result = BuildCFG(Code);
164f4cf51c9SYitzhak Mandelbaum ASSERT_EQ(BuildResult::BuiltCFG, Result.getStatus());
165f4cf51c9SYitzhak Mandelbaum
166f4cf51c9SYitzhak Mandelbaum CFG *cfg = Result.getCFG();
167f4cf51c9SYitzhak Mandelbaum ASSERT_EQ(cfg->size(), 7u);
168f4cf51c9SYitzhak Mandelbaum
169f4cf51c9SYitzhak Mandelbaum auto *EntryBlock = &cfg->getEntry();
170f4cf51c9SYitzhak Mandelbaum CFGBlock *InitXBlock = *EntryBlock->succ_begin();
171f4cf51c9SYitzhak Mandelbaum CFGBlock *LoopHeadBlock = *InitXBlock->succ_begin();
172f4cf51c9SYitzhak Mandelbaum
17326db5e65SYitzhak Mandelbaum std::vector<const CFGBlock *> I1 = buildInterval(EntryBlock);
17426db5e65SYitzhak Mandelbaum EXPECT_THAT(I1, ElementsAre(EntryBlock, InitXBlock));
175f4cf51c9SYitzhak Mandelbaum
17626db5e65SYitzhak Mandelbaum std::vector<const CFGBlock *> I2 = buildInterval(LoopHeadBlock);
17726db5e65SYitzhak Mandelbaum EXPECT_EQ(I2.size(), 5u);
178f4cf51c9SYitzhak Mandelbaum }
179f4cf51c9SYitzhak Mandelbaum
TEST(PartitionIntoIntervals,PartitionIfThenOneInterval)180f4cf51c9SYitzhak Mandelbaum TEST(PartitionIntoIntervals, PartitionIfThenOneInterval) {
181f4cf51c9SYitzhak Mandelbaum const char *Code = R"(void f() {
182f4cf51c9SYitzhak Mandelbaum int x = 3;
183f4cf51c9SYitzhak Mandelbaum if (x > 3)
184f4cf51c9SYitzhak Mandelbaum x = 2;
185f4cf51c9SYitzhak Mandelbaum else
186f4cf51c9SYitzhak Mandelbaum x = 7;
187f4cf51c9SYitzhak Mandelbaum x = x + x;
188f4cf51c9SYitzhak Mandelbaum })";
189f4cf51c9SYitzhak Mandelbaum BuildResult Result = BuildCFG(Code);
190f4cf51c9SYitzhak Mandelbaum ASSERT_EQ(BuildResult::BuiltCFG, Result.getStatus());
191f4cf51c9SYitzhak Mandelbaum
19226db5e65SYitzhak Mandelbaum auto Graph = partitionIntoIntervals(*Result.getCFG());
19326db5e65SYitzhak Mandelbaum EXPECT_EQ(Graph.size(), 1u);
19426db5e65SYitzhak Mandelbaum EXPECT_THAT(Graph, ElementsAre(isInterval(0, IsEmpty(), IsEmpty())));
195f4cf51c9SYitzhak Mandelbaum }
196f4cf51c9SYitzhak Mandelbaum
TEST(PartitionIntoIntervals,PartitionWhileTwoIntervals)197f4cf51c9SYitzhak Mandelbaum TEST(PartitionIntoIntervals, PartitionWhileTwoIntervals) {
198f4cf51c9SYitzhak Mandelbaum const char *Code = R"(void f() {
199f4cf51c9SYitzhak Mandelbaum int x = 3;
200f4cf51c9SYitzhak Mandelbaum while (x >= 3)
201f4cf51c9SYitzhak Mandelbaum --x;
202f4cf51c9SYitzhak Mandelbaum x = x + x;
203f4cf51c9SYitzhak Mandelbaum })";
204f4cf51c9SYitzhak Mandelbaum BuildResult Result = BuildCFG(Code);
205f4cf51c9SYitzhak Mandelbaum ASSERT_EQ(BuildResult::BuiltCFG, Result.getStatus());
206f4cf51c9SYitzhak Mandelbaum
20726db5e65SYitzhak Mandelbaum auto Graph = partitionIntoIntervals(*Result.getCFG());
20826db5e65SYitzhak Mandelbaum EXPECT_THAT(
20926db5e65SYitzhak Mandelbaum Graph,
21026db5e65SYitzhak Mandelbaum ElementsAre(
21126db5e65SYitzhak Mandelbaum isInterval(0, IsEmpty(), UnorderedElementsAre(intervalID(1u))),
21226db5e65SYitzhak Mandelbaum isInterval(1, UnorderedElementsAre(intervalID(0u)), IsEmpty())));
213f4cf51c9SYitzhak Mandelbaum }
214f4cf51c9SYitzhak Mandelbaum
TEST(PartitionIntoIntervals,PartitionNestedWhileThreeIntervals)215f4cf51c9SYitzhak Mandelbaum TEST(PartitionIntoIntervals, PartitionNestedWhileThreeIntervals) {
216f4cf51c9SYitzhak Mandelbaum const char *Code = R"(void f() {
217f4cf51c9SYitzhak Mandelbaum int x = 3;
218f4cf51c9SYitzhak Mandelbaum while (x >= 3) {
219f4cf51c9SYitzhak Mandelbaum --x;
220f4cf51c9SYitzhak Mandelbaum int y = x;
221f4cf51c9SYitzhak Mandelbaum while (y > 0) --y;
222f4cf51c9SYitzhak Mandelbaum }
223f4cf51c9SYitzhak Mandelbaum x = x + x;
224f4cf51c9SYitzhak Mandelbaum })";
225f4cf51c9SYitzhak Mandelbaum BuildResult Result = BuildCFG(Code);
226f4cf51c9SYitzhak Mandelbaum ASSERT_EQ(BuildResult::BuiltCFG, Result.getStatus());
227f4cf51c9SYitzhak Mandelbaum
22826db5e65SYitzhak Mandelbaum auto Graph = partitionIntoIntervals(*Result.getCFG());
22926db5e65SYitzhak Mandelbaum EXPECT_THAT(
23026db5e65SYitzhak Mandelbaum Graph,
23126db5e65SYitzhak Mandelbaum ElementsAre(
23226db5e65SYitzhak Mandelbaum isInterval(0, IsEmpty(), UnorderedElementsAre(intervalID(1u))),
23326db5e65SYitzhak Mandelbaum isInterval(1, UnorderedElementsAre(intervalID(0u), intervalID(2u)),
23426db5e65SYitzhak Mandelbaum UnorderedElementsAre(intervalID(2u))),
23526db5e65SYitzhak Mandelbaum isInterval(2, UnorderedElementsAre(intervalID(1u)),
23626db5e65SYitzhak Mandelbaum UnorderedElementsAre(intervalID(1u)))));
237f4cf51c9SYitzhak Mandelbaum }
238f4cf51c9SYitzhak Mandelbaum
TEST(PartitionIntoIntervals,PartitionSequentialWhileThreeIntervals)239f4cf51c9SYitzhak Mandelbaum TEST(PartitionIntoIntervals, PartitionSequentialWhileThreeIntervals) {
240f4cf51c9SYitzhak Mandelbaum const char *Code = R"(void f() {
241f4cf51c9SYitzhak Mandelbaum int x = 3;
242f4cf51c9SYitzhak Mandelbaum while (x >= 3) {
243f4cf51c9SYitzhak Mandelbaum --x;
244f4cf51c9SYitzhak Mandelbaum }
245f4cf51c9SYitzhak Mandelbaum x = x + x;
246f4cf51c9SYitzhak Mandelbaum int y = x;
247f4cf51c9SYitzhak Mandelbaum while (y > 0) --y;
248f4cf51c9SYitzhak Mandelbaum })";
249f4cf51c9SYitzhak Mandelbaum BuildResult Result = BuildCFG(Code);
250f4cf51c9SYitzhak Mandelbaum ASSERT_EQ(BuildResult::BuiltCFG, Result.getStatus());
251f4cf51c9SYitzhak Mandelbaum
25226db5e65SYitzhak Mandelbaum auto Graph = partitionIntoIntervals(*Result.getCFG());
25326db5e65SYitzhak Mandelbaum EXPECT_THAT(
25426db5e65SYitzhak Mandelbaum Graph,
25526db5e65SYitzhak Mandelbaum ElementsAre(
25626db5e65SYitzhak Mandelbaum isInterval(0, IsEmpty(), UnorderedElementsAre(intervalID(1u))),
25726db5e65SYitzhak Mandelbaum isInterval(1, UnorderedElementsAre(intervalID(0u)),
25826db5e65SYitzhak Mandelbaum UnorderedElementsAre(intervalID(2u))),
25926db5e65SYitzhak Mandelbaum isInterval(2, UnorderedElementsAre(intervalID(1u)), IsEmpty())));
26026db5e65SYitzhak Mandelbaum }
26126db5e65SYitzhak Mandelbaum
TEST(PartitionIntoIntervals,LimitReducibleSequentialWhile)26226db5e65SYitzhak Mandelbaum TEST(PartitionIntoIntervals, LimitReducibleSequentialWhile) {
26326db5e65SYitzhak Mandelbaum const char *Code = R"(void f() {
26426db5e65SYitzhak Mandelbaum int x = 3;
26526db5e65SYitzhak Mandelbaum while (x >= 3) {
26626db5e65SYitzhak Mandelbaum --x;
26726db5e65SYitzhak Mandelbaum }
26826db5e65SYitzhak Mandelbaum x = x + x;
26926db5e65SYitzhak Mandelbaum int y = x;
27026db5e65SYitzhak Mandelbaum while (y > 0) --y;
27126db5e65SYitzhak Mandelbaum })";
27226db5e65SYitzhak Mandelbaum BuildResult Result = BuildCFG(Code);
27326db5e65SYitzhak Mandelbaum ASSERT_EQ(BuildResult::BuiltCFG, Result.getStatus());
27426db5e65SYitzhak Mandelbaum
27526db5e65SYitzhak Mandelbaum auto Graph = partitionIntoIntervals(*Result.getCFG());
27626db5e65SYitzhak Mandelbaum ASSERT_THAT(
27726db5e65SYitzhak Mandelbaum Graph,
27826db5e65SYitzhak Mandelbaum ElementsAre(isInterval(0, blockOrder(9, 8), IsEmpty(),
27926db5e65SYitzhak Mandelbaum UnorderedElementsAre(intervalID(1u))),
28026db5e65SYitzhak Mandelbaum isInterval(1, blockOrder(7, 6, 4, 5),
28126db5e65SYitzhak Mandelbaum UnorderedElementsAre(intervalID(0u)),
28226db5e65SYitzhak Mandelbaum UnorderedElementsAre(intervalID(2u))),
28326db5e65SYitzhak Mandelbaum isInterval(2, blockOrder(3, 2, 0, 1),
28426db5e65SYitzhak Mandelbaum UnorderedElementsAre(intervalID(1u)), IsEmpty())));
28526db5e65SYitzhak Mandelbaum
28626db5e65SYitzhak Mandelbaum auto Graph2 = partitionIntoIntervals(Graph);
28726db5e65SYitzhak Mandelbaum EXPECT_THAT(Graph2, ElementsAre(isInterval(
28826db5e65SYitzhak Mandelbaum 0, blockOrder(9, 8, 7, 6, 4, 5, 3, 2, 0, 1),
28926db5e65SYitzhak Mandelbaum IsEmpty(), IsEmpty())));
29026db5e65SYitzhak Mandelbaum }
29126db5e65SYitzhak Mandelbaum
TEST(PartitionIntoIntervals,LimitReducibleNestedWhile)29226db5e65SYitzhak Mandelbaum TEST(PartitionIntoIntervals, LimitReducibleNestedWhile) {
29326db5e65SYitzhak Mandelbaum const char *Code = R"(void f() {
29426db5e65SYitzhak Mandelbaum int x = 3;
29526db5e65SYitzhak Mandelbaum while (x >= 3) {
29626db5e65SYitzhak Mandelbaum --x;
29726db5e65SYitzhak Mandelbaum int y = x;
29826db5e65SYitzhak Mandelbaum while (y > 0) --y;
29926db5e65SYitzhak Mandelbaum }
30026db5e65SYitzhak Mandelbaum x = x + x;
30126db5e65SYitzhak Mandelbaum })";
30226db5e65SYitzhak Mandelbaum BuildResult Result = BuildCFG(Code);
30326db5e65SYitzhak Mandelbaum ASSERT_EQ(BuildResult::BuiltCFG, Result.getStatus());
30426db5e65SYitzhak Mandelbaum
30526db5e65SYitzhak Mandelbaum auto Graph = partitionIntoIntervals(*Result.getCFG());
30626db5e65SYitzhak Mandelbaum ASSERT_THAT(Graph,
30726db5e65SYitzhak Mandelbaum ElementsAre(isInterval(0, blockOrder(9, 8), IsEmpty(),
30826db5e65SYitzhak Mandelbaum UnorderedElementsAre(intervalID(1u))),
30926db5e65SYitzhak Mandelbaum isInterval(1, blockOrder(7, 6, 1, 0),
31026db5e65SYitzhak Mandelbaum UnorderedElementsAre(intervalID(0u),
31126db5e65SYitzhak Mandelbaum intervalID(2u)),
31226db5e65SYitzhak Mandelbaum UnorderedElementsAre(intervalID(2u))),
31326db5e65SYitzhak Mandelbaum isInterval(2, blockOrder(5, 4, 2, 3),
31426db5e65SYitzhak Mandelbaum UnorderedElementsAre(intervalID(1u)),
31526db5e65SYitzhak Mandelbaum UnorderedElementsAre(intervalID(1u)))));
31626db5e65SYitzhak Mandelbaum
31726db5e65SYitzhak Mandelbaum auto Graph2 = partitionIntoIntervals(Graph);
31826db5e65SYitzhak Mandelbaum EXPECT_THAT(
31926db5e65SYitzhak Mandelbaum Graph2,
32026db5e65SYitzhak Mandelbaum ElementsAre(isInterval(0, blockOrder(9, 8), IsEmpty(),
32126db5e65SYitzhak Mandelbaum UnorderedElementsAre(intervalID(1u))),
32226db5e65SYitzhak Mandelbaum isInterval(1, blockOrder(7, 6, 1, 0, 5, 4, 2, 3),
32326db5e65SYitzhak Mandelbaum UnorderedElementsAre(intervalID(0u)), IsEmpty())));
32426db5e65SYitzhak Mandelbaum
32526db5e65SYitzhak Mandelbaum auto Graph3 = partitionIntoIntervals(Graph2);
32626db5e65SYitzhak Mandelbaum EXPECT_THAT(Graph3, ElementsAre(isInterval(
32726db5e65SYitzhak Mandelbaum 0, blockOrder(9, 8, 7, 6, 1, 0, 5, 4, 2, 3),
32826db5e65SYitzhak Mandelbaum IsEmpty(), IsEmpty())));
32926db5e65SYitzhak Mandelbaum }
33026db5e65SYitzhak Mandelbaum
TEST(GetIntervalWTO,SequentialWhile)33126db5e65SYitzhak Mandelbaum TEST(GetIntervalWTO, SequentialWhile) {
33226db5e65SYitzhak Mandelbaum const char *Code = R"(void f() {
33326db5e65SYitzhak Mandelbaum int x = 3;
33426db5e65SYitzhak Mandelbaum while (x >= 3) {
33526db5e65SYitzhak Mandelbaum --x;
33626db5e65SYitzhak Mandelbaum }
33726db5e65SYitzhak Mandelbaum x = x + x;
33826db5e65SYitzhak Mandelbaum int y = x;
33926db5e65SYitzhak Mandelbaum while (y > 0) --y;
34026db5e65SYitzhak Mandelbaum })";
34126db5e65SYitzhak Mandelbaum BuildResult Result = BuildCFG(Code);
34226db5e65SYitzhak Mandelbaum ASSERT_EQ(BuildResult::BuiltCFG, Result.getStatus());
34326db5e65SYitzhak Mandelbaum EXPECT_THAT(getIntervalWTO(*Result.getCFG()),
34426db5e65SYitzhak Mandelbaum Optional(blockOrder(9, 8, 7, 6, 4, 5, 3, 2, 0, 1)));
34526db5e65SYitzhak Mandelbaum }
34626db5e65SYitzhak Mandelbaum
TEST(GetIntervalWTO,NestedWhile)34726db5e65SYitzhak Mandelbaum TEST(GetIntervalWTO, NestedWhile) {
34826db5e65SYitzhak Mandelbaum const char *Code = R"(void f() {
34926db5e65SYitzhak Mandelbaum int x = 3;
35026db5e65SYitzhak Mandelbaum while (x >= 3) {
35126db5e65SYitzhak Mandelbaum --x;
35226db5e65SYitzhak Mandelbaum int y = x;
35326db5e65SYitzhak Mandelbaum while (y > 0) --y;
35426db5e65SYitzhak Mandelbaum }
35526db5e65SYitzhak Mandelbaum x = x + x;
35626db5e65SYitzhak Mandelbaum })";
35726db5e65SYitzhak Mandelbaum BuildResult Result = BuildCFG(Code);
35826db5e65SYitzhak Mandelbaum ASSERT_EQ(BuildResult::BuiltCFG, Result.getStatus());
35926db5e65SYitzhak Mandelbaum EXPECT_THAT(getIntervalWTO(*Result.getCFG()),
36026db5e65SYitzhak Mandelbaum Optional(blockOrder(9, 8, 7, 6, 1, 0, 5, 4, 2, 3)));
361f4cf51c9SYitzhak Mandelbaum }
362f4cf51c9SYitzhak Mandelbaum
TEST(GetIntervalWTO,UnreachablePred)363*e21b1dd9SYitzhak Mandelbaum TEST(GetIntervalWTO, UnreachablePred) {
364*e21b1dd9SYitzhak Mandelbaum const char *Code = R"(
365*e21b1dd9SYitzhak Mandelbaum void target(bool Foo) {
366*e21b1dd9SYitzhak Mandelbaum bool Bar = false;
367*e21b1dd9SYitzhak Mandelbaum if (Foo)
368*e21b1dd9SYitzhak Mandelbaum Bar = Foo;
369*e21b1dd9SYitzhak Mandelbaum else
370*e21b1dd9SYitzhak Mandelbaum __builtin_unreachable();
371*e21b1dd9SYitzhak Mandelbaum (void)0;
372*e21b1dd9SYitzhak Mandelbaum })";
373*e21b1dd9SYitzhak Mandelbaum BuildResult Result = BuildCFG(Code);
374*e21b1dd9SYitzhak Mandelbaum ASSERT_EQ(BuildResult::BuiltCFG, Result.getStatus());
375*e21b1dd9SYitzhak Mandelbaum EXPECT_THAT(getIntervalWTO(*Result.getCFG()),
376*e21b1dd9SYitzhak Mandelbaum Optional(blockOrder(5, 4, 3, 2, 1, 0)));
377*e21b1dd9SYitzhak Mandelbaum }
378*e21b1dd9SYitzhak Mandelbaum
TEST(WTOCompare,UnreachableBlock)379*e21b1dd9SYitzhak Mandelbaum TEST(WTOCompare, UnreachableBlock) {
380*e21b1dd9SYitzhak Mandelbaum const char *Code = R"(
381*e21b1dd9SYitzhak Mandelbaum void target() {
382*e21b1dd9SYitzhak Mandelbaum while (true) {}
383*e21b1dd9SYitzhak Mandelbaum (void)0;
384*e21b1dd9SYitzhak Mandelbaum /*[[p]]*/
385*e21b1dd9SYitzhak Mandelbaum })";
386*e21b1dd9SYitzhak Mandelbaum BuildResult Result = BuildCFG(Code);
387*e21b1dd9SYitzhak Mandelbaum ASSERT_EQ(BuildResult::BuiltCFG, Result.getStatus());
388*e21b1dd9SYitzhak Mandelbaum std::optional<WeakTopologicalOrdering> WTO = getIntervalWTO(*Result.getCFG());
389*e21b1dd9SYitzhak Mandelbaum ASSERT_THAT(WTO, Optional(blockOrder(4, 3, 2)));
390*e21b1dd9SYitzhak Mandelbaum auto Cmp = WTOCompare(*WTO);
391*e21b1dd9SYitzhak Mandelbaum const CFGBlock &Entry = Result.getCFG()->getEntry();
392*e21b1dd9SYitzhak Mandelbaum const CFGBlock &Exit = Result.getCFG()->getExit();
393*e21b1dd9SYitzhak Mandelbaum EXPECT_TRUE(Cmp(&Entry, &Exit));
394*e21b1dd9SYitzhak Mandelbaum }
395*e21b1dd9SYitzhak Mandelbaum
396f4cf51c9SYitzhak Mandelbaum } // namespace
397f4cf51c9SYitzhak Mandelbaum } // namespace clang
398