xref: /llvm-project/clang/unittests/Analysis/IntervalPartitionTest.cpp (revision e21b1dd9cc5316c00216ba54f899f67fe473ab33)
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