• 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/optimizations/adjust_arefs.h"
18 
19 namespace panda::compiler {
20 class AdjustRefsTest : public GraphTest {
21 public:
AdjustRefsTest()22     AdjustRefsTest() {}
23 };
24 
25 /* One block, continuous chain */
TEST_F(AdjustRefsTest,OneBlockContinuousChain)26 TEST_F(AdjustRefsTest, OneBlockContinuousChain)
27 {
28     auto graph = CreateEmptyFastpathGraph(RUNTIME_ARCH);
29 #ifndef NDEBUG
30     graph->SetLowLevelInstructionsEnabled();
31 #endif
32     GRAPH(graph)
33     {
34         PARAMETER(0, 0).ref();
35         PARAMETER(1, 1).s32();
36         PARAMETER(2, 2).u64();
37         CONSTANT(3, 10).s32();
38 
39         BASIC_BLOCK(3, 4, 5)
40         {
41             INST(10, Opcode::Phi).s32().Inputs(1, 40);
42             INST(11, Opcode::LoadArray).u64().Inputs(0, 1);
43             INST(12, Opcode::LoadArray).u64().Inputs(0, 1);
44             INST(13, Opcode::StoreArray).u64().Inputs(0, 1, 2);
45             INST(14, Opcode::StoreArray).u64().Inputs(0, 1, 2);
46             INST(15, Opcode::Compare).b().Inputs(10, 1);
47             INST(19, Opcode::IfImm).CC(CC_NE).Inputs(15).Imm(0);
48         }
49         BASIC_BLOCK(4, 3)
50         {
51             INST(40, Opcode::Add).s32().Inputs(10, 3);
52         }
53         BASIC_BLOCK(5, 1)
54         {
55             INST(50, Opcode::ReturnVoid);
56         }
57     }
58 
59     Graph *graph_et = CreateEmptyFastpathGraph(RUNTIME_ARCH);
60     GRAPH(graph_et)
61     {
62         PARAMETER(0, 0).ref();
63         PARAMETER(1, 1).s32();
64         PARAMETER(2, 2).u64();
65         CONSTANT(3, 10).s32();
66 
67         BASIC_BLOCK(3, 4, 5)
68         {
69             INST(10, Opcode::Phi).s32().Inputs(1, 40);
70             INST(11, Opcode::AddI).ptr().Inputs(0).Imm(graph->GetRuntime()->GetArrayDataOffset(graph->GetArch()));
71             INST(12, Opcode::Load).u64().Inputs(11, 1);
72             INST(13, Opcode::Load).u64().Inputs(11, 1);
73             INST(14, Opcode::Store).u64().Inputs(11, 1, 2);
74             INST(15, Opcode::Store).u64().Inputs(11, 1, 2);
75             INST(16, Opcode::Compare).b().Inputs(10, 1);
76             INST(19, Opcode::IfImm).CC(CC_NE).Inputs(16).Imm(0);
77         }
78 
79         BASIC_BLOCK(4, 3)
80         {
81             INST(40, Opcode::Add).s32().Inputs(10, 3);
82         }
83         BASIC_BLOCK(5, 1)
84         {
85             INST(50, Opcode::ReturnVoid);
86         }
87     }
88 
89     ASSERT_TRUE(graph->RunPass<AdjustRefs>());
90 
91     GraphChecker(graph).Check();
92     ASSERT_TRUE(GraphComparator().Compare(graph, graph_et));
93 }
94 
95 /* One block, broken chain */
TEST_F(AdjustRefsTest,OneBlockBrokenChain)96 TEST_F(AdjustRefsTest, OneBlockBrokenChain)
97 {
98     auto graph = CreateEmptyFastpathGraph(RUNTIME_ARCH);
99 #ifndef NDEBUG
100     graph->SetLowLevelInstructionsEnabled();
101 #endif
102     GRAPH(graph)
103     {
104         PARAMETER(0, 0).ref();
105         PARAMETER(1, 1).s32();
106         PARAMETER(2, 2).u64();
107         CONSTANT(3, 10).s32();
108 
109         BASIC_BLOCK(3, 4, 5)
110         {
111             INST(10, Opcode::Phi).s32().Inputs(1, 40);
112             INST(11, Opcode::LoadArray).u64().Inputs(0, 1);
113             INST(12, Opcode::LoadArray).u64().Inputs(0, 1);
114             INST(13, Opcode::SafePoint).NoVregs();
115             INST(14, Opcode::StoreArray).u64().Inputs(0, 1, 2);
116             INST(15, Opcode::StoreArray).u64().Inputs(0, 1, 2);
117             INST(16, Opcode::Compare).b().Inputs(10, 1);
118             INST(19, Opcode::IfImm).CC(CC_NE).Inputs(16).Imm(0);
119         }
120         BASIC_BLOCK(4, 3)
121         {
122             INST(40, Opcode::Add).s32().Inputs(10, 3);
123         }
124         BASIC_BLOCK(5, 1)
125         {
126             INST(50, Opcode::ReturnVoid);
127         }
128     }
129 
130     Graph *graph_et = CreateEmptyFastpathGraph(RUNTIME_ARCH);
131     GRAPH(graph_et)
132     {
133         PARAMETER(0, 0).ref();
134         PARAMETER(1, 1).s32();
135         PARAMETER(2, 2).u64();
136         CONSTANT(3, 10).s32();
137 
138         BASIC_BLOCK(3, 4, 5)
139         {
140             INST(10, Opcode::Phi).s32().Inputs(1, 40);
141             INST(11, Opcode::AddI).ptr().Inputs(0).Imm(graph->GetRuntime()->GetArrayDataOffset(graph->GetArch()));
142             INST(12, Opcode::Load).u64().Inputs(11, 1);
143             INST(13, Opcode::Load).u64().Inputs(11, 1);
144 
145             INST(14, Opcode::SafePoint).NoVregs();
146 
147             INST(15, Opcode::AddI).ptr().Inputs(0).Imm(graph->GetRuntime()->GetArrayDataOffset(graph->GetArch()));
148             INST(16, Opcode::Store).u64().Inputs(15, 1, 2);
149             INST(17, Opcode::Store).u64().Inputs(15, 1, 2);
150 
151             INST(18, Opcode::Compare).b().Inputs(10, 1);
152             INST(19, Opcode::IfImm).CC(CC_NE).Inputs(18).Imm(0);
153         }
154 
155         BASIC_BLOCK(4, 3)
156         {
157             INST(40, Opcode::Add).s32().Inputs(10, 3);
158         }
159         BASIC_BLOCK(5, 1)
160         {
161             INST(50, Opcode::ReturnVoid);
162         }
163     }
164 
165     ASSERT_TRUE(graph->RunPass<AdjustRefs>());
166 
167     GraphChecker(graph).Check();
168     ASSERT_TRUE(GraphComparator().Compare(graph, graph_et));
169 }
170 
171 /* one head, the chain spans across multiple blocks, not broken */
TEST_F(AdjustRefsTest,MultipleBlockContinuousChain)172 TEST_F(AdjustRefsTest, MultipleBlockContinuousChain)
173 {
174     auto graph = CreateEmptyFastpathGraph(RUNTIME_ARCH);
175 #ifndef NDEBUG
176     graph->SetLowLevelInstructionsEnabled();
177 #endif
178     GRAPH(graph)
179     {
180         PARAMETER(0, 0).ref();
181         PARAMETER(1, 1).s32();
182         PARAMETER(2, 2).u64();
183         CONSTANT(3, 10).s32();
184 
185         BASIC_BLOCK(3, 4, 10)
186         {
187             INST(10, Opcode::Phi).s32().Inputs(1, 90);
188             INST(11, Opcode::LoadArray).u64().Inputs(0, 1);
189             INST(15, Opcode::Compare).b().Inputs(10, 1);
190             INST(19, Opcode::IfImm).CC(CC_NE).Inputs(15).Imm(0);
191         }
192         BASIC_BLOCK(4, 5, 6)
193         {
194             INST(41, Opcode::Compare).b().Inputs(10, 1);
195             INST(42, Opcode::IfImm).CC(CC_NE).Inputs(41).Imm(0);
196         }
197         BASIC_BLOCK(5, 9)
198         {
199             INST(51, Opcode::LoadArray).u64().Inputs(0, 1);
200         }
201         BASIC_BLOCK(6, 9)
202         {
203             INST(61, Opcode::LoadArray).u64().Inputs(0, 1);
204         }
205         BASIC_BLOCK(9, 3)
206         {
207             INST(90, Opcode::Add).s32().Inputs(10, 3);
208         }
209         BASIC_BLOCK(10, 1)
210         {
211             INST(100, Opcode::ReturnVoid);
212         }
213     }
214 
215     Graph *graph_et = CreateEmptyFastpathGraph(RUNTIME_ARCH);
216     GRAPH(graph_et)
217     {
218         PARAMETER(0, 0).ref();
219         PARAMETER(1, 1).s32();
220         PARAMETER(2, 2).u64();
221         CONSTANT(3, 10).s32();
222         BASIC_BLOCK(3, 4, 10)
223         {
224             INST(10, Opcode::Phi).s32().Inputs(1, 90);
225             INST(11, Opcode::AddI).ptr().Inputs(0).Imm(graph->GetRuntime()->GetArrayDataOffset(graph->GetArch()));
226             INST(12, Opcode::Load).u64().Inputs(11, 1);
227             INST(15, Opcode::Compare).b().Inputs(10, 1);
228             INST(19, Opcode::IfImm).CC(CC_NE).Inputs(15).Imm(0);
229         }
230         BASIC_BLOCK(4, 5, 6)
231         {
232             INST(41, Opcode::Compare).b().Inputs(10, 1);
233             INST(42, Opcode::IfImm).CC(CC_NE).Inputs(41).Imm(0);
234         }
235         BASIC_BLOCK(5, 9)
236         {
237             INST(51, Opcode::Load).u64().Inputs(11, 1);
238         }
239         BASIC_BLOCK(6, 9)
240         {
241             INST(61, Opcode::Load).u64().Inputs(11, 1);
242         }
243         BASIC_BLOCK(9, 3)
244         {
245             INST(90, Opcode::Add).s32().Inputs(10, 3);
246         }
247         BASIC_BLOCK(10, 1)
248         {
249             INST(100, Opcode::ReturnVoid);
250         }
251     }
252 
253     ASSERT_TRUE(graph->RunPass<AdjustRefs>());
254 
255     GraphChecker(graph).Check();
256     ASSERT_TRUE(GraphComparator().Compare(graph, graph_et));
257 }
258 
259 /* one head, the chain spans across multiple blocks,
260  * broken in one of the dominated basic blocks */
TEST_F(AdjustRefsTest,MultipleBlockBrokenChain)261 TEST_F(AdjustRefsTest, MultipleBlockBrokenChain)
262 {
263     auto graph = CreateEmptyFastpathGraph(RUNTIME_ARCH);
264 #ifndef NDEBUG
265     graph->SetLowLevelInstructionsEnabled();
266 #endif
267     GRAPH(graph)
268     {
269         PARAMETER(0, 0).ref();
270         PARAMETER(1, 1).s32();
271         PARAMETER(2, 2).u64();
272         CONSTANT(3, 10).s32();
273 
274         BASIC_BLOCK(3, 4, 10)
275         {
276             INST(10, Opcode::Phi).s32().Inputs(1, 90);
277             INST(11, Opcode::LoadArray).u64().Inputs(0, 1);
278             INST(15, Opcode::Compare).b().Inputs(10, 1);
279             INST(19, Opcode::IfImm).CC(CC_NE).Inputs(15).Imm(0);
280         }
281         BASIC_BLOCK(4, 5, 6)
282         {
283             INST(41, Opcode::Compare).b().Inputs(10, 1);
284             INST(42, Opcode::IfImm).CC(CC_NE).Inputs(41).Imm(0);
285         }
286         BASIC_BLOCK(5, 9)
287         {
288             INST(51, Opcode::LoadArray).u64().Inputs(0, 1);
289         }
290         BASIC_BLOCK(6, 9)
291         {
292             INST(13, Opcode::SafePoint).NoVregs();
293             INST(61, Opcode::LoadArray).u64().Inputs(0, 1);
294         }
295         BASIC_BLOCK(9, 3)
296         {
297             INST(90, Opcode::Add).s32().Inputs(10, 3);
298         }
299         BASIC_BLOCK(10, 1)
300         {
301             INST(100, Opcode::ReturnVoid);
302         }
303     }
304 
305     Graph *graph_et = CreateEmptyFastpathGraph(RUNTIME_ARCH);
306     GRAPH(graph_et)
307     {
308         PARAMETER(0, 0).ref();
309         PARAMETER(1, 1).s32();
310         PARAMETER(2, 2).u64();
311         CONSTANT(3, 10).s32();
312         BASIC_BLOCK(3, 4, 10)
313         {
314             INST(10, Opcode::Phi).s32().Inputs(1, 90);
315             INST(11, Opcode::AddI).ptr().Inputs(0).Imm(graph->GetRuntime()->GetArrayDataOffset(graph->GetArch()));
316             INST(12, Opcode::Load).u64().Inputs(11, 1);
317             INST(15, Opcode::Compare).b().Inputs(10, 1);
318             INST(19, Opcode::IfImm).CC(CC_NE).Inputs(15).Imm(0);
319         }
320         BASIC_BLOCK(4, 5, 6)
321         {
322             INST(41, Opcode::Compare).b().Inputs(10, 1);
323             INST(42, Opcode::IfImm).CC(CC_NE).Inputs(41).Imm(0);
324         }
325         BASIC_BLOCK(5, 9)
326         {
327             INST(51, Opcode::Load).u64().Inputs(11, 1);
328         }
329         BASIC_BLOCK(6, 9)
330         {
331             INST(13, Opcode::SafePoint).NoVregs();
332             INST(61, Opcode::LoadArray).u64().Inputs(0, 1);
333         }
334         BASIC_BLOCK(9, 3)
335         {
336             INST(90, Opcode::Add).s32().Inputs(10, 3);
337         }
338         BASIC_BLOCK(10, 1)
339         {
340             INST(100, Opcode::ReturnVoid);
341         }
342     }
343 
344     ASSERT_TRUE(graph->RunPass<AdjustRefs>());
345 
346     GraphChecker(graph).Check();
347     ASSERT_TRUE(GraphComparator().Compare(graph, graph_et));
348 }
349 
350 }  // namespace panda::compiler
351