xref: /llvm-project/clang/unittests/Analysis/IntervalPartitionTest.cpp (revision f4cf51c99c74f46a490e0ae265da8fba298d800b)
1 //===- unittests/Analysis/IntervalPartitionTest.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 "clang/Analysis/Analyses/IntervalPartition.h"
10 #include "CFGBuildResult.h"
11 #include "gmock/gmock.h"
12 #include "gtest/gtest.h"
13 
14 namespace clang {
15 namespace analysis {
16 namespace {
17 
18 TEST(BuildInterval, PartitionSimpleOneInterval) {
19 
20   const char *Code = R"(void f() {
21                           int x = 3;
22                           int y = 7;
23                           x = y + x;
24                         })";
25   BuildResult Result = BuildCFG(Code);
26   EXPECT_EQ(BuildResult::BuiltCFG, Result.getStatus());
27 
28   CFG *cfg = Result.getCFG();
29 
30   // Basic correctness checks.
31   ASSERT_EQ(cfg->size(), 3u);
32 
33   auto &EntryBlock = cfg->getEntry();
34 
35   CFGInterval I = buildInterval(*cfg, EntryBlock);
36   EXPECT_EQ(I.Blocks.size(), 3u);
37 }
38 
39 TEST(BuildInterval, PartitionIfThenOneInterval) {
40 
41   const char *Code = R"(void f() {
42                           int x = 3;
43                           if (x > 3)
44                             x = 2;
45                           else
46                             x = 7;
47                           x = x + x;
48                         })";
49   BuildResult Result = BuildCFG(Code);
50   EXPECT_EQ(BuildResult::BuiltCFG, Result.getStatus());
51 
52   CFG *cfg = Result.getCFG();
53 
54   // Basic correctness checks.
55   ASSERT_EQ(cfg->size(), 6u);
56 
57   auto &EntryBlock = cfg->getEntry();
58 
59   CFGInterval I = buildInterval(*cfg, EntryBlock);
60   EXPECT_EQ(I.Blocks.size(), 6u);
61 }
62 
63 using ::testing::UnorderedElementsAre;
64 
65 TEST(BuildInterval, PartitionWhileMultipleIntervals) {
66 
67   const char *Code = R"(void f() {
68                           int x = 3;
69                           while (x >= 3)
70                             --x;
71                           x = x + x;
72                         })";
73   BuildResult Result = BuildCFG(Code);
74   ASSERT_EQ(BuildResult::BuiltCFG, Result.getStatus());
75 
76   CFG *cfg = Result.getCFG();
77   ASSERT_EQ(cfg->size(), 7u);
78 
79   auto *EntryBlock = &cfg->getEntry();
80   CFGBlock *InitXBlock = *EntryBlock->succ_begin();
81   CFGBlock *LoopHeadBlock = *InitXBlock->succ_begin();
82 
83   CFGInterval I1 = buildInterval(*cfg, *EntryBlock);
84   EXPECT_THAT(I1.Blocks, UnorderedElementsAre(EntryBlock, InitXBlock));
85 
86   CFGInterval I2 = buildInterval(*cfg, *LoopHeadBlock);
87   EXPECT_EQ(I2.Blocks.size(), 5u);
88 }
89 
90 TEST(PartitionIntoIntervals, PartitionIfThenOneInterval) {
91   const char *Code = R"(void f() {
92                           int x = 3;
93                           if (x > 3)
94                             x = 2;
95                           else
96                             x = 7;
97                           x = x + x;
98                         })";
99   BuildResult Result = BuildCFG(Code);
100   ASSERT_EQ(BuildResult::BuiltCFG, Result.getStatus());
101 
102   CFG *cfg = Result.getCFG();
103   ASSERT_EQ(cfg->size(), 6u);
104 
105   auto Intervals = partitionIntoIntervals(*cfg);
106   EXPECT_EQ(Intervals.size(), 1u);
107 }
108 
109 TEST(PartitionIntoIntervals, PartitionWhileTwoIntervals) {
110   const char *Code = R"(void f() {
111                           int x = 3;
112                           while (x >= 3)
113                             --x;
114                           x = x + x;
115                         })";
116   BuildResult Result = BuildCFG(Code);
117   ASSERT_EQ(BuildResult::BuiltCFG, Result.getStatus());
118 
119   CFG *cfg = Result.getCFG();
120   ASSERT_EQ(cfg->size(), 7u);
121 
122   auto Intervals = partitionIntoIntervals(*cfg);
123   EXPECT_EQ(Intervals.size(), 2u);
124 }
125 
126 TEST(PartitionIntoIntervals, PartitionNestedWhileThreeIntervals) {
127   const char *Code = R"(void f() {
128                           int x = 3;
129                           while (x >= 3) {
130                             --x;
131                             int y = x;
132                             while (y > 0) --y;
133                           }
134                           x = x + x;
135                         })";
136   BuildResult Result = BuildCFG(Code);
137   ASSERT_EQ(BuildResult::BuiltCFG, Result.getStatus());
138 
139   CFG *cfg = Result.getCFG();
140   auto Intervals = partitionIntoIntervals(*cfg);
141   EXPECT_EQ(Intervals.size(), 3u);
142 }
143 
144 TEST(PartitionIntoIntervals, PartitionSequentialWhileThreeIntervals) {
145   const char *Code = R"(void f() {
146                           int x = 3;
147                           while (x >= 3) {
148                             --x;
149                           }
150                           x = x + x;
151                           int y = x;
152                           while (y > 0) --y;
153                         })";
154   BuildResult Result = BuildCFG(Code);
155   ASSERT_EQ(BuildResult::BuiltCFG, Result.getStatus());
156 
157   CFG *cfg = Result.getCFG();
158   auto Intervals = partitionIntoIntervals(*cfg);
159   EXPECT_EQ(Intervals.size(), 3u);
160 }
161 
162 } // namespace
163 } // namespace analysis
164 } // namespace clang
165