• 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 <algorithm>
17 #include <vector>
18 #include "unit_test.h"
19 
20 namespace panda::compiler {
21 class IteratorsTest : public GraphTest {
22 public:
23     static constexpr size_t INST_COUNT = 10;
24 
25 public:
Check(std::vector<Inst * > & tested_instructions)26     void Check(std::vector<Inst *> &tested_instructions)
27     {
28         auto block = &BB(0);
29         PopulateBlock(block, tested_instructions);
30         InitExpectData(tested_instructions);
31 
32         // Check InstForwardIterator
33         std::vector<Inst *> result;
34         for (auto inst : block->PhiInsts()) {
35             result.push_back(inst);
36         }
37         EXPECT_EQ(result, expect_phis_);
38 
39         result.clear();
40         for (auto inst : block->Insts()) {
41             result.push_back(inst);
42         }
43         EXPECT_EQ(result, expect_insts_);
44 
45         result.clear();
46         for (auto inst : block->AllInsts()) {
47             result.push_back(inst);
48         }
49         EXPECT_EQ(result, expect_all_);
50 
51         // Check InstForwardValidIterator
52         result.clear();
53         for (auto inst : block->PhiInstsSafe()) {
54             result.push_back(inst);
55         }
56         EXPECT_EQ(result, expect_phis_);
57 
58         result.clear();
59         for (auto inst : block->InstsSafe()) {
60             result.push_back(inst);
61         }
62         EXPECT_EQ(result, expect_insts_);
63 
64         result.clear();
65         for (auto inst : block->AllInstsSafe()) {
66             result.push_back(inst);
67         }
68         EXPECT_EQ(result, expect_all_);
69 
70         // Check InstBackwardValidIterator
71         result.clear();
72         for (auto inst : block->PhiInstsSafeReverse()) {
73             result.push_back(inst);
74         }
75         std::reverse(result.begin(), result.end());
76         EXPECT_EQ(result, expect_phis_);
77 
78         result.clear();
79         for (auto inst : block->InstsSafeReverse()) {
80             result.push_back(inst);
81         }
82         std::reverse(result.begin(), result.end());
83         EXPECT_EQ(result, expect_insts_);
84 
85         result.clear();
86         for (auto inst : block->AllInstsSafeReverse()) {
87             result.push_back(inst);
88         }
89         std::reverse(result.begin(), result.end());
90         EXPECT_EQ(result, expect_all_);
91 
92         // Check InstForwardValidIterator with erasing instructions
93         result.clear();
94         for (auto inst : block->PhiInstsSafe()) {
95             result.push_back(inst);
96             block->EraseInst(inst);
97         }
98         EXPECT_EQ(result, expect_phis_);
99 
100         result.clear();
101         for (auto inst : block->InstsSafe()) {
102             result.push_back(inst);
103             block->EraseInst(inst);
104         }
105         EXPECT_EQ(result, expect_insts_);
106 
107         result.clear();
108         for (auto inst : block->AllInstsSafe()) {
109             result.push_back(inst);
110         }
111         EXPECT_EQ(result.size(), 0U);
112 
113         PopulateBlock(block, tested_instructions);
114         for (auto inst : block->AllInstsSafe()) {
115             result.push_back(inst);
116             block->EraseInst(inst);
117         }
118         EXPECT_EQ(result, expect_all_);
119 
120         // Check InstBackwardValidIterator with erasing instructions
121         PopulateBlock(block, tested_instructions);
122         result.clear();
123         for (auto inst : block->PhiInstsSafeReverse()) {
124             result.push_back(inst);
125             block->EraseInst(inst);
126         }
127         std::reverse(result.begin(), result.end());
128         EXPECT_EQ(result, expect_phis_);
129 
130         result.clear();
131         for (auto inst : block->InstsSafeReverse()) {
132             result.push_back(inst);
133             block->EraseInst(inst);
134         }
135         std::reverse(result.begin(), result.end());
136         EXPECT_EQ(result, expect_insts_);
137 
138         result.clear();
139         for (auto inst : block->AllInstsSafeReverse()) {
140             result.push_back(inst);
141         }
142         EXPECT_EQ(result.size(), 0U);
143 
144         PopulateBlock(block, tested_instructions);
145         for (auto inst : block->AllInstsSafeReverse()) {
146             result.push_back(inst);
147             block->EraseInst(inst);
148         }
149         std::reverse(result.begin(), result.end());
150         EXPECT_EQ(result, expect_all_);
151     }
152 
153 private:
InitExpectData(std::vector<Inst * > & instructions)154     void InitExpectData(std::vector<Inst *> &instructions)
155     {
156         expect_phis_.clear();
157         expect_insts_.clear();
158         expect_all_.clear();
159 
160         for (auto inst : instructions) {
161             if (inst->IsPhi()) {
162                 expect_phis_.push_back(inst);
163             } else {
164                 expect_insts_.push_back(inst);
165             }
166         }
167         expect_all_.insert(expect_all_.end(), expect_phis_.begin(), expect_phis_.end());
168         expect_all_.insert(expect_all_.end(), expect_insts_.begin(), expect_insts_.end());
169     }
170 
PopulateBlock(BasicBlock * block,std::vector<Inst * > & instructions)171     void PopulateBlock(BasicBlock *block, std::vector<Inst *> &instructions)
172     {
173         for (auto inst : instructions) {
174             if (inst->IsPhi()) {
175                 block->AppendPhi(inst);
176             } else {
177                 block->AppendInst(inst);
178             }
179         }
180     }
181 
182 private:
183     std::vector<Inst *> expect_phis_;
184     std::vector<Inst *> expect_insts_;
185     std::vector<Inst *> expect_all_;
186 };
187 
TEST_F(IteratorsTest,EmptyBlock)188 TEST_F(IteratorsTest, EmptyBlock)
189 {
190     GRAPH(GetGraph())
191     {
192         BASIC_BLOCK(2, -1)
193         {
194             INST(0, Opcode::ReturnVoid);
195         }
196     }
197     std::vector<Inst *> instructions;
198     Check(instructions);
199 }
200 
TEST_F(IteratorsTest,BlockPhisInstructions)201 TEST_F(IteratorsTest, BlockPhisInstructions)
202 {
203     GRAPH(GetGraph())
204     {
205         BASIC_BLOCK(2, -1)
206         {
207             INST(0, Opcode::ReturnVoid);
208         }
209     }
210     std::vector<Inst *> instructions(IteratorsTest::INST_COUNT);
211     for (auto &inst : instructions) {
212         inst = GetGraph()->CreateInst(Opcode::Phi);
213     }
214     Check(instructions);
215 }
216 
TEST_F(IteratorsTest,BlockNotPhisInstructions)217 TEST_F(IteratorsTest, BlockNotPhisInstructions)
218 {
219     GRAPH(GetGraph())
220     {
221         BASIC_BLOCK(2, -1)
222         {
223             INST(0, Opcode::ReturnVoid);
224         }
225     }
226     std::vector<Inst *> instructions(IteratorsTest::INST_COUNT);
227     for (auto &inst : instructions) {
228         inst = GetGraph()->CreateInst(Opcode::Add);
229     }
230     Check(instructions);
231 }
232 
TEST_F(IteratorsTest,BlockAllInstructions)233 TEST_F(IteratorsTest, BlockAllInstructions)
234 {
235     GRAPH(GetGraph())
236     {
237         BASIC_BLOCK(2, -1)
238         {
239             INST(0, Opcode::ReturnVoid);
240         }
241     }
242     std::vector<Inst *> instructions(IteratorsTest::INST_COUNT);
243 
244     // first instruction is phi
245     size_t i = 0;
246     for (auto &inst : instructions) {
247         if (++i % 2) {
248             inst = GetGraph()->CreateInst(Opcode::Phi);
249         } else {
250             inst = GetGraph()->CreateInst(Opcode::Add);
251         }
252     }
253     Check(instructions);
254     // first instruction is not phi
255     i = 1;
256     for (auto &inst : instructions) {
257         if (++i % 2) {
258             inst = GetGraph()->CreateInst(Opcode::Phi);
259         } else {
260             inst = GetGraph()->CreateInst(Opcode::Add);
261         }
262     }
263     Check(instructions);
264 
265     // first instructions are phi
266     i = 0;
267     for (auto &inst : instructions) {
268         if (i < IteratorsTest::INST_COUNT / 2) {
269             inst = GetGraph()->CreateInst(Opcode::Phi);
270         } else {
271             inst = GetGraph()->CreateInst(Opcode::Add);
272         }
273     }
274     Check(instructions);
275 
276     // first instructions are not phi
277     i = 0;
278     for (auto &inst : instructions) {
279         if (i >= IteratorsTest::INST_COUNT / 2) {
280             inst = GetGraph()->CreateInst(Opcode::Phi);
281         } else {
282             inst = GetGraph()->CreateInst(Opcode::Add);
283         }
284     }
285     Check(instructions);
286 }
287 }  // namespace panda::compiler
288