1b1994897Sopenharmony_ci/**
2b1994897Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3b1994897Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4b1994897Sopenharmony_ci * you may not use this file except in compliance with the License.
5b1994897Sopenharmony_ci * You may obtain a copy of the License at
6b1994897Sopenharmony_ci *
7b1994897Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8b1994897Sopenharmony_ci *
9b1994897Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10b1994897Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11b1994897Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b1994897Sopenharmony_ci * See the License for the specific language governing permissions and
13b1994897Sopenharmony_ci * limitations under the License.
14b1994897Sopenharmony_ci */
15b1994897Sopenharmony_ci
16b1994897Sopenharmony_ci#include "unit_test.h"
17b1994897Sopenharmony_ci#include "optimizer/ir_builder/inst_builder-inl.h"
18b1994897Sopenharmony_ci
19b1994897Sopenharmony_cinamespace panda::compiler {
20b1994897Sopenharmony_ciinline bool operator==(const Input &lhs, const Inst *rhs)
21b1994897Sopenharmony_ci{
22b1994897Sopenharmony_ci    return lhs.GetInst() == rhs;
23b1994897Sopenharmony_ci}
24b1994897Sopenharmony_ci
25b1994897Sopenharmony_ciclass InstTest : public GraphTest {
26b1994897Sopenharmony_ci};
27b1994897Sopenharmony_ci
28b1994897Sopenharmony_ciTEST_F(InstTest, Dataflow)
29b1994897Sopenharmony_ci{
30b1994897Sopenharmony_ci    /**
31b1994897Sopenharmony_ci     * '=' is a definition
32b1994897Sopenharmony_ci     *
33b1994897Sopenharmony_ci     *           [2]
34b1994897Sopenharmony_ci     *            |
35b1994897Sopenharmony_ci     *    /---------------\
36b1994897Sopenharmony_ci     *    |               |
37b1994897Sopenharmony_ci     *   [3]=            [4]=
38b1994897Sopenharmony_ci     *    |               |
39b1994897Sopenharmony_ci     *    |          /---------\
40b1994897Sopenharmony_ci     *   [5]         |         |
41b1994897Sopenharmony_ci     *    |          |        [6] (need for removing #6)
42b1994897Sopenharmony_ci     *    |          |         |
43b1994897Sopenharmony_ci     *    |          |        [7]=
44b1994897Sopenharmony_ci     *    |          |         |
45b1994897Sopenharmony_ci     *    \---------[8]--------/
46b1994897Sopenharmony_ci     *          PHI(1,2,4)
47b1994897Sopenharmony_ci     *
48b1994897Sopenharmony_ci     */
49b1994897Sopenharmony_ci    GRAPH(GetGraph())
50b1994897Sopenharmony_ci    {
51b1994897Sopenharmony_ci        CONSTANT(0, 12);
52b1994897Sopenharmony_ci        CONSTANT(1, 13);
53b1994897Sopenharmony_ci
54b1994897Sopenharmony_ci        BASIC_BLOCK(2, 3, 4)
55b1994897Sopenharmony_ci        {
56b1994897Sopenharmony_ci            INST(2, Opcode::Add).u64().Inputs(0, 1);
57b1994897Sopenharmony_ci            INST(8, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(0, 1);
58b1994897Sopenharmony_ci            INST(9, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(8);
59b1994897Sopenharmony_ci        }
60b1994897Sopenharmony_ci        BASIC_BLOCK(3, 5)
61b1994897Sopenharmony_ci        {
62b1994897Sopenharmony_ci            INST(3, Opcode::Not).u64().Inputs(0);
63b1994897Sopenharmony_ci        }
64b1994897Sopenharmony_ci        BASIC_BLOCK(4, 8, 6)
65b1994897Sopenharmony_ci        {
66b1994897Sopenharmony_ci            INST(4, Opcode::Not).u64().Inputs(1);
67b1994897Sopenharmony_ci            INST(11, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(0, 1);
68b1994897Sopenharmony_ci            INST(12, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(11);
69b1994897Sopenharmony_ci        }
70b1994897Sopenharmony_ci        BASIC_BLOCK(5, 8)
71b1994897Sopenharmony_ci        {
72b1994897Sopenharmony_ci            INST(7, Opcode::Sub).u64().Inputs(3, 2);
73b1994897Sopenharmony_ci        }
74b1994897Sopenharmony_ci        BASIC_BLOCK(6, 7) {}
75b1994897Sopenharmony_ci        BASIC_BLOCK(7, 8)
76b1994897Sopenharmony_ci        {
77b1994897Sopenharmony_ci            INST(5, Opcode::Not).u64().Inputs(4);
78b1994897Sopenharmony_ci        }
79b1994897Sopenharmony_ci        BASIC_BLOCK(8, -1)
80b1994897Sopenharmony_ci        {
81b1994897Sopenharmony_ci            INST(6, Opcode::Phi).u64().Inputs({{5, 3}, {4, 4}, {7, 5}});
82b1994897Sopenharmony_ci            INST(16, Opcode::ReturnVoid);
83b1994897Sopenharmony_ci        }
84b1994897Sopenharmony_ci    }
85b1994897Sopenharmony_ci
86b1994897Sopenharmony_ci    // Check constructed dataflow
87b1994897Sopenharmony_ci    ASSERT_TRUE(CheckUsers(INS(0), {2, 3, 8, 11}));
88b1994897Sopenharmony_ci    ASSERT_TRUE(CheckUsers(INS(1), {2, 4, 8, 11}));
89b1994897Sopenharmony_ci    ASSERT_TRUE(CheckUsers(INS(2), {7}));
90b1994897Sopenharmony_ci    ASSERT_TRUE(CheckUsers(INS(3), {6, 7}));
91b1994897Sopenharmony_ci    ASSERT_TRUE(CheckUsers(INS(4), {5, 6}));
92b1994897Sopenharmony_ci    ASSERT_TRUE(CheckUsers(INS(5), {6}));
93b1994897Sopenharmony_ci    ASSERT_TRUE(CheckInputs(INS(2), {0, 1}));
94b1994897Sopenharmony_ci    ASSERT_TRUE(CheckInputs(INS(3), {0}));
95b1994897Sopenharmony_ci    ASSERT_TRUE(CheckInputs(INS(7), {3, 2}));
96b1994897Sopenharmony_ci    ASSERT_TRUE(CheckInputs(INS(4), {1}));
97b1994897Sopenharmony_ci    ASSERT_TRUE(CheckInputs(INS(5), {4}));
98b1994897Sopenharmony_ci    ASSERT_TRUE(CheckInputs(INS(6), {3, 4, 5}));
99b1994897Sopenharmony_ci    ASSERT_EQ(static_cast<PhiInst &>(INS(6)).GetPhiInput(&BB(5)), &INS(3));
100b1994897Sopenharmony_ci    ASSERT_EQ(static_cast<PhiInst &>(INS(6)).GetPhiInput(&BB(4)), &INS(4));
101b1994897Sopenharmony_ci    ASSERT_EQ(static_cast<PhiInst &>(INS(6)).GetPhiInput(&BB(7)), &INS(5));
102b1994897Sopenharmony_ci
103b1994897Sopenharmony_ci    {  // Test iterating over users of constant instruction
104b1994897Sopenharmony_ci        const Inst *inst = &INS(2);
105b1994897Sopenharmony_ci        for (auto &user : inst->GetUsers()) {
106b1994897Sopenharmony_ci            ASSERT_EQ(inst, user.GetInput());
107b1994897Sopenharmony_ci        }
108b1994897Sopenharmony_ci    }
109b1994897Sopenharmony_ci
110b1994897Sopenharmony_ci    {  // Test iterating over users of non-constant instruction
111b1994897Sopenharmony_ci        Inst *inst = &INS(2);
112b1994897Sopenharmony_ci        for (auto &user : inst->GetUsers()) {
113b1994897Sopenharmony_ci            user.GetInst()->SetId(user.GetInst()->GetId());
114b1994897Sopenharmony_ci        }
115b1994897Sopenharmony_ci    }
116b1994897Sopenharmony_ci
117b1994897Sopenharmony_ci    // 1. Remove instruction #3, replace its users by its input
118b1994897Sopenharmony_ci    INS(3).ReplaceUsers(INS(3).GetInput(0).GetInst());
119b1994897Sopenharmony_ci    INS(3).GetBasicBlock()->RemoveInst(&INS(3));
120b1994897Sopenharmony_ci    ASSERT_TRUE(INS(6).GetInput(0).GetInst() == &INS(0));
121b1994897Sopenharmony_ci    ASSERT_TRUE(INS(3).GetInput(0).GetInst() == nullptr);
122b1994897Sopenharmony_ci    ASSERT_TRUE(CheckUsers(INS(0), {2, 6, 7, 8, 11}));
123b1994897Sopenharmony_ci    ASSERT_EQ(static_cast<PhiInst &>(INS(6)).GetPhiInput(&BB(5)), &INS(0));
124b1994897Sopenharmony_ci    GraphChecker(GetGraph()).Check();
125b1994897Sopenharmony_ci
126b1994897Sopenharmony_ci    // TODO(A.Popov): refactor RemovePredsBlocks
127b1994897Sopenharmony_ci    // 2. Remove basic block #4, phi should be fixed properly
128b1994897Sopenharmony_ci    // INS(5).RemoveInputs()
129b1994897Sopenharmony_ci    // INS(5).GetBasicBlock()->EraseInst(&INS(5))
130b1994897Sopenharmony_ci    // GetGraph()->DisconnectBlock(&BB(7))
131b1994897Sopenharmony_ci    // ASSERT_TRUE(INS(6).GetInputsCount() == 2)
132b1994897Sopenharmony_ci    // static_cast<PhiInst&>(INS(6)).GetPhiInput(&BB(5)), &INS(0))
133b1994897Sopenharmony_ci    // static_cast<PhiInst&>(INS(6)).GetPhiInput(&BB(4)), &INS(4))
134b1994897Sopenharmony_ci    GraphChecker(GetGraph()).Check();
135b1994897Sopenharmony_ci
136b1994897Sopenharmony_ci    // 3. Append additional inputs into PHI, thereby force it to reallocate inputs storage, dataflow is not valid  from
137b1994897Sopenharmony_ci    // this moment
138b1994897Sopenharmony_ci    for (int i = 0; i < 4; ++i) {
139b1994897Sopenharmony_ci        INS(6).AppendInput(&INS(0));
140b1994897Sopenharmony_ci    }
141b1994897Sopenharmony_ci}
142b1994897Sopenharmony_ci
143b1994897Sopenharmony_ciTEST_F(InstTest, Arithmetics)
144b1994897Sopenharmony_ci{
145b1994897Sopenharmony_ci    GRAPH(GetGraph())
146b1994897Sopenharmony_ci    {
147b1994897Sopenharmony_ci        CONSTANT(0, 12);
148b1994897Sopenharmony_ci        CONSTANT(1, 17.23);
149b1994897Sopenharmony_ci
150b1994897Sopenharmony_ci        BASIC_BLOCK(2, -1)
151b1994897Sopenharmony_ci        {
152b1994897Sopenharmony_ci            INST(2, Opcode::Cast).u64().SrcType(DataType::FLOAT64).Inputs(1);
153b1994897Sopenharmony_ci            INST(3, Opcode::Add).u64().Inputs(0, 2);
154b1994897Sopenharmony_ci            INST(4, Opcode::ReturnVoid);
155b1994897Sopenharmony_ci        }
156b1994897Sopenharmony_ci    }
157b1994897Sopenharmony_ci}
158b1994897Sopenharmony_ci
159b1994897Sopenharmony_ciTEST_F(InstTest, Memory)
160b1994897Sopenharmony_ci{
161b1994897Sopenharmony_ci    GRAPH(GetGraph())
162b1994897Sopenharmony_ci    {
163b1994897Sopenharmony_ci        PARAMETER(0, 0).ref();  // array
164b1994897Sopenharmony_ci        PARAMETER(1, 1).u64();  // index
165b1994897Sopenharmony_ci        BASIC_BLOCK(2, -1)
166b1994897Sopenharmony_ci        {
167b1994897Sopenharmony_ci            INST(2, Opcode::SaveState).Inputs(0, 1).SrcVregs({0, 1});
168b1994897Sopenharmony_ci            INST(3, Opcode::NullCheck).ref().Inputs(0, 2);
169b1994897Sopenharmony_ci            INST(4, Opcode::LenArray).s32().Inputs(3);
170b1994897Sopenharmony_ci            INST(5, Opcode::BoundsCheck).s32().Inputs(4, 1, 2);
171b1994897Sopenharmony_ci            INST(6, Opcode::LoadArray).u64().Inputs(3, 5);
172b1994897Sopenharmony_ci            INST(7, Opcode::Add).u64().Inputs(6, 6);
173b1994897Sopenharmony_ci            INST(8, Opcode::StoreArray).u64().Inputs(3, 5, 7);
174b1994897Sopenharmony_ci            INST(9, Opcode::ReturnVoid);
175b1994897Sopenharmony_ci        }
176b1994897Sopenharmony_ci    }
177b1994897Sopenharmony_ci}
178b1994897Sopenharmony_ci
179b1994897Sopenharmony_ciTEST_F(InstTest, Const)
180b1994897Sopenharmony_ci{
181b1994897Sopenharmony_ci    int32_t int32_const[3] = {-5, 0, 5};
182b1994897Sopenharmony_ci    int64_t int64_const[3] = {-5, 0, 5};
183b1994897Sopenharmony_ci    GRAPH(GetGraph())
184b1994897Sopenharmony_ci    {
185b1994897Sopenharmony_ci        BASIC_BLOCK(2, -1)
186b1994897Sopenharmony_ci        {
187b1994897Sopenharmony_ci            INST(0, Opcode::ReturnVoid);
188b1994897Sopenharmony_ci        }
189b1994897Sopenharmony_ci    }
190b1994897Sopenharmony_ci    auto start = GetGraph()->GetStartBlock();
191b1994897Sopenharmony_ci    for (auto i = 0; i < 3; i++) {
192b1994897Sopenharmony_ci        int32_t val = int32_const[i];
193b1994897Sopenharmony_ci        auto const1 = GetGraph()->FindOrCreateConstant(val);
194b1994897Sopenharmony_ci        ASSERT_EQ(const1->GetType(), DataType::INT64);
195b1994897Sopenharmony_ci        ASSERT_EQ(const1->GetBasicBlock(), start);
196b1994897Sopenharmony_ci        uint64_t val1 = int64_const[i];
197b1994897Sopenharmony_ci        auto const2 = GetGraph()->FindOrCreateConstant(val1);
198b1994897Sopenharmony_ci        ASSERT_EQ(const2->GetType(), DataType::INT64);
199b1994897Sopenharmony_ci        ASSERT_EQ(const1, const2);
200b1994897Sopenharmony_ci        ASSERT_EQ(const1->GetIntValue(), val1);
201b1994897Sopenharmony_ci    }
202b1994897Sopenharmony_ci    GraphChecker(GetGraph()).Check();
203b1994897Sopenharmony_ci    float float_const[3] = {-5.5f, 0.1f, 5.2f};
204b1994897Sopenharmony_ci    for (auto i = 0; i < 3; i++) {
205b1994897Sopenharmony_ci        float val = float_const[i];
206b1994897Sopenharmony_ci        auto const1 = GetGraph()->FindOrCreateConstant(val);
207b1994897Sopenharmony_ci        ASSERT_EQ(const1->GetType(), DataType::FLOAT32);
208b1994897Sopenharmony_ci        ASSERT_EQ(const1->GetBasicBlock(), start);
209b1994897Sopenharmony_ci        auto const2 = GetGraph()->FindOrCreateConstant(val);
210b1994897Sopenharmony_ci        ASSERT_EQ(const1, const2);
211b1994897Sopenharmony_ci        ASSERT_EQ(const1->GetFloatValue(), val);
212b1994897Sopenharmony_ci    }
213b1994897Sopenharmony_ci    GraphChecker(GetGraph()).Check();
214b1994897Sopenharmony_ci    double double_const[3] = {-5.5, 0.1, 5.2};
215b1994897Sopenharmony_ci    for (auto i = 0; i < 3; i++) {
216b1994897Sopenharmony_ci        double val = double_const[i];
217b1994897Sopenharmony_ci        auto const1 = GetGraph()->FindOrCreateConstant(val);
218b1994897Sopenharmony_ci        ASSERT_EQ(const1->GetType(), DataType::FLOAT64);
219b1994897Sopenharmony_ci        ASSERT_EQ(const1->GetBasicBlock(), start);
220b1994897Sopenharmony_ci        auto const2 = GetGraph()->FindOrCreateConstant(val);
221b1994897Sopenharmony_ci        ASSERT_EQ(const1, const2);
222b1994897Sopenharmony_ci        ASSERT_EQ(const1->GetDoubleValue(), val);
223b1994897Sopenharmony_ci    }
224b1994897Sopenharmony_ci    int i = 0;
225b1994897Sopenharmony_ci    for (auto current_const = GetGraph()->GetFirstConstInst(); current_const != nullptr;
226b1994897Sopenharmony_ci         current_const = current_const->GetNextConst()) {
227b1994897Sopenharmony_ci        i++;
228b1994897Sopenharmony_ci    }
229b1994897Sopenharmony_ci    ASSERT_EQ(i, 9);
230b1994897Sopenharmony_ci}
231b1994897Sopenharmony_ci
232b1994897Sopenharmony_ciTEST_F(InstTest, Const32)
233b1994897Sopenharmony_ci{
234b1994897Sopenharmony_ci    int32_t int32_const[3] = {-5, 0, 5};
235b1994897Sopenharmony_ci    int64_t int64_const[3] = {-5, 0, 5};
236b1994897Sopenharmony_ci    auto graph = CreateEmptyBytecodeGraph();
237b1994897Sopenharmony_ci
238b1994897Sopenharmony_ci    GRAPH(graph)
239b1994897Sopenharmony_ci    {
240b1994897Sopenharmony_ci        BASIC_BLOCK(2, -1)
241b1994897Sopenharmony_ci        {
242b1994897Sopenharmony_ci            INST(0, Opcode::ReturnVoid);
243b1994897Sopenharmony_ci        }
244b1994897Sopenharmony_ci    }
245b1994897Sopenharmony_ci    auto start = graph->GetStartBlock();
246b1994897Sopenharmony_ci    for (auto i = 0; i < 3; i++) {
247b1994897Sopenharmony_ci        // add first int32 constant
248b1994897Sopenharmony_ci        int32_t val = int32_const[i];
249b1994897Sopenharmony_ci        auto const1 = graph->FindOrCreateConstant(val);
250b1994897Sopenharmony_ci        ASSERT_EQ(const1->GetType(), DataType::INT32);
251b1994897Sopenharmony_ci        ASSERT_EQ(const1->GetBasicBlock(), start);
252b1994897Sopenharmony_ci        uint64_t val1 = int64_const[i];
253b1994897Sopenharmony_ci        // add int64 constant, graph creates new constant
254b1994897Sopenharmony_ci        auto const2 = graph->FindOrCreateConstant(val1);
255b1994897Sopenharmony_ci        ASSERT_EQ(const2->GetType(), DataType::INT64);
256b1994897Sopenharmony_ci        ASSERT_NE(const1, const2);
257b1994897Sopenharmony_ci        ASSERT_EQ(const2->GetBasicBlock(), start);
258b1994897Sopenharmony_ci        ASSERT_EQ(const1->GetIntValue(), val1);
259b1994897Sopenharmony_ci        // add second int32 constant, graph doesn't create new constant
260b1994897Sopenharmony_ci        int32_t val2 = int32_const[i];
261b1994897Sopenharmony_ci        auto const3 = graph->FindOrCreateConstant(val2);
262b1994897Sopenharmony_ci        ASSERT_EQ(const3, const1);
263b1994897Sopenharmony_ci        ASSERT_EQ(const1->GetInt32Value(), val2);
264b1994897Sopenharmony_ci    }
265b1994897Sopenharmony_ci    GraphChecker(graph).Check();
266b1994897Sopenharmony_ci}
267b1994897Sopenharmony_ci
268b1994897Sopenharmony_ciTEST_F(InstTest, ReturnVoid)
269b1994897Sopenharmony_ci{
270b1994897Sopenharmony_ci    GRAPH(GetGraph())
271b1994897Sopenharmony_ci    {
272b1994897Sopenharmony_ci        BASIC_BLOCK(2, -1)
273b1994897Sopenharmony_ci        {
274b1994897Sopenharmony_ci            INST(0, Opcode::ReturnVoid);
275b1994897Sopenharmony_ci        }
276b1994897Sopenharmony_ci    }
277b1994897Sopenharmony_ci}
278b1994897Sopenharmony_ci
279b1994897Sopenharmony_ciTEST_F(InstTest, ReturnFloat)
280b1994897Sopenharmony_ci{
281b1994897Sopenharmony_ci    GRAPH(GetGraph())
282b1994897Sopenharmony_ci    {
283b1994897Sopenharmony_ci        CONSTANT(0, 1.1f);
284b1994897Sopenharmony_ci        BASIC_BLOCK(2, -1)
285b1994897Sopenharmony_ci        {
286b1994897Sopenharmony_ci            INST(1, Opcode::Return).f32().Inputs(0);
287b1994897Sopenharmony_ci        }
288b1994897Sopenharmony_ci    }
289b1994897Sopenharmony_ci}
290b1994897Sopenharmony_ci
291b1994897Sopenharmony_ciTEST_F(InstTest, ReturnDouble)
292b1994897Sopenharmony_ci{
293b1994897Sopenharmony_ci    GRAPH(GetGraph())
294b1994897Sopenharmony_ci    {
295b1994897Sopenharmony_ci        CONSTANT(0, 1.1);
296b1994897Sopenharmony_ci        BASIC_BLOCK(2, -1)
297b1994897Sopenharmony_ci        {
298b1994897Sopenharmony_ci            INST(1, Opcode::Return).f64().Inputs(0);
299b1994897Sopenharmony_ci        }
300b1994897Sopenharmony_ci    }
301b1994897Sopenharmony_ci}
302b1994897Sopenharmony_ci
303b1994897Sopenharmony_ciTEST_F(InstTest, ReturnLong)
304b1994897Sopenharmony_ci{
305b1994897Sopenharmony_ci    uint64_t i = 1;
306b1994897Sopenharmony_ci    GRAPH(GetGraph())
307b1994897Sopenharmony_ci    {
308b1994897Sopenharmony_ci        CONSTANT(0, i);
309b1994897Sopenharmony_ci        BASIC_BLOCK(2, -1)
310b1994897Sopenharmony_ci        {
311b1994897Sopenharmony_ci            INST(1, Opcode::Return).u64().Inputs(0);
312b1994897Sopenharmony_ci        }
313b1994897Sopenharmony_ci    }
314b1994897Sopenharmony_ci}
315b1994897Sopenharmony_ci
316b1994897Sopenharmony_ciTEST_F(InstTest, ReturnInt)
317b1994897Sopenharmony_ci{
318b1994897Sopenharmony_ci    int32_t i = 1;
319b1994897Sopenharmony_ci    GRAPH(GetGraph())
320b1994897Sopenharmony_ci    {
321b1994897Sopenharmony_ci        CONSTANT(0, i);
322b1994897Sopenharmony_ci        BASIC_BLOCK(2, -1)
323b1994897Sopenharmony_ci        {
324b1994897Sopenharmony_ci            INST(1, Opcode::Return).u32().Inputs(0);
325b1994897Sopenharmony_ci        }
326b1994897Sopenharmony_ci    }
327b1994897Sopenharmony_ci}
328b1994897Sopenharmony_ci
329b1994897Sopenharmony_ciTEST_F(InstTest, ArrayChecks)
330b1994897Sopenharmony_ci{
331b1994897Sopenharmony_ci    GRAPH(GetGraph())
332b1994897Sopenharmony_ci    {
333b1994897Sopenharmony_ci        PARAMETER(0, 0).ref();  // array
334b1994897Sopenharmony_ci        PARAMETER(1, 1).u64();  // index
335b1994897Sopenharmony_ci        BASIC_BLOCK(2, -1)
336b1994897Sopenharmony_ci        {
337b1994897Sopenharmony_ci            INST(2, Opcode::SaveState).Inputs(0, 1).SrcVregs({0, 1});
338b1994897Sopenharmony_ci            INST(3, Opcode::NullCheck).ref().Inputs(0, 2);
339b1994897Sopenharmony_ci            INST(4, Opcode::LenArray).s32().Inputs(3);
340b1994897Sopenharmony_ci            INST(5, Opcode::BoundsCheck).s32().Inputs(4, 1, 2);
341b1994897Sopenharmony_ci            INST(6, Opcode::LoadArray).u64().Inputs(3, 5);
342b1994897Sopenharmony_ci            INST(7, Opcode::Add).u64().Inputs(6, 6);
343b1994897Sopenharmony_ci            INST(8, Opcode::StoreArray).u64().Inputs(3, 5, 7);
344b1994897Sopenharmony_ci            INST(9, Opcode::ReturnVoid);
345b1994897Sopenharmony_ci        }
346b1994897Sopenharmony_ci    }
347b1994897Sopenharmony_ci}
348b1994897Sopenharmony_ci
349b1994897Sopenharmony_ciTEST_F(InstTest, ZeroCheck)
350b1994897Sopenharmony_ci{
351b1994897Sopenharmony_ci    GRAPH(GetGraph())
352b1994897Sopenharmony_ci    {
353b1994897Sopenharmony_ci        PARAMETER(0, 0).u64();
354b1994897Sopenharmony_ci        PARAMETER(1, 1).u64();
355b1994897Sopenharmony_ci        BASIC_BLOCK(2, -1)
356b1994897Sopenharmony_ci        {
357b1994897Sopenharmony_ci            INST(2, Opcode::SaveState).Inputs(0, 1).SrcVregs({0, 1});
358b1994897Sopenharmony_ci            INST(3, Opcode::ZeroCheck).u64().Inputs(0, 2);
359b1994897Sopenharmony_ci            INST(4, Opcode::Div).u64().Inputs(1, 3);
360b1994897Sopenharmony_ci            INST(5, Opcode::Mod).u64().Inputs(1, 3);
361b1994897Sopenharmony_ci            INST(6, Opcode::ReturnVoid);
362b1994897Sopenharmony_ci        }
363b1994897Sopenharmony_ci    }
364b1994897Sopenharmony_ci}
365b1994897Sopenharmony_ci
366b1994897Sopenharmony_ciTEST_F(InstTest, Parametr)
367b1994897Sopenharmony_ci{
368b1994897Sopenharmony_ci    GRAPH(GetGraph())
369b1994897Sopenharmony_ci    {
370b1994897Sopenharmony_ci        PARAMETER(0, 0).u64();
371b1994897Sopenharmony_ci        PARAMETER(1, 1).u32();
372b1994897Sopenharmony_ci        PARAMETER(2, 4).u16();
373b1994897Sopenharmony_ci        PARAMETER(3, 5).u8();
374b1994897Sopenharmony_ci        PARAMETER(4, 8).s64();
375b1994897Sopenharmony_ci        PARAMETER(5, 10).s32();
376b1994897Sopenharmony_ci        PARAMETER(6, 11).s16();
377b1994897Sopenharmony_ci        PARAMETER(7, 24).s8();
378b1994897Sopenharmony_ci        PARAMETER(8, 27).b();
379b1994897Sopenharmony_ci        PARAMETER(9, 28).f64();
380b1994897Sopenharmony_ci        PARAMETER(10, 29).f32();
381b1994897Sopenharmony_ci        PARAMETER(11, 40).ref();
382b1994897Sopenharmony_ci        BASIC_BLOCK(2, -1)
383b1994897Sopenharmony_ci        {
384b1994897Sopenharmony_ci            INST(12, Opcode::Add).u32().Inputs(1, 5);
385b1994897Sopenharmony_ci            INST(13, Opcode::ReturnVoid);
386b1994897Sopenharmony_ci        }
387b1994897Sopenharmony_ci    }
388b1994897Sopenharmony_ci}
389b1994897Sopenharmony_ci
390b1994897Sopenharmony_ciTEST_F(InstTest, LenArray)
391b1994897Sopenharmony_ci{
392b1994897Sopenharmony_ci    GRAPH(GetGraph())
393b1994897Sopenharmony_ci    {
394b1994897Sopenharmony_ci        PARAMETER(0, 40).ref();
395b1994897Sopenharmony_ci        BASIC_BLOCK(2, -1)
396b1994897Sopenharmony_ci        {
397b1994897Sopenharmony_ci            INST(1, Opcode::LenArray).s32().Inputs(0);
398b1994897Sopenharmony_ci            INST(2, Opcode::ReturnVoid);
399b1994897Sopenharmony_ci        }
400b1994897Sopenharmony_ci    }
401b1994897Sopenharmony_ci}
402b1994897Sopenharmony_ci
403b1994897Sopenharmony_ciTEST_F(InstTest, Call)
404b1994897Sopenharmony_ci{
405b1994897Sopenharmony_ci    GRAPH(GetGraph())
406b1994897Sopenharmony_ci    {
407b1994897Sopenharmony_ci        PARAMETER(0, 1).ref();
408b1994897Sopenharmony_ci        PARAMETER(1, 2).u32();
409b1994897Sopenharmony_ci        PARAMETER(2, 4).u16();
410b1994897Sopenharmony_ci        PARAMETER(3, 5).u8();
411b1994897Sopenharmony_ci        PARAMETER(4, 8).s64();
412b1994897Sopenharmony_ci        BASIC_BLOCK(2, -1)
413b1994897Sopenharmony_ci        {
414b1994897Sopenharmony_ci            using namespace DataType;
415b1994897Sopenharmony_ci            INST(8, Opcode::SaveState).NoVregs();
416b1994897Sopenharmony_ci            INST(5, Opcode::CallVirtual).s32().InputsAutoType(0, 2, 4, 8);
417b1994897Sopenharmony_ci            INST(6, Opcode::CallStatic).b().InputsAutoType(1, 3, 4, 5, 8);
418b1994897Sopenharmony_ci            INST(7, Opcode::ReturnVoid);
419b1994897Sopenharmony_ci        }
420b1994897Sopenharmony_ci    }
421b1994897Sopenharmony_ci}
422b1994897Sopenharmony_ci
423b1994897Sopenharmony_ciTEST_F(InstTest, BinaryImmOperation)
424b1994897Sopenharmony_ci{
425b1994897Sopenharmony_ci    GRAPH(GetGraph())
426b1994897Sopenharmony_ci    {
427b1994897Sopenharmony_ci        PARAMETER(0, 1).u64();
428b1994897Sopenharmony_ci        PARAMETER(1, 4).s32();
429b1994897Sopenharmony_ci        BASIC_BLOCK(2, -1)
430b1994897Sopenharmony_ci        {
431b1994897Sopenharmony_ci            INST(2, Opcode::AddI).s32().Imm(10ULL).Inputs(1);
432b1994897Sopenharmony_ci            INST(3, Opcode::SubI).s32().Imm(15ULL).Inputs(2);
433b1994897Sopenharmony_ci            INST(4, Opcode::AndI).u64().Imm(15ULL).Inputs(0);
434b1994897Sopenharmony_ci            INST(5, Opcode::OrI).u64().Imm(1ULL).Inputs(4);
435b1994897Sopenharmony_ci            INST(6, Opcode::XorI).u64().Imm(10ULL).Inputs(5);
436b1994897Sopenharmony_ci            INST(7, Opcode::ShlI).u64().Imm(5ULL).Inputs(6);
437b1994897Sopenharmony_ci            INST(8, Opcode::ShrI).u64().Imm(5ULL).Inputs(7);
438b1994897Sopenharmony_ci            INST(9, Opcode::AShrI).s32().Imm(4ULL).Inputs(3);
439b1994897Sopenharmony_ci            INST(10, Opcode::ReturnVoid);
440b1994897Sopenharmony_ci        }
441b1994897Sopenharmony_ci    }
442b1994897Sopenharmony_ci}
443b1994897Sopenharmony_ci
444b1994897Sopenharmony_ciTEST_F(InstTest, Fcmp)
445b1994897Sopenharmony_ci{
446b1994897Sopenharmony_ci    GRAPH(GetGraph())
447b1994897Sopenharmony_ci    {
448b1994897Sopenharmony_ci        PARAMETER(0, 0).f32();
449b1994897Sopenharmony_ci        PARAMETER(1, 1).f32();
450b1994897Sopenharmony_ci        PARAMETER(2, 2).f64();
451b1994897Sopenharmony_ci        PARAMETER(3, 3).f64();
452b1994897Sopenharmony_ci        BASIC_BLOCK(2, -1)
453b1994897Sopenharmony_ci        {
454b1994897Sopenharmony_ci            INST(4, Opcode::Cmp).s32().Inputs(0, 1);
455b1994897Sopenharmony_ci            INST(5, Opcode::Cmp).s32().Inputs(2, 3);
456b1994897Sopenharmony_ci            INST(6, Opcode::ReturnVoid);
457b1994897Sopenharmony_ci        }
458b1994897Sopenharmony_ci    }
459b1994897Sopenharmony_ci    GraphChecker(GetGraph()).Check();
460b1994897Sopenharmony_ci    auto inst4 = static_cast<CmpInst *>(&INS(4));
461b1994897Sopenharmony_ci    auto inst5 = static_cast<CmpInst *>(&INS(5));
462b1994897Sopenharmony_ci    inst4->SetFcmpl();
463b1994897Sopenharmony_ci    ASSERT_EQ(inst4->IsFcmpg(), false);
464b1994897Sopenharmony_ci    ASSERT_EQ(inst4->IsFcmpl(), true);
465b1994897Sopenharmony_ci    inst4->SetFcmpl(true);
466b1994897Sopenharmony_ci    ASSERT_EQ(inst4->IsFcmpg(), false);
467b1994897Sopenharmony_ci    ASSERT_EQ(inst4->IsFcmpl(), true);
468b1994897Sopenharmony_ci    inst4->SetFcmpl(false);
469b1994897Sopenharmony_ci    ASSERT_EQ(inst4->IsFcmpg(), true);
470b1994897Sopenharmony_ci    ASSERT_EQ(inst4->IsFcmpl(), false);
471b1994897Sopenharmony_ci    inst5->SetFcmpg();
472b1994897Sopenharmony_ci    ASSERT_EQ(inst5->IsFcmpg(), true);
473b1994897Sopenharmony_ci    ASSERT_EQ(inst5->IsFcmpl(), false);
474b1994897Sopenharmony_ci    inst5->SetFcmpg(true);
475b1994897Sopenharmony_ci    ASSERT_EQ(inst5->IsFcmpg(), true);
476b1994897Sopenharmony_ci    ASSERT_EQ(inst5->IsFcmpl(), false);
477b1994897Sopenharmony_ci    inst5->SetFcmpg(false);
478b1994897Sopenharmony_ci    ASSERT_EQ(inst5->IsFcmpg(), false);
479b1994897Sopenharmony_ci    ASSERT_EQ(inst5->IsFcmpl(), true);
480b1994897Sopenharmony_ci}
481b1994897Sopenharmony_ci
482b1994897Sopenharmony_ciTEST_F(InstTest, SpillFill)
483b1994897Sopenharmony_ci{
484b1994897Sopenharmony_ci    Register R0 = 0;
485b1994897Sopenharmony_ci    Register R1 = 1;
486b1994897Sopenharmony_ci    StackSlot slot0 = 0;
487b1994897Sopenharmony_ci    StackSlot slot1 = 1;
488b1994897Sopenharmony_ci
489b1994897Sopenharmony_ci    auto spill_fill_inst = GetGraph()->CreateInstSpillFill();
490b1994897Sopenharmony_ci    spill_fill_inst->AddFill(slot0, R0, DataType::UINT64);
491b1994897Sopenharmony_ci    spill_fill_inst->AddMove(R0, R1, DataType::UINT64);
492b1994897Sopenharmony_ci    spill_fill_inst->AddSpill(R1, slot1, DataType::UINT64);
493b1994897Sopenharmony_ci
494b1994897Sopenharmony_ci    ASSERT_EQ(spill_fill_inst->GetSpillFills().size(), 3U);
495b1994897Sopenharmony_ci}
496b1994897Sopenharmony_ci
497b1994897Sopenharmony_ciTEST_F(InstTest, RemovePhiInput)
498b1994897Sopenharmony_ci{
499b1994897Sopenharmony_ci    GRAPH(GetGraph())
500b1994897Sopenharmony_ci    {
501b1994897Sopenharmony_ci        CONSTANT(0, 0);
502b1994897Sopenharmony_ci        CONSTANT(1, 1);
503b1994897Sopenharmony_ci        CONSTANT(2, 2);
504b1994897Sopenharmony_ci        BASIC_BLOCK(2, 3, 5)
505b1994897Sopenharmony_ci        {
506b1994897Sopenharmony_ci            INST(5, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(0, 1);
507b1994897Sopenharmony_ci            INST(6, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(5);
508b1994897Sopenharmony_ci        }
509b1994897Sopenharmony_ci        BASIC_BLOCK(3, 5) {}
510b1994897Sopenharmony_ci        BASIC_BLOCK(5, -1)
511b1994897Sopenharmony_ci        {
512b1994897Sopenharmony_ci            INST(3, Opcode::Phi).u64().Inputs({{2, 0}, {3, 1}});
513b1994897Sopenharmony_ci            INST(4, Opcode::ReturnVoid);
514b1994897Sopenharmony_ci        }
515b1994897Sopenharmony_ci    }
516b1994897Sopenharmony_ci    auto init_inputs = INS(3).GetInputs();
517b1994897Sopenharmony_ci    auto init_preds = BB(5).GetPredsBlocks();
518b1994897Sopenharmony_ci
519b1994897Sopenharmony_ci    auto pred_bb_idx = INS(3).CastToPhi()->GetPredBlockIndex(&BB(3));
520b1994897Sopenharmony_ci    BB(5).RemovePred(&BB(3));
521b1994897Sopenharmony_ci    INS(3).RemoveInput(pred_bb_idx);
522b1994897Sopenharmony_ci
523b1994897Sopenharmony_ci    auto curr_inputs = INS(3).GetInputs();
524b1994897Sopenharmony_ci    auto curr_preds = BB(5).GetPredsBlocks();
525b1994897Sopenharmony_ci    for (size_t idx = 0; idx < curr_inputs.size(); idx++) {
526b1994897Sopenharmony_ci        if (idx != pred_bb_idx) {
527b1994897Sopenharmony_ci            ASSERT_EQ(init_inputs[idx].GetInst(), curr_inputs[idx].GetInst());
528b1994897Sopenharmony_ci            ASSERT_EQ(init_preds[idx], curr_preds[idx]);
529b1994897Sopenharmony_ci        } else {
530b1994897Sopenharmony_ci            ASSERT_EQ(init_inputs.rbegin()->GetInst(), curr_inputs[idx].GetInst());
531b1994897Sopenharmony_ci            ASSERT_EQ(init_preds.back(), curr_preds[idx]);
532b1994897Sopenharmony_ci        }
533b1994897Sopenharmony_ci    }
534b1994897Sopenharmony_ci}
535b1994897Sopenharmony_ci
536b1994897Sopenharmony_ci/**
537b1994897Sopenharmony_ci * Test creating instruction with huge dynamic inputs amount
538b1994897Sopenharmony_ci */
539b1994897Sopenharmony_ciTEST_F(InstTest, HugeDynamicOperandsAmount)
540b1994897Sopenharmony_ci{
541b1994897Sopenharmony_ci    auto graph = CreateGraphStartEndBlocks();
542b1994897Sopenharmony_ci    const size_t COUNT = 1000;
543b1994897Sopenharmony_ci    auto save_state = graph->CreateInstSaveState();
544b1994897Sopenharmony_ci
545b1994897Sopenharmony_ci    for (size_t i = 0; i < COUNT; i++) {
546b1994897Sopenharmony_ci        save_state->AppendInput(graph->FindOrCreateConstant(i));
547b1994897Sopenharmony_ci        save_state->SetVirtualRegister(i, VirtualRegister(i, false));
548b1994897Sopenharmony_ci    }
549b1994897Sopenharmony_ci
550b1994897Sopenharmony_ci    for (size_t i = 0; i < COUNT; i++) {
551b1994897Sopenharmony_ci        auto user = graph->FindOrCreateConstant(i)->GetUsers().begin()->GetInst();
552b1994897Sopenharmony_ci        ASSERT_EQ(user, save_state);
553b1994897Sopenharmony_ci    }
554b1994897Sopenharmony_ci}
555b1994897Sopenharmony_ci
556b1994897Sopenharmony_ciTEST_F(InstTest, FloatConstants)
557b1994897Sopenharmony_ci{
558b1994897Sopenharmony_ci    auto graph = CreateGraphStartEndBlocks();
559b1994897Sopenharmony_ci    graph->GetStartBlock()->AddSucc(graph->GetEndBlock());
560b1994897Sopenharmony_ci    auto positiv_zero_float = graph->FindOrCreateConstant(0.0f);
561b1994897Sopenharmony_ci    auto negativ_zero_float = graph->FindOrCreateConstant(-0.0f);
562b1994897Sopenharmony_ci    auto positiv_zero_double = graph->FindOrCreateConstant(0.0);
563b1994897Sopenharmony_ci    auto negativ_zero_double = graph->FindOrCreateConstant(-0.0);
564b1994897Sopenharmony_ci
565b1994897Sopenharmony_ci    ASSERT_NE(positiv_zero_float, negativ_zero_float);
566b1994897Sopenharmony_ci    ASSERT_NE(positiv_zero_double, negativ_zero_double);
567b1994897Sopenharmony_ci}
568b1994897Sopenharmony_ci
569b1994897Sopenharmony_ciTEST_F(InstTest, Flags)
570b1994897Sopenharmony_ci{
571b1994897Sopenharmony_ci    auto initial_mask = inst_flags::GetFlagsMask(Opcode::LoadObject);
572b1994897Sopenharmony_ci    auto inst = GetGraph()->CreateInstLoadObject();
573b1994897Sopenharmony_ci    ASSERT_EQ(initial_mask, inst->GetFlagsMask());
574b1994897Sopenharmony_ci    ASSERT_EQ(inst->GetFlagsMask(), initial_mask);
575b1994897Sopenharmony_ci    ASSERT_TRUE(inst->IsLoad());
576b1994897Sopenharmony_ci    inst->SetFlag(inst_flags::ALLOC);
577b1994897Sopenharmony_ci    ASSERT_EQ(inst->GetFlagsMask(), initial_mask | inst_flags::ALLOC);
578b1994897Sopenharmony_ci    inst->ClearFlag(inst_flags::LOAD);
579b1994897Sopenharmony_ci    ASSERT_FALSE(inst->IsLoad());
580b1994897Sopenharmony_ci    ASSERT_EQ(inst->GetFlagsMask(), (initial_mask | inst_flags::ALLOC) & ~inst_flags::LOAD);
581b1994897Sopenharmony_ci}
582b1994897Sopenharmony_ci
583b1994897Sopenharmony_ciTEST_F(InstTest, IntrinsicFlags)
584b1994897Sopenharmony_ci{
585b1994897Sopenharmony_ci    ArenaAllocator allocator {SpaceType::SPACE_TYPE_COMPILER};
586b1994897Sopenharmony_ci#include "intrinsic_flags_test.inl"
587b1994897Sopenharmony_ci}
588b1994897Sopenharmony_ci
589b1994897Sopenharmony_ci}  // namespace panda::compiler
590