• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 
18 #include "optimizer/optimizations/scheduler.h"
19 
20 namespace panda::compiler {
21 class SchedulerTest : public GraphTest {};
22 
23 // NOLINTBEGIN(readability-magic-numbers)
TEST_F(SchedulerTest,Basic)24 TEST_F(SchedulerTest, Basic)
25 {
26     GRAPH(GetGraph())
27     {
28         CONSTANT(0U, 42U);
29         CONSTANT(1U, 43U);
30         CONSTANT(2U, 44U);
31         CONSTANT(3U, 45U);
32         CONSTANT(4U, 46U);
33         CONSTANT(5U, 47U);
34         CONSTANT(6U, 48U);
35         CONSTANT(7U, 49U);
36 
37         BASIC_BLOCK(2U, -1L)
38         {
39             INST(8U, Opcode::Add).u64().Inputs(0U, 1U);
40             INST(9U, Opcode::Add).u64().Inputs(2U, 3U);
41             // should be moved down
42             INST(10U, Opcode::Add).u64().Inputs(8U, 9U);
43 
44             INST(11U, Opcode::Add).u64().Inputs(4U, 5U);
45             INST(12U, Opcode::Add).u64().Inputs(6U, 7U);
46             INST(13U, Opcode::Add).u64().Inputs(11U, 12U);
47             // Grand total
48             INST(14U, Opcode::Add).u64().Inputs(10U, 13U);
49             INST(15U, Opcode::Return).u64().Inputs(14U);
50         }
51     }
52 
53     ASSERT_TRUE(GetGraph()->RunPass<Scheduler>());
54 
55     ASSERT_EQ(INS(8U).GetNext(), &INS(9U));
56     ASSERT_NE(INS(9U).GetNext(), &INS(10U));
57 
58     EXPECT_TRUE((INS(11U).GetNext() == &INS(10U)) || (INS(12U).GetNext() == &INS(10U)));
59 
60     ASSERT_EQ(INS(13U).GetNext(), &INS(14U));
61     ASSERT_EQ(INS(14U).GetNext(), &INS(15U));
62 }
63 
TEST_F(SchedulerTest,LoadBarrier)64 TEST_F(SchedulerTest, LoadBarrier)
65 {
66     GRAPH(GetGraph())
67     {
68         PARAMETER(0U, 0U).s32();  // index
69         PARAMETER(1U, 1U).ref();
70         CONSTANT(2U, 42U);
71         CONSTANT(3U, 43U);
72         CONSTANT(4U, 44U);
73         CONSTANT(5U, 45U);
74         CONSTANT(6U, 46U);
75         CONSTANT(7U, 47U);
76         CONSTANT(8U, 48U);
77         CONSTANT(9U, 5U);  // len array
78 
79         BASIC_BLOCK(2U, -1L)
80         {
81             INST(10U, Opcode::Add).u64().Inputs(2U, 3U);
82             INST(11U, Opcode::Add).u64().Inputs(4U, 5U);
83             // should be moved down
84             INST(12U, Opcode::Add).u64().Inputs(10U, 11U);
85 
86             INST(13U, Opcode::Add).u64().Inputs(6U, 7U);
87 
88             INST(21U, Opcode::SafePoint).Inputs(0U, 1U).SrcVregs({0U, 1U});
89             INST(14U, Opcode::SaveState).Inputs(0U, 1U).SrcVregs({0U, 1U});
90             INST(15U, Opcode::BoundsCheck).s32().Inputs(9U, 0U, 14U);
91             // can't move up because of SafePoint
92             INST(16U, Opcode::LoadArray).u64().Inputs(1U, 15U);
93 
94             INST(17U, Opcode::Add).u64().Inputs(8U, 16U);
95             INST(18U, Opcode::Add).u64().Inputs(13U, 17U);
96 
97             INST(19U, Opcode::Add).u64().Inputs(12U, 18U);
98             INST(20U, Opcode::Return).u64().Inputs(19U);
99         }
100     }
101 
102     ASSERT_TRUE(GetGraph()->RunPass<Scheduler>());
103 
104     ASSERT_EQ(INS(11U).GetNext(), &INS(13U));
105     ASSERT_EQ(INS(13U).GetNext(), &INS(12U));
106     ASSERT_EQ(INS(12U).GetNext(), &INS(21U));
107     ASSERT_EQ(INS(21U).GetNext(), &INS(14U));
108     ASSERT_EQ(INS(15U).GetNext(), &INS(16U));
109     ASSERT_EQ(INS(16U).GetNext(), &INS(17U));
110 }
111 
TEST_F(SchedulerTest,Load)112 TEST_F(SchedulerTest, Load)
113 {
114     GRAPH(GetGraph())
115     {
116         PARAMETER(0U, 0U).s32();  // index
117         PARAMETER(1U, 1U).ref();
118         CONSTANT(2U, 42U);
119         CONSTANT(3U, 43U);
120         CONSTANT(4U, 44U);
121         CONSTANT(5U, 45U);
122         CONSTANT(6U, 46U);
123         CONSTANT(7U, 47U);
124         CONSTANT(8U, 48U);
125         CONSTANT(9U, 5U);  // len array
126 
127         BASIC_BLOCK(2U, -1L)
128         {
129             INST(10U, Opcode::Add).u64().Inputs(2U, 3U);
130             INST(11U, Opcode::Add).u64().Inputs(4U, 5U);
131             // should be moved down
132             INST(12U, Opcode::Add).u64().Inputs(10U, 11U);
133 
134             INST(13U, Opcode::Add).u64().Inputs(6U, 7U);
135 
136             // all three should be moved up
137             INST(14U, Opcode::SaveState).Inputs(0U, 1U).SrcVregs({0U, 1U});
138             INST(15U, Opcode::BoundsCheck).s32().Inputs(9U, 0U, 14U);
139             INST(16U, Opcode::LoadArray).u64().Inputs(1U, 15U);
140 
141             INST(17U, Opcode::Add).u64().Inputs(8U, 16U);
142             INST(18U, Opcode::Add).u64().Inputs(13U, 17U);
143 
144             INST(19U, Opcode::Add).u64().Inputs(12U, 18U);
145             INST(20U, Opcode::Return).u64().Inputs(19U);
146         }
147     }
148 
149     ASSERT_TRUE(GetGraph()->RunPass<Scheduler>());
150 
151     ASSERT_EQ(INS(14U).GetNext(), &INS(10U));
152     ASSERT_EQ(INS(10U).GetNext(), &INS(15U));
153     ASSERT_EQ(INS(15U).GetNext(), &INS(11U));
154     ASSERT_EQ(INS(11U).GetNext(), &INS(16U));
155     ASSERT_EQ(INS(16U).GetNext(), &INS(13U));
156     ASSERT_EQ(INS(13U).GetNext(), &INS(12U));
157     ASSERT_EQ(INS(12U).GetNext(), &INS(17U));
158     ASSERT_EQ(INS(17U).GetNext(), &INS(18U));
159     ASSERT_EQ(INS(18U).GetNext(), &INS(19U));
160     ASSERT_EQ(INS(19U).GetNext(), &INS(20U));
161 }
162 
TEST_F(SchedulerTest,FixSSInBBAfterScheduler)163 TEST_F(SchedulerTest, FixSSInBBAfterScheduler)
164 {
165     GRAPH(GetGraph())
166     {
167         CONSTANT(1U, 1U).s32();
168         CONSTANT(2U, 2U).s32();
169 
170         BASIC_BLOCK(2U, -1L)
171         {
172             INST(4U, Opcode::SaveState).NoVregs();
173             INST(5U, Opcode::LoadAndInitClass).ref().Inputs(4U).TypeId(68U);
174             INST(6U, Opcode::SaveState).NoVregs();
175             INST(7U, Opcode::LoadConstArray).ref().Inputs(6U);
176             INST(8U, Opcode::Add).s32().Inputs(1U, 2U);
177             // LoadArray will move on one position down
178             INST(9U, Opcode::LoadArray).s32().Inputs(7U, 8U);
179             INST(10U, Opcode::SaveState).NoVregs();
180 
181             INST(11U, Opcode::NOP);
182             INST(12U, Opcode::Return).s32().Inputs(9U);
183         }
184     }
185 
186     ASSERT_TRUE(GetGraph()->RunPass<Scheduler>());
187 
188     auto graph = CreateEmptyGraph();
189     GRAPH(graph)
190     {
191         CONSTANT(1U, 1U).s32();
192         CONSTANT(2U, 2U).s32();
193 
194         BASIC_BLOCK(2U, -1L)
195         {
196             INST(4U, Opcode::SaveState).NoVregs();
197             INST(5U, Opcode::LoadAndInitClass).ref().Inputs(4U).TypeId(68U);
198             INST(6U, Opcode::SaveState).NoVregs();
199             INST(7U, Opcode::LoadConstArray).ref().Inputs(6U);
200             INST(8U, Opcode::Add).s32().Inputs(1U, 2U);
201 
202             INST(10U, Opcode::SaveState).Inputs(7U).SrcVregs({VirtualRegister::BRIDGE});
203             INST(9U, Opcode::LoadArray).s32().Inputs(7U, 8U);
204 
205             INST(11U, Opcode::NOP);
206             INST(12U, Opcode::Return).s32().Inputs(9U);
207         }
208     }
209 
210     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
211 }
212 
TEST_F(SchedulerTest,FixSSInBBAfterSchedulerOutToBlock)213 TEST_F(SchedulerTest, FixSSInBBAfterSchedulerOutToBlock)
214 {
215     GRAPH(GetGraph())
216     {
217         CONSTANT(1U, 1U).s32();
218         CONSTANT(2U, 2U).s32();
219 
220         BASIC_BLOCK(2U, 3U)
221         {
222             INST(4U, Opcode::SaveState).NoVregs();
223             INST(5U, Opcode::LoadAndInitClass).ref().Inputs(4U).TypeId(68U);
224             INST(6U, Opcode::SaveState).NoVregs();
225             INST(7U, Opcode::LoadConstArray).ref().Inputs(6U);
226         }
227         BASIC_BLOCK(3U, -1L)
228         {
229             INST(8U, Opcode::Add).s32().Inputs(1U, 2U);
230             // LoadArray will move on one position down
231             INST(9U, Opcode::LoadArray).s32().Inputs(7U, 8U);
232             INST(10U, Opcode::SaveState).NoVregs();
233 
234             INST(11U, Opcode::NOP);
235             INST(12U, Opcode::Return).s32().Inputs(9U);
236         }
237     }
238 
239     ASSERT_TRUE(GetGraph()->RunPass<Scheduler>());
240 
241     auto graph = CreateEmptyGraph();
242     GRAPH(graph)
243     {
244         CONSTANT(1U, 1U).s32();
245         CONSTANT(2U, 2U).s32();
246 
247         BASIC_BLOCK(2U, 3U)
248         {
249             INST(4U, Opcode::SaveState).NoVregs();
250             INST(5U, Opcode::LoadAndInitClass).ref().Inputs(4U).TypeId(68U);
251             INST(6U, Opcode::SaveState).NoVregs();
252             INST(7U, Opcode::LoadConstArray).ref().Inputs(6U);
253         }
254         BASIC_BLOCK(3U, -1L)
255         {
256             INST(8U, Opcode::Add).s32().Inputs(1U, 2U);
257 
258             INST(10U, Opcode::SaveState).Inputs(7U).SrcVregs({VirtualRegister::BRIDGE});
259             INST(9U, Opcode::LoadArray).s32().Inputs(7U, 8U);
260 
261             INST(11U, Opcode::NOP);
262             INST(12U, Opcode::Return).s32().Inputs(9U);
263         }
264     }
265 
266     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
267 }
268 
TEST_F(SchedulerTest,LoadI)269 TEST_F(SchedulerTest, LoadI)
270 {
271     GRAPH(GetGraph())
272     {
273         PARAMETER(0U, 0U).u64();
274         PARAMETER(1U, 1U).ref();
275 
276         BASIC_BLOCK(2U, -1L)
277         {
278             INST(2U, Opcode::SaveState).Inputs(0U, 1U).SrcVregs({0U, 1U});
279             INST(3U, Opcode::BoundsCheckI).s32().Inputs(0U, 2U).Imm(1U);
280             INST(4U, Opcode::StoreArrayI).u64().Inputs(1U, 0U).Imm(1U);
281             INST(5U, Opcode::SaveState).Inputs(0U, 1U).SrcVregs({0U, 1U});
282             INST(6U, Opcode::BoundsCheckI).s32().Inputs(0U, 5U).Imm(0U);
283             INST(7U, Opcode::LoadArrayI).u64().Inputs(1U).Imm(0U);
284             INST(8U, Opcode::Return).u64().Inputs(7U);
285         }
286     }
287 
288     ASSERT_FALSE(GetGraph()->RunPass<Scheduler>());
289 }
290 
TEST_F(SchedulerTest,TrickyLoadI)291 TEST_F(SchedulerTest, TrickyLoadI)
292 {
293     GRAPH(GetGraph())
294     {
295         PARAMETER(0U, 0U).u64();
296         PARAMETER(1U, 1U).ref();
297         BASIC_BLOCK(2U, -1L)
298         {
299             INST(5U, Opcode::SaveState).Inputs(0U, 1U).SrcVregs({0U, 1U});
300             INST(6U, Opcode::BoundsCheckI).s32().Inputs(0U, 5U).Imm(0U);
301             // Manually moved here
302             INST(2U, Opcode::SaveState).Inputs(0U, 1U).SrcVregs({0U, 1U});
303             INST(3U, Opcode::BoundsCheckI).s32().Inputs(0U, 2U).Imm(1U);
304             INST(4U, Opcode::StoreArrayI).u64().Inputs(1U, 0U).Imm(1U);
305             // But than all 3 may be moved below the load
306             INST(7U, Opcode::LoadArrayI).u64().Inputs(1U).Imm(0U);
307             INST(8U, Opcode::Return).u64().Inputs(7U);
308         }
309     }
310 
311     ASSERT_TRUE(GetGraph()->RunPass<Scheduler>());
312 
313     auto graph = CreateEmptyGraph();
314     GRAPH(graph)
315     {
316         PARAMETER(0U, 0U).u64();
317         PARAMETER(1U, 1U).ref();
318         BASIC_BLOCK(2U, -1L)
319         {
320             INST(5U, Opcode::SaveState).Inputs(0U, 1U).SrcVregs({0U, 1U});
321             INST(6U, Opcode::BoundsCheckI).s32().Inputs(0U, 5U).Imm(0U);
322             INST(7U, Opcode::LoadArrayI).u64().Inputs(1U).Imm(0U);
323 
324             INST(2U, Opcode::SaveState).Inputs(0U, 1U).SrcVregs({0U, 1U});
325             INST(3U, Opcode::BoundsCheckI).s32().Inputs(0U, 2U).Imm(1U);
326             INST(4U, Opcode::StoreArrayI).u64().Inputs(1U, 0U).Imm(1U);
327 
328             INST(8U, Opcode::Return).u64().Inputs(7U);
329         }
330     }
331     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
332 }
333 
TEST_F(SchedulerTest,MustAliasLoadI)334 TEST_F(SchedulerTest, MustAliasLoadI)
335 {
336     GRAPH(GetGraph())
337     {
338         PARAMETER(0U, 0U).u64();
339         PARAMETER(1U, 1U).ref();
340         BASIC_BLOCK(2U, -1L)
341         {
342             INST(5U, Opcode::SaveState).Inputs(0U, 1U).SrcVregs({0U, 1U});
343             INST(6U, Opcode::BoundsCheckI).s32().Inputs(0U, 5U).Imm(42U);
344             // Manually moved here
345             INST(2U, Opcode::SaveState).Inputs(0U, 1U).SrcVregs({0U, 1U});
346             INST(3U, Opcode::BoundsCheckI).s32().Inputs(0U, 2U).Imm(42U);
347             INST(4U, Opcode::StoreArrayI).u64().Inputs(1U, 0U).Imm(42U);
348             // But than all 3 may be moved below the load
349             INST(7U, Opcode::LoadArrayI).u64().Inputs(1U).Imm(42U);
350             INST(8U, Opcode::Return).u64().Inputs(7U);
351         }
352     }
353 
354     ASSERT_FALSE(GetGraph()->RunPass<Scheduler>());
355 }
356 
TEST_F(SchedulerTest,LoadPair)357 TEST_F(SchedulerTest, LoadPair)
358 {
359     GRAPH(GetGraph())
360     {
361         PARAMETER(0U, 0U).s32();  // index
362         PARAMETER(1U, 1U).ref();
363         CONSTANT(11U, 41U);
364         CONSTANT(12U, 42U);
365         CONSTANT(13U, 43U);
366         CONSTANT(14U, 44U);
367         CONSTANT(15U, 45U);
368         CONSTANT(16U, 46U);
369         CONSTANT(17U, 47U);
370         CONSTANT(18U, 48U);
371         CONSTANT(19U, 49U);
372         CONSTANT(20U, 50U);
373         CONSTANT(21U, 51U);
374         CONSTANT(22U, 52U);
375         CONSTANT(23U, 53U);
376         CONSTANT(24U, 54U);
377 
378         BASIC_BLOCK(2U, -1L)
379         {
380             INST(31U, Opcode::Add).u64().Inputs(11U, 12U);
381             INST(32U, Opcode::Add).u64().Inputs(13U, 14U);
382             INST(41U, Opcode::Add).u64().Inputs(31U, 32U);
383 
384             INST(33U, Opcode::Add).u64().Inputs(15U, 16U);
385             INST(34U, Opcode::Add).u64().Inputs(17U, 18U);
386             INST(42U, Opcode::Add).u64().Inputs(33U, 34U);
387 
388             INST(35U, Opcode::Add).u64().Inputs(19U, 20U);
389             INST(36U, Opcode::Add).u64().Inputs(21U, 22U);
390             INST(43U, Opcode::Add).u64().Inputs(35U, 36U);
391 
392             INST(92U, Opcode::LoadArrayPair).u64().Inputs(1U, 0U);
393             INST(93U, Opcode::LoadPairPart).u64().Inputs(92U).Imm(0U);
394             INST(94U, Opcode::LoadPairPart).u64().Inputs(92U).Imm(1U);
395 
396             INST(37U, Opcode::Add).u64().Inputs(23U, 93U);
397             INST(38U, Opcode::Add).u64().Inputs(24U, 94U);
398             INST(44U, Opcode::Add).u64().Inputs(37U, 38U);
399 
400             INST(51U, Opcode::Add).u64().Inputs(41U, 42U);
401             INST(52U, Opcode::Add).u64().Inputs(43U, 44U);
402 
403             INST(61U, Opcode::Add).u64().Inputs(51U, 52U);
404             INST(62U, Opcode::Return).u64().Inputs(61U);
405         }
406     }
407 
408     ASSERT_TRUE(GetGraph()->RunPass<Scheduler>());
409 
410     auto graph = CreateEmptyGraph();
411     GRAPH(graph)
412     {
413         PARAMETER(0U, 0U).s32();  // index
414         PARAMETER(1U, 1U).ref();
415         CONSTANT(11U, 41U);
416         CONSTANT(12U, 42U);
417         CONSTANT(13U, 43U);
418         CONSTANT(14U, 44U);
419         CONSTANT(15U, 45U);
420         CONSTANT(16U, 46U);
421         CONSTANT(17U, 47U);
422         CONSTANT(18U, 48U);
423         CONSTANT(19U, 49U);
424         CONSTANT(20U, 50U);
425         CONSTANT(21U, 51U);
426         CONSTANT(22U, 52U);
427         CONSTANT(23U, 53U);
428         CONSTANT(24U, 54U);
429 
430         BASIC_BLOCK(2U, -1L)
431         {
432             INST(92U, Opcode::LoadArrayPair).u64().Inputs(1U, 0U);
433             INST(93U, Opcode::LoadPairPart).u64().Inputs(92U).Imm(0U);
434             INST(94U, Opcode::LoadPairPart).u64().Inputs(92U).Imm(1U);
435 
436             INST(31U, Opcode::Add).u64().Inputs(11U, 12U);
437             INST(32U, Opcode::Add).u64().Inputs(13U, 14U);
438             INST(33U, Opcode::Add).u64().Inputs(15U, 16U);
439             INST(34U, Opcode::Add).u64().Inputs(17U, 18U);
440             INST(35U, Opcode::Add).u64().Inputs(19U, 20U);
441             INST(36U, Opcode::Add).u64().Inputs(21U, 22U);
442             INST(37U, Opcode::Add).u64().Inputs(23U, 93U);
443             INST(38U, Opcode::Add).u64().Inputs(24U, 94U);
444 
445             INST(41U, Opcode::Add).u64().Inputs(31U, 32U);
446             INST(42U, Opcode::Add).u64().Inputs(33U, 34U);
447             INST(43U, Opcode::Add).u64().Inputs(35U, 36U);
448             INST(44U, Opcode::Add).u64().Inputs(37U, 38U);
449 
450             INST(51U, Opcode::Add).u64().Inputs(41U, 42U);
451             INST(52U, Opcode::Add).u64().Inputs(43U, 44U);
452 
453             INST(61U, Opcode::Add).u64().Inputs(51U, 52U);
454             INST(62U, Opcode::Return).u64().Inputs(61U);
455         }
456     }
457     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
458 }
459 
TEST_F(SchedulerTest,NonVolatileLoadObject)460 TEST_F(SchedulerTest, NonVolatileLoadObject)
461 {
462     GRAPH(GetGraph())
463     {
464         PARAMETER(0U, 0U).ref();
465         PARAMETER(1U, 1U).s32();
466         PARAMETER(2U, 2U).s32();
467         PARAMETER(3U, 3U).s32();
468         BASIC_BLOCK(2U, -1L)
469         {
470             INST(4U, Opcode::Add).s32().Inputs(1U, 2U);
471             INST(5U, Opcode::Add).s32().Inputs(1U, 3U);
472             INST(6U, Opcode::Add).s32().Inputs(2U, 3U);
473             INST(7U, Opcode::Add).s32().Inputs(4U, 5U);
474             INST(8U, Opcode::Add).s32().Inputs(6U, 7U);
475             INST(9U, Opcode::SaveState).Inputs(0U).SrcVregs({0U});
476             INST(10U, Opcode::NullCheck).ref().Inputs(0U, 9U);
477             INST(11U, Opcode::LoadObject).s32().Inputs(10U).TypeId(152U);
478             INST(12U, Opcode::Add).s32().Inputs(8U, 11U);
479             INST(13U, Opcode::Return).s32().Inputs(12U);
480         }
481     }
482     ASSERT_TRUE(GetGraph()->RunPass<Scheduler>());
483 
484     auto graph = CreateEmptyGraph();
485     GRAPH(graph)
486     {
487         PARAMETER(0U, 0U).ref();
488         PARAMETER(1U, 1U).s32();
489         PARAMETER(2U, 2U).s32();
490         PARAMETER(3U, 3U).s32();
491         BASIC_BLOCK(2U, -1L)
492         {
493             INST(9U, Opcode::SaveState).Inputs(0U).SrcVregs({0U});
494             INST(4U, Opcode::Add).s32().Inputs(1U, 2U);
495             INST(10U, Opcode::NullCheck).ref().Inputs(0U, 9U);
496             INST(5U, Opcode::Add).s32().Inputs(1U, 3U);
497             INST(11U, Opcode::LoadObject).s32().Inputs(10U).TypeId(152U);
498             INST(6U, Opcode::Add).s32().Inputs(2U, 3U);
499             INST(7U, Opcode::Add).s32().Inputs(4U, 5U);
500             INST(8U, Opcode::Add).s32().Inputs(6U, 7U);
501             INST(12U, Opcode::Add).s32().Inputs(8U, 11U);
502             INST(13U, Opcode::Return).s32().Inputs(12U);
503         }
504     }
505     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
506 }
507 
TEST_F(SchedulerTest,VolatileLoadObject)508 TEST_F(SchedulerTest, VolatileLoadObject)
509 {
510     GRAPH(GetGraph())
511     {
512         PARAMETER(0U, 0U).ref();
513         PARAMETER(1U, 1U).s32();
514         PARAMETER(2U, 2U).s32();
515         PARAMETER(3U, 3U).s32();
516         BASIC_BLOCK(2U, -1L)
517         {
518             INST(4U, Opcode::Add).s32().Inputs(1U, 2U);
519             INST(5U, Opcode::Add).s32().Inputs(1U, 3U);
520             INST(6U, Opcode::Add).s32().Inputs(2U, 3U);
521             INST(7U, Opcode::Add).s32().Inputs(4U, 5U);
522             INST(8U, Opcode::Add).s32().Inputs(6U, 7U);
523             INST(9U, Opcode::SaveState).Inputs(0U).SrcVregs({0U});
524             INST(10U, Opcode::NullCheck).ref().Inputs(0U, 9U);
525             INST(11U, Opcode::LoadObject).s32().Inputs(10U).TypeId(152U).Volatile();
526             INST(12U, Opcode::Add).s32().Inputs(8U, 11U);
527             INST(13U, Opcode::Return).s32().Inputs(12U);
528         }
529     }
530     ASSERT_TRUE(GetGraph()->RunPass<Scheduler>());
531 
532     auto graph = CreateEmptyGraph();
533     GRAPH(graph)
534     {
535         PARAMETER(0U, 0U).ref();
536         PARAMETER(1U, 1U).s32();
537         PARAMETER(2U, 2U).s32();
538         PARAMETER(3U, 3U).s32();
539         BASIC_BLOCK(2U, -1L)
540         {
541             INST(4U, Opcode::Add).s32().Inputs(1U, 2U);
542             INST(5U, Opcode::Add).s32().Inputs(1U, 3U);
543             INST(9U, Opcode::SaveState).Inputs(0U).SrcVregs({0U});
544             INST(6U, Opcode::Add).s32().Inputs(2U, 3U);
545             INST(7U, Opcode::Add).s32().Inputs(4U, 5U);
546             INST(10U, Opcode::NullCheck).ref().Inputs(0U, 9U);
547             INST(8U, Opcode::Add).s32().Inputs(6U, 7U);
548             INST(11U, Opcode::LoadObject).s32().Inputs(10U).TypeId(152U).Volatile();
549             INST(12U, Opcode::Add).s32().Inputs(8U, 11U);
550             INST(13U, Opcode::Return).s32().Inputs(12U);
551         }
552     }
553     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
554 }
555 // NOLINTEND(readability-magic-numbers)
556 
557 }  // namespace panda::compiler
558