• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "unit_test.h"
17 #include "optimizer/analysis/liveness_analyzer.h"
18 
19 namespace panda::compiler {
20 class LifeIntervalsTest : public CommonTest {
21 public:
LifeIntervalsTest()22     LifeIntervalsTest() : graph_(CreateEmptyGraph()) {}
23 
Create(std::initializer_list<std::pair<LifeNumber,LifeNumber>> lns)24     LifeIntervals *Create(std::initializer_list<std::pair<LifeNumber, LifeNumber>> lns)
25     {
26         auto inst = graph_->CreateInstConstant(42);
27         auto li = GetAllocator()->New<LifeIntervals>(GetAllocator(), inst);
28         for (auto range = std::rbegin(lns); range != std::rend(lns); range++) {
29             li->AppendRange(range->first, range->second);
30         }
31         return li;
32     }
33 
CheckSiblings(std::initializer_list<LifeIntervals * > intervals)34     void CheckSiblings(std::initializer_list<LifeIntervals *> intervals)
35     {
36         if (intervals.size() == 0) {
37             return;
38         }
39         for (auto it = std::begin(intervals); it != std::end(intervals); it++) {
40             auto next = std::next(it);
41             if (next == std::end(intervals)) {
42                 ASSERT_EQ((*it)->GetSibling(), nullptr);
43             } else {
44                 ASSERT_EQ((*it)->GetSibling(), *next);
45             }
46         }
47     }
48 
CheckRanges(LifeIntervals * interval,std::initializer_list<std::pair<LifeNumber,LifeNumber>> ranges)49     void CheckRanges(LifeIntervals *interval, std::initializer_list<std::pair<LifeNumber, LifeNumber>> ranges)
50     {
51         ASSERT(interval != nullptr);
52         auto li_ranges = interval->GetRanges();
53         ASSERT_EQ(li_ranges.size(), ranges.size());
54 
55         auto actual_it = li_ranges.begin();
56         auto expected_it = std::begin(ranges);
57         while (actual_it != li_ranges.end() && expected_it != std::end(ranges)) {
58             auto actual_range = *(actual_it++);
59             auto expected_lns = *(expected_it++);
60             ASSERT_EQ(actual_range.GetBegin(), expected_lns.first);
61             ASSERT_EQ(actual_range.GetEnd(), expected_lns.second);
62         }
63     }
64 
65 private:
66     Graph *graph_;
67 };
68 
TEST_F(LifeIntervalsTest,SplitAtTheEnd)69 TEST_F(LifeIntervalsTest, SplitAtTheEnd)
70 {
71     auto interval = Create({{0, 4}});
72     auto split = interval->SplitAt(4, GetAllocator());
73 
74     CheckSiblings({interval, split});
75     CheckRanges(interval, {{0, 4}});
76     CheckRanges(split, {});
77 }
78 
TEST_F(LifeIntervalsTest,SplitBetweenRanges)79 TEST_F(LifeIntervalsTest, SplitBetweenRanges)
80 {
81     auto interval = Create({{0, 4}, {8, 10}});
82     auto split = interval->SplitAt(6, GetAllocator());
83 
84     CheckSiblings({interval, split});
85     CheckRanges(interval, {{0, 4}});
86     CheckRanges(split, {{8, 10}});
87 }
88 
TEST_F(LifeIntervalsTest,SplitRange)89 TEST_F(LifeIntervalsTest, SplitRange)
90 {
91     auto interval = Create({{0, 10}});
92     auto split = interval->SplitAt(6, GetAllocator());
93 
94     CheckSiblings({interval, split});
95     CheckRanges(interval, {{0, 6}});
96     CheckRanges(split, {{6, 10}});
97 }
98 
TEST_F(LifeIntervalsTest,SplitIntervalWithMultipleRanges)99 TEST_F(LifeIntervalsTest, SplitIntervalWithMultipleRanges)
100 {
101     auto interval = Create({{0, 4}, {6, 10}, {12, 20}});
102     auto split = interval->SplitAt(8, GetAllocator());
103 
104     CheckSiblings({interval, split});
105     CheckRanges(interval, {{0, 4}, {6, 8}});
106     CheckRanges(split, {{8, 10}, {12, 20}});
107 }
108 
TEST_F(LifeIntervalsTest,RecursiveSplits)109 TEST_F(LifeIntervalsTest, RecursiveSplits)
110 {
111     auto interval = Create({{0, 100}});
112     auto split0 = interval->SplitAt(50, GetAllocator());
113     auto split1 = split0->SplitAt(75, GetAllocator());
114     auto split2 = interval->SplitAt(25, GetAllocator());
115 
116     CheckSiblings({interval, split2, split0, split1});
117     CheckRanges(interval, {{0, 25}});
118     CheckRanges(split2, {{25, 50}});
119     CheckRanges(split0, {{50, 75}});
120     CheckRanges(split1, {{75, 100}});
121 }
122 
TEST_F(LifeIntervalsTest,IntervalsCoverage)123 TEST_F(LifeIntervalsTest, IntervalsCoverage)
124 {
125     auto interval = Create({{0, 20}, {22, 40}, {42, 100}});
126     auto split0 = interval->SplitAt(21, GetAllocator());
127     auto split1 = split0->SplitAt(50, GetAllocator());
128 
129     EXPECT_TRUE(interval->SplitCover(18));
130     EXPECT_FALSE(split0->SplitCover(18));
131     EXPECT_FALSE(split1->SplitCover(18));
132 
133     EXPECT_FALSE(interval->SplitCover(42));
134     EXPECT_TRUE(split0->SplitCover(42));
135     EXPECT_FALSE(split1->SplitCover(42));
136 }
137 
TEST_F(LifeIntervalsTest,FindSiblingAt)138 TEST_F(LifeIntervalsTest, FindSiblingAt)
139 {
140     auto interval = Create({{0, 20}, {22, 40}, {42, 100}});
141     auto split0 = interval->SplitAt(22, GetAllocator());
142     auto split1 = split0->SplitAt(50, GetAllocator());
143 
144     EXPECT_EQ(interval->FindSiblingAt(0), interval);
145     EXPECT_EQ(interval->FindSiblingAt(20), interval);
146     EXPECT_EQ(interval->FindSiblingAt(39), split0);
147     EXPECT_EQ(interval->FindSiblingAt(51), split1);
148     EXPECT_EQ(interval->FindSiblingAt(21), nullptr);
149 }
150 
TEST_F(LifeIntervalsTest,Intersects)151 TEST_F(LifeIntervalsTest, Intersects)
152 {
153     auto interval = Create({{6, 10}});
154 
155     EXPECT_TRUE(interval->Intersects(LiveRange(0, 20)));
156     EXPECT_TRUE(interval->Intersects(LiveRange(6, 10)));
157     EXPECT_TRUE(interval->Intersects(LiveRange(0, 8)));
158     EXPECT_TRUE(interval->Intersects(LiveRange(8, 20)));
159     EXPECT_TRUE(interval->Intersects(LiveRange(7, 9)));
160 
161     EXPECT_FALSE(interval->Intersects(LiveRange(0, 4)));
162     EXPECT_FALSE(interval->Intersects(LiveRange(12, 20)));
163 }
164 
TEST_F(LifeIntervalsTest,IsSameLocation)165 TEST_F(LifeIntervalsTest, IsSameLocation)
166 {
167     auto graph = CreateEmptyGraph();
168     GRAPH(graph)
169     {
170         CONSTANT(0, 0);
171         CONSTANT(1, 42);
172 
173         BASIC_BLOCK(2, -1)
174         {
175             INST(2, Opcode::Add).u64().Inputs(0, 1);
176             INST(3, Opcode::Return).u64().Inputs(2);
177         }
178     };
179 
180     auto con0 = &INS(0);
181     auto con42 = &INS(1);
182     auto add = &INS(2);
183 
184     std::vector<std::function<LifeIntervals *()>> factories = {
185         [&]() {
186             auto li = GetAllocator()->New<LifeIntervals>(GetAllocator(), add);
187             li->SetReg(0);
188             return li;
189         },
190         [&]() {
191             auto li = GetAllocator()->New<LifeIntervals>(GetAllocator(), add);
192             li->SetReg(1);
193             return li;
194         },
195         [&]() {
196             auto li = GetAllocator()->New<LifeIntervals>(GetAllocator(), add);
197             li->SetLocation(Location::MakeStackSlot(1));
198             return li;
199         },
200         [&]() {
201             auto li = GetAllocator()->New<LifeIntervals>(GetAllocator(), add);
202             li->SetLocation(Location::MakeStackSlot(2));
203             return li;
204         },
205         [&]() {
206             auto li = GetAllocator()->New<LifeIntervals>(GetAllocator(), con42);
207             li->SetLocation(Location::MakeConstant(0));
208             return li;
209         },
210         [&]() {
211             auto li = GetAllocator()->New<LifeIntervals>(GetAllocator(), con42);
212             li->SetLocation(Location::MakeConstant(1));
213             return li;
214         },
215         [&]() {
216             auto li = GetAllocator()->New<LifeIntervals>(GetAllocator(), con0);
217             if (graph->GetZeroReg() == INVALID_REG) {
218                 ASSERT(graph->GetArch() != Arch::AARCH64);
219                 li->SetReg(31);
220             } else {
221                 li->SetReg(graph->GetZeroReg());
222             }
223             return li;
224         }};
225 
226     for (size_t l1_idx = 0; l1_idx < factories.size(); l1_idx++) {
227         auto interval0 = factories[l1_idx]();
228         for (size_t l2_idx = 0; l2_idx < factories.size(); l2_idx++) {
229             auto interval1 = factories[l2_idx]();
230             bool same_settings = l1_idx == l2_idx;
231             EXPECT_EQ(same_settings, interval0->GetLocation() == interval1->GetLocation());
232         }
233     }
234 }
235 
TEST_F(LifeIntervalsTest,LastUsageBefore)236 TEST_F(LifeIntervalsTest, LastUsageBefore)
237 {
238     auto interval = Create({{10, 100}});
239 
240     ASSERT_EQ(INVALID_LIFE_NUMBER, interval->GetLastUsageBefore(100));
241 
242     interval->AddUsePosition(12);
243     interval->AddUsePosition(50);
244     interval->AddUsePosition(60);
245 
246     ASSERT_EQ(INVALID_LIFE_NUMBER, interval->GetLastUsageBefore(12));
247     ASSERT_EQ(12, interval->GetLastUsageBefore(13));
248     ASSERT_EQ(60, interval->GetLastUsageBefore(100));
249 }
250 
251 }  // namespace panda::compiler
252