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#ifndef BYTECODE_OPTIMIZER_TESTS_COMMON_H
17b1994897Sopenharmony_ci#define BYTECODE_OPTIMIZER_TESTS_COMMON_H
18b1994897Sopenharmony_ci
19b1994897Sopenharmony_ci#include <gtest/gtest.h>
20b1994897Sopenharmony_ci#include <string>
21b1994897Sopenharmony_ci#include <string_view>
22b1994897Sopenharmony_ci
23b1994897Sopenharmony_ci#include "assembler/assembly-emitter.h"
24b1994897Sopenharmony_ci#include "assembler/assembly-parser.h"
25b1994897Sopenharmony_ci#include "assembler/assembly-program.h"
26b1994897Sopenharmony_ci#include "assembler/extensions/extensions.h"
27b1994897Sopenharmony_ci#include "canonicalization.h"
28b1994897Sopenharmony_ci#include "class_data_accessor-inl.h"
29b1994897Sopenharmony_ci#include "codegen.h"
30b1994897Sopenharmony_ci#include "compiler/compiler_options.h"
31b1994897Sopenharmony_ci#include "compiler/optimizer/analysis/rpo.h"
32b1994897Sopenharmony_ci#include "compiler/optimizer/ir/datatype.h"
33b1994897Sopenharmony_ci#include "compiler/optimizer/ir/inst.h"
34b1994897Sopenharmony_ci#include "compiler/optimizer/ir/ir_constructor.h"
35b1994897Sopenharmony_ci#include "compiler/optimizer/ir_builder/ir_builder.h"
36b1994897Sopenharmony_ci#include "compiler/optimizer/optimizations/cleanup.h"
37b1994897Sopenharmony_ci#include "compiler/optimizer/optimizations/lowering.h"
38b1994897Sopenharmony_ci#include "compiler/optimizer/optimizations/regalloc/reg_alloc_linear_scan.h"
39b1994897Sopenharmony_ci#include "file_items.h"
40b1994897Sopenharmony_ci#include "ir_interface.h"
41b1994897Sopenharmony_ci#include "libpandabase/utils/logger.h"
42b1994897Sopenharmony_ci#include "mem/arena_allocator.h"
43b1994897Sopenharmony_ci#include "mem/pool_manager.h"
44b1994897Sopenharmony_ci#include "method_data_accessor-inl.h"
45b1994897Sopenharmony_ci#include "optimize_bytecode.h"
46b1994897Sopenharmony_ci#include "reg_encoder.h"
47b1994897Sopenharmony_ci#include "runtime_adapter.h"
48b1994897Sopenharmony_ci
49b1994897Sopenharmony_cinamespace panda::bytecodeopt {
50b1994897Sopenharmony_ci
51b1994897Sopenharmony_ciusing compiler::BasicBlock;
52b1994897Sopenharmony_ciusing compiler::Graph;
53b1994897Sopenharmony_ciusing compiler::Input;
54b1994897Sopenharmony_ciusing compiler::Inst;
55b1994897Sopenharmony_ciusing compiler::Opcode;
56b1994897Sopenharmony_ci
57b1994897Sopenharmony_cistruct RuntimeInterfaceMock : public compiler::RuntimeInterface {
58b1994897Sopenharmony_ci    size_t argument_count {0};
59b1994897Sopenharmony_ci    bool is_constructor {true};
60b1994897Sopenharmony_ci
61b1994897Sopenharmony_ci    explicit RuntimeInterfaceMock(size_t arg_count) : RuntimeInterfaceMock(arg_count, true) {}
62b1994897Sopenharmony_ci
63b1994897Sopenharmony_ci    RuntimeInterfaceMock(size_t arg_count, bool is_ctor) : argument_count(arg_count), is_constructor(is_ctor) {}
64b1994897Sopenharmony_ci
65b1994897Sopenharmony_ci    size_t GetMethodTotalArgumentsCount([[maybe_unused]] MethodPtr method) const override
66b1994897Sopenharmony_ci    {
67b1994897Sopenharmony_ci        return argument_count;
68b1994897Sopenharmony_ci    }
69b1994897Sopenharmony_ci
70b1994897Sopenharmony_ci    bool IsConstructor([[maybe_unused]] MethodPtr method, [[maybe_unused]] uint32_t class_id) override
71b1994897Sopenharmony_ci    {
72b1994897Sopenharmony_ci        return is_constructor;
73b1994897Sopenharmony_ci    }
74b1994897Sopenharmony_ci};
75b1994897Sopenharmony_ci
76b1994897Sopenharmony_ciclass IrInterfaceTest : public BytecodeOptIrInterface {
77b1994897Sopenharmony_cipublic:
78b1994897Sopenharmony_ci    explicit IrInterfaceTest(pandasm::Program *prog = nullptr,
79b1994897Sopenharmony_ci                             const pandasm::AsmEmitter::PandaFileToPandaAsmMaps *maps = nullptr)
80b1994897Sopenharmony_ci        : BytecodeOptIrInterface(maps, prog)
81b1994897Sopenharmony_ci    {
82b1994897Sopenharmony_ci    }
83b1994897Sopenharmony_ci
84b1994897Sopenharmony_ci    std::string GetFieldIdByOffset([[maybe_unused]] uint32_t offset) const override
85b1994897Sopenharmony_ci    {
86b1994897Sopenharmony_ci        return "";
87b1994897Sopenharmony_ci    }
88b1994897Sopenharmony_ci
89b1994897Sopenharmony_ci    std::string GetTypeIdByOffset([[maybe_unused]] uint32_t offset) const override
90b1994897Sopenharmony_ci    {
91b1994897Sopenharmony_ci        return IsMapsSet() ? BytecodeOptIrInterface::GetTypeIdByOffset(offset) : "";
92b1994897Sopenharmony_ci    }
93b1994897Sopenharmony_ci
94b1994897Sopenharmony_ci    std::string GetMethodIdByOffset([[maybe_unused]] uint32_t offset) const override
95b1994897Sopenharmony_ci    {
96b1994897Sopenharmony_ci        return "";
97b1994897Sopenharmony_ci    }
98b1994897Sopenharmony_ci
99b1994897Sopenharmony_ci    std::string GetStringIdByOffset([[maybe_unused]] uint32_t offset) const override
100b1994897Sopenharmony_ci    {
101b1994897Sopenharmony_ci        return "";
102b1994897Sopenharmony_ci    }
103b1994897Sopenharmony_ci};
104b1994897Sopenharmony_ci
105b1994897Sopenharmony_cinamespace test {
106b1994897Sopenharmony_ci
107b1994897Sopenharmony_ciextern std::string glob_argv0;
108b1994897Sopenharmony_ci
109b1994897Sopenharmony_ci}  // namespace test
110b1994897Sopenharmony_ci
111b1994897Sopenharmony_ciclass CommonTest : public ::testing::Test {
112b1994897Sopenharmony_cipublic:
113b1994897Sopenharmony_ci    CommonTest()
114b1994897Sopenharmony_ci    {
115b1994897Sopenharmony_ci        compiler::options.SetCompilerUseSafepoint(false);
116b1994897Sopenharmony_ci        compiler::options.SetCompilerSupportInitObjectInst(true);
117b1994897Sopenharmony_ci
118b1994897Sopenharmony_ci        mem::MemConfig::Initialize(128_MB, 64_MB, 64_MB, 32_MB);
119b1994897Sopenharmony_ci        PoolManager::Initialize();
120b1994897Sopenharmony_ci        allocator_ = new ArenaAllocator(SpaceType::SPACE_TYPE_INTERNAL);
121b1994897Sopenharmony_ci        local_allocator_ = new ArenaAllocator(SpaceType::SPACE_TYPE_INTERNAL);
122b1994897Sopenharmony_ci        builder_ = new compiler::IrConstructor();
123b1994897Sopenharmony_ci
124b1994897Sopenharmony_ci        Logger::InitializeStdLogging(Logger::Level::ERROR,
125b1994897Sopenharmony_ci                                     panda::Logger::ComponentMask().set(Logger::Component::BYTECODE_OPTIMIZER));
126b1994897Sopenharmony_ci    }
127b1994897Sopenharmony_ci    virtual ~CommonTest()
128b1994897Sopenharmony_ci    {
129b1994897Sopenharmony_ci        delete allocator_;
130b1994897Sopenharmony_ci        delete local_allocator_;
131b1994897Sopenharmony_ci        delete builder_;
132b1994897Sopenharmony_ci        PoolManager::Finalize();
133b1994897Sopenharmony_ci        mem::MemConfig::Finalize();
134b1994897Sopenharmony_ci
135b1994897Sopenharmony_ci        Logger::Destroy();
136b1994897Sopenharmony_ci    }
137b1994897Sopenharmony_ci    ArenaAllocator *GetAllocator()
138b1994897Sopenharmony_ci    {
139b1994897Sopenharmony_ci        return allocator_;
140b1994897Sopenharmony_ci    }
141b1994897Sopenharmony_ci    ArenaAllocator *GetLocalAllocator()
142b1994897Sopenharmony_ci    {
143b1994897Sopenharmony_ci        return local_allocator_;
144b1994897Sopenharmony_ci    }
145b1994897Sopenharmony_ci
146b1994897Sopenharmony_ci    compiler::Graph *CreateEmptyGraph(bool isDynamic = false)
147b1994897Sopenharmony_ci    {
148b1994897Sopenharmony_ci        auto *graph =
149b1994897Sopenharmony_ci            GetAllocator()->New<compiler::Graph>(GetAllocator(), GetLocalAllocator(), Arch::NONE, isDynamic, true);
150b1994897Sopenharmony_ci        return graph;
151b1994897Sopenharmony_ci    }
152b1994897Sopenharmony_ci
153b1994897Sopenharmony_ci    compiler::Graph *GetGraph()
154b1994897Sopenharmony_ci    {
155b1994897Sopenharmony_ci        return graph_;
156b1994897Sopenharmony_ci    }
157b1994897Sopenharmony_ci
158b1994897Sopenharmony_ci    void SetGraph(compiler::Graph *graph)
159b1994897Sopenharmony_ci    {
160b1994897Sopenharmony_ci        graph_ = graph;
161b1994897Sopenharmony_ci    }
162b1994897Sopenharmony_ci
163b1994897Sopenharmony_ci    bool FuncHasInst(pandasm::Function *func, pandasm::Opcode opcode)
164b1994897Sopenharmony_ci    {
165b1994897Sopenharmony_ci        for (const auto &inst : func->ins) {
166b1994897Sopenharmony_ci            if (inst.opcode == opcode) {
167b1994897Sopenharmony_ci                return true;
168b1994897Sopenharmony_ci            }
169b1994897Sopenharmony_ci        }
170b1994897Sopenharmony_ci        return false;
171b1994897Sopenharmony_ci    }
172b1994897Sopenharmony_ci
173b1994897Sopenharmony_ciprotected:
174b1994897Sopenharmony_ci    compiler::IrConstructor *builder_;
175b1994897Sopenharmony_ci
176b1994897Sopenharmony_ciprivate:
177b1994897Sopenharmony_ci    ArenaAllocator *allocator_;
178b1994897Sopenharmony_ci    ArenaAllocator *local_allocator_;
179b1994897Sopenharmony_ci    compiler::Graph *graph_ {nullptr};
180b1994897Sopenharmony_ci};
181b1994897Sopenharmony_ci
182b1994897Sopenharmony_ciclass AsmTest : public CommonTest {
183b1994897Sopenharmony_cipublic:
184b1994897Sopenharmony_ci    bool ParseToGraph(const std::string &source, const std::string &func_name, const char *file_name = "test.pb")
185b1994897Sopenharmony_ci    {
186b1994897Sopenharmony_ci        panda::pandasm::Parser parser;
187b1994897Sopenharmony_ci        auto res = parser.Parse(source, file_name);
188b1994897Sopenharmony_ci        if (parser.ShowError().err != pandasm::Error::ErrorType::ERR_NONE) {
189b1994897Sopenharmony_ci            std::cerr << "Parse failed: " << parser.ShowError().message << std::endl
190b1994897Sopenharmony_ci                      << parser.ShowError().whole_line << std::endl;
191b1994897Sopenharmony_ci            ADD_FAILURE();
192b1994897Sopenharmony_ci            return false;
193b1994897Sopenharmony_ci        }
194b1994897Sopenharmony_ci        auto &prog = res.Value();
195b1994897Sopenharmony_ci        return ParseToGraph(&prog, func_name);
196b1994897Sopenharmony_ci    }
197b1994897Sopenharmony_ci
198b1994897Sopenharmony_ci    bool ParseToGraph(pandasm::Program *prog, const std::string &func_name)
199b1994897Sopenharmony_ci    {
200b1994897Sopenharmony_ci        pfile_ = pandasm::AsmEmitter::Emit(*prog, &maps_);
201b1994897Sopenharmony_ci        ir_interface_ = std::make_unique<bytecodeopt::BytecodeOptIrInterface>(&maps_, prog);
202b1994897Sopenharmony_ci
203b1994897Sopenharmony_ci        if (pfile_ == nullptr) {
204b1994897Sopenharmony_ci            ADD_FAILURE();
205b1994897Sopenharmony_ci            return false;
206b1994897Sopenharmony_ci        }
207b1994897Sopenharmony_ci
208b1994897Sopenharmony_ci        auto ptr_file = pfile_.get();
209b1994897Sopenharmony_ci        if (ptr_file == nullptr) {
210b1994897Sopenharmony_ci            ADD_FAILURE();
211b1994897Sopenharmony_ci            return false;
212b1994897Sopenharmony_ci        }
213b1994897Sopenharmony_ci
214b1994897Sopenharmony_ci        compiler::Graph *temp_graph = nullptr;
215b1994897Sopenharmony_ci
216b1994897Sopenharmony_ci        for (uint32_t id : ptr_file->GetClasses()) {
217b1994897Sopenharmony_ci            panda_file::File::EntityId record_id {id};
218b1994897Sopenharmony_ci
219b1994897Sopenharmony_ci            if (ptr_file->IsExternal(record_id)) {
220b1994897Sopenharmony_ci                continue;
221b1994897Sopenharmony_ci            }
222b1994897Sopenharmony_ci
223b1994897Sopenharmony_ci            panda_file::ClassDataAccessor cda {*ptr_file, record_id};
224b1994897Sopenharmony_ci            cda.EnumerateMethods([&temp_graph, ptr_file, func_name, this](panda_file::MethodDataAccessor &mda) {
225b1994897Sopenharmony_ci                auto name_id = mda.GetNameId();
226b1994897Sopenharmony_ci                auto str = ptr_file->GetStringData(name_id).data;
227b1994897Sopenharmony_ci                bool is_equal = (std::string(func_name) == std::string(reinterpret_cast<const char *>(str)));
228b1994897Sopenharmony_ci                auto method_ptr =
229b1994897Sopenharmony_ci                    reinterpret_cast<compiler::RuntimeInterface::MethodPtr>(mda.GetMethodId().GetOffset());
230b1994897Sopenharmony_ci
231b1994897Sopenharmony_ci                if (!mda.IsExternal() && !mda.IsAbstract() && !mda.IsNative() && is_equal) {
232b1994897Sopenharmony_ci                    auto adapter = allocator_.New<BytecodeOptimizerRuntimeAdapter>(mda.GetPandaFile());
233b1994897Sopenharmony_ci                    temp_graph = allocator_.New<compiler::Graph>(&allocator_, &local_allocator_, Arch::NONE, method_ptr,
234b1994897Sopenharmony_ci                                                                 adapter, false, nullptr, false, true);
235b1994897Sopenharmony_ci                    ASSERT_NE(temp_graph, nullptr);
236b1994897Sopenharmony_ci                    ASSERT_TRUE(temp_graph->RunPass<compiler::IrBuilder>());
237b1994897Sopenharmony_ci                }
238b1994897Sopenharmony_ci            });
239b1994897Sopenharmony_ci        }
240b1994897Sopenharmony_ci
241b1994897Sopenharmony_ci        if (temp_graph != nullptr) {
242b1994897Sopenharmony_ci            SetGraph(temp_graph);
243b1994897Sopenharmony_ci            return true;
244b1994897Sopenharmony_ci        }
245b1994897Sopenharmony_ci        return false;
246b1994897Sopenharmony_ci    }
247b1994897Sopenharmony_ci
248b1994897Sopenharmony_ci    bytecodeopt::BytecodeOptIrInterface *GetIrInterface()
249b1994897Sopenharmony_ci    {
250b1994897Sopenharmony_ci        return ir_interface_.get();
251b1994897Sopenharmony_ci    }
252b1994897Sopenharmony_ci
253b1994897Sopenharmony_ci    pandasm::AsmEmitter::PandaFileToPandaAsmMaps *GetMaps()
254b1994897Sopenharmony_ci    {
255b1994897Sopenharmony_ci        return &maps_;
256b1994897Sopenharmony_ci    }
257b1994897Sopenharmony_ci
258b1994897Sopenharmony_ci    auto GetFile()
259b1994897Sopenharmony_ci    {
260b1994897Sopenharmony_ci        return pfile_.get();
261b1994897Sopenharmony_ci    }
262b1994897Sopenharmony_ci
263b1994897Sopenharmony_ciprivate:
264b1994897Sopenharmony_ci    std::unique_ptr<BytecodeOptIrInterface> ir_interface_;
265b1994897Sopenharmony_ci    pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps_;
266b1994897Sopenharmony_ci    ArenaAllocator allocator_ {SpaceType::SPACE_TYPE_COMPILER};
267b1994897Sopenharmony_ci    ArenaAllocator local_allocator_ {SpaceType::SPACE_TYPE_COMPILER};
268b1994897Sopenharmony_ci    std::unique_ptr<const panda_file::File> pfile_ {nullptr};
269b1994897Sopenharmony_ci};
270b1994897Sopenharmony_ci
271b1994897Sopenharmony_ciclass GraphComparator {
272b1994897Sopenharmony_cipublic:
273b1994897Sopenharmony_ci    bool Compare(Graph *graph1, Graph *graph2)
274b1994897Sopenharmony_ci    {
275b1994897Sopenharmony_ci        graph1->InvalidateAnalysis<compiler::Rpo>();
276b1994897Sopenharmony_ci        graph2->InvalidateAnalysis<compiler::Rpo>();
277b1994897Sopenharmony_ci        if (graph1->GetBlocksRPO().size() != graph2->GetBlocksRPO().size()) {
278b1994897Sopenharmony_ci            std::cerr << "Different number of blocks: " << graph1->GetBlocksRPO().size() << " and "
279b1994897Sopenharmony_ci                      << graph2->GetBlocksRPO().size() << std::endl;
280b1994897Sopenharmony_ci            return false;
281b1994897Sopenharmony_ci        }
282b1994897Sopenharmony_ci        return std::equal(graph1->GetBlocksRPO().begin(), graph1->GetBlocksRPO().end(), graph2->GetBlocksRPO().begin(),
283b1994897Sopenharmony_ci                          graph2->GetBlocksRPO().end(), [this](auto bb1, auto bb2) { return Compare(bb1, bb2); });
284b1994897Sopenharmony_ci    }
285b1994897Sopenharmony_ci
286b1994897Sopenharmony_ci    bool Compare(BasicBlock *block1, BasicBlock *block2)
287b1994897Sopenharmony_ci    {
288b1994897Sopenharmony_ci        if (block1->GetPredsBlocks().size() != block2->GetPredsBlocks().size()) {
289b1994897Sopenharmony_ci            std::cerr << "Different number of preds blocks\n";
290b1994897Sopenharmony_ci            block1->Dump(&std::cout);
291b1994897Sopenharmony_ci            block2->Dump(&std::cout);
292b1994897Sopenharmony_ci            return false;
293b1994897Sopenharmony_ci        }
294b1994897Sopenharmony_ci        if (block1->GetSuccsBlocks().size() != block2->GetSuccsBlocks().size()) {
295b1994897Sopenharmony_ci            std::cerr << "Different number of succs blocks\n";
296b1994897Sopenharmony_ci            block1->Dump(&std::cout);
297b1994897Sopenharmony_ci            block2->Dump(&std::cout);
298b1994897Sopenharmony_ci            return false;
299b1994897Sopenharmony_ci        }
300b1994897Sopenharmony_ci        return std::equal(block1->AllInsts().begin(), block1->AllInsts().end(), block2->AllInsts().begin(),
301b1994897Sopenharmony_ci                          block2->AllInsts().end(), [this](auto inst1, auto inst2) {
302b1994897Sopenharmony_ci                              ASSERT(inst2 != nullptr);
303b1994897Sopenharmony_ci                              bool t = Compare(inst1, inst2);
304b1994897Sopenharmony_ci                              if (!t) {
305b1994897Sopenharmony_ci                                  std::cerr << "Different instructions:\n";
306b1994897Sopenharmony_ci                                  inst1->Dump(&std::cout);
307b1994897Sopenharmony_ci                                  inst2->Dump(&std::cout);
308b1994897Sopenharmony_ci                              }
309b1994897Sopenharmony_ci                              return t;
310b1994897Sopenharmony_ci                          });
311b1994897Sopenharmony_ci    }
312b1994897Sopenharmony_ci
313b1994897Sopenharmony_ci    bool Compare(Inst *inst1, Inst *inst2)
314b1994897Sopenharmony_ci    {
315b1994897Sopenharmony_ci        if (auto it = inst_compare_map_.insert({inst1, inst2}); !it.second) {
316b1994897Sopenharmony_ci            if (inst2 == it.first->second) {
317b1994897Sopenharmony_ci                return true;
318b1994897Sopenharmony_ci            }
319b1994897Sopenharmony_ci            inst_compare_map_.erase(inst1);
320b1994897Sopenharmony_ci            return false;
321b1994897Sopenharmony_ci        }
322b1994897Sopenharmony_ci
323b1994897Sopenharmony_ci        if (inst1->GetOpcode() != inst2->GetOpcode() || inst1->GetType() != inst2->GetType() ||
324b1994897Sopenharmony_ci            inst1->GetInputsCount() != inst2->GetInputsCount()) {
325b1994897Sopenharmony_ci            inst_compare_map_.erase(inst1);
326b1994897Sopenharmony_ci            return false;
327b1994897Sopenharmony_ci        }
328b1994897Sopenharmony_ci
329b1994897Sopenharmony_ci        if (inst1->GetOpcode() == Opcode::Intrinsic || inst1->GetOpcode() == Opcode::Builtin) {
330b1994897Sopenharmony_ci            if (inst1->CastToIntrinsic()->GetIntrinsicId() != inst2->CastToIntrinsic()->GetIntrinsicId()) {
331b1994897Sopenharmony_ci                inst_compare_map_.erase(inst1);
332b1994897Sopenharmony_ci                return false;
333b1994897Sopenharmony_ci            }
334b1994897Sopenharmony_ci        }
335b1994897Sopenharmony_ci
336b1994897Sopenharmony_ci        if (inst1->GetOpcode() != Opcode::Phi) {
337b1994897Sopenharmony_ci            if (!std::equal(
338b1994897Sopenharmony_ci                    inst1->GetInputs().begin(), inst1->GetInputs().end(), inst2->GetInputs().begin(),
339b1994897Sopenharmony_ci                    [this](Input input1, Input input2) { return Compare(input1.GetInst(), input2.GetInst()); })) {
340b1994897Sopenharmony_ci                inst_compare_map_.erase(inst1);
341b1994897Sopenharmony_ci                return false;
342b1994897Sopenharmony_ci            }
343b1994897Sopenharmony_ci        } else {
344b1994897Sopenharmony_ci            for (auto input1 : inst1->GetInputs()) {
345b1994897Sopenharmony_ci                auto it =
346b1994897Sopenharmony_ci                    std::find_if(inst2->GetInputs().begin(), inst2->GetInputs().end(),
347b1994897Sopenharmony_ci                                 [this, &input1](Input input2) { return Compare(input1.GetInst(), input2.GetInst()); });
348b1994897Sopenharmony_ci                if (it == inst2->GetInputs().end()) {
349b1994897Sopenharmony_ci                    inst_compare_map_.erase(inst1);
350b1994897Sopenharmony_ci                    return false;
351b1994897Sopenharmony_ci                }
352b1994897Sopenharmony_ci            }
353b1994897Sopenharmony_ci        }
354b1994897Sopenharmony_ci
355b1994897Sopenharmony_ci#define CAST(Opc) CastTo##Opc()
356b1994897Sopenharmony_ci
357b1994897Sopenharmony_ci#define CHECK(Opc, Getter)                                                                               \
358b1994897Sopenharmony_ci    if (inst1->GetOpcode() == Opcode::Opc && inst1->CAST(Opc)->Getter() != inst2->CAST(Opc)->Getter()) { \
359b1994897Sopenharmony_ci        inst_compare_map_.erase(inst1);                                                                  \
360b1994897Sopenharmony_ci        return false;                                                                                    \
361b1994897Sopenharmony_ci    }
362b1994897Sopenharmony_ci
363b1994897Sopenharmony_ci        CHECK(Constant, GetRawValue)
364b1994897Sopenharmony_ci
365b1994897Sopenharmony_ci        CHECK(Cast, GetOperandsType)
366b1994897Sopenharmony_ci        CHECK(Cmp, GetOperandsType)
367b1994897Sopenharmony_ci
368b1994897Sopenharmony_ci        CHECK(Compare, GetCc)
369b1994897Sopenharmony_ci        CHECK(Compare, GetOperandsType)
370b1994897Sopenharmony_ci
371b1994897Sopenharmony_ci        CHECK(If, GetCc)
372b1994897Sopenharmony_ci        CHECK(If, GetOperandsType)
373b1994897Sopenharmony_ci
374b1994897Sopenharmony_ci        CHECK(IfImm, GetCc)
375b1994897Sopenharmony_ci        CHECK(IfImm, GetImm)
376b1994897Sopenharmony_ci        CHECK(IfImm, GetOperandsType)
377b1994897Sopenharmony_ci
378b1994897Sopenharmony_ci        CHECK(LoadArrayI, GetImm)
379b1994897Sopenharmony_ci        CHECK(LoadArrayPairI, GetImm)
380b1994897Sopenharmony_ci        CHECK(LoadPairPart, GetImm)
381b1994897Sopenharmony_ci        CHECK(StoreArrayI, GetImm)
382b1994897Sopenharmony_ci        CHECK(StoreArrayPairI, GetImm)
383b1994897Sopenharmony_ci        CHECK(BoundsCheckI, GetImm)
384b1994897Sopenharmony_ci        CHECK(ReturnI, GetImm)
385b1994897Sopenharmony_ci        CHECK(AddI, GetImm)
386b1994897Sopenharmony_ci        CHECK(SubI, GetImm)
387b1994897Sopenharmony_ci        CHECK(ShlI, GetImm)
388b1994897Sopenharmony_ci        CHECK(ShrI, GetImm)
389b1994897Sopenharmony_ci        CHECK(AShrI, GetImm)
390b1994897Sopenharmony_ci        CHECK(AndI, GetImm)
391b1994897Sopenharmony_ci        CHECK(OrI, GetImm)
392b1994897Sopenharmony_ci        CHECK(XorI, GetImm)
393b1994897Sopenharmony_ci
394b1994897Sopenharmony_ci        CHECK(LoadStatic, GetVolatile)
395b1994897Sopenharmony_ci        CHECK(StoreStatic, GetVolatile)
396b1994897Sopenharmony_ci        CHECK(LoadObject, GetVolatile)
397b1994897Sopenharmony_ci        CHECK(StoreObject, GetVolatile)
398b1994897Sopenharmony_ci#undef CHECK
399b1994897Sopenharmony_ci#undef CAST
400b1994897Sopenharmony_ci
401b1994897Sopenharmony_ci        if (inst1->GetOpcode() == Opcode::Cmp && IsFloatType(inst1->GetInput(0).GetInst()->GetType())) {
402b1994897Sopenharmony_ci            auto cmp1 = static_cast<compiler::CmpInst *>(inst1);
403b1994897Sopenharmony_ci            auto cmp2 = static_cast<compiler::CmpInst *>(inst2);
404b1994897Sopenharmony_ci            if (cmp1->IsFcmpg() != cmp2->IsFcmpg()) {
405b1994897Sopenharmony_ci                inst_compare_map_.erase(inst1);
406b1994897Sopenharmony_ci                return false;
407b1994897Sopenharmony_ci            }
408b1994897Sopenharmony_ci        }
409b1994897Sopenharmony_ci        for (uint32_t i = 0; i < inst2->GetInputsCount(); i++) {
410b1994897Sopenharmony_ci            if (inst1->GetInputType(i) != inst2->GetInputType(i)) {
411b1994897Sopenharmony_ci                inst_compare_map_.erase(inst1);
412b1994897Sopenharmony_ci                return false;
413b1994897Sopenharmony_ci            }
414b1994897Sopenharmony_ci        }
415b1994897Sopenharmony_ci        return true;
416b1994897Sopenharmony_ci    }
417b1994897Sopenharmony_ci
418b1994897Sopenharmony_ciprivate:
419b1994897Sopenharmony_ci    std::unordered_map<Inst *, Inst *> inst_compare_map_;
420b1994897Sopenharmony_ci};
421b1994897Sopenharmony_ci
422b1994897Sopenharmony_ciclass IrBuilderTest : public AsmTest {
423b1994897Sopenharmony_cipublic:
424b1994897Sopenharmony_ci    void CheckSimple(std::string inst_name, compiler::DataType::Type data_type, std::string inst_type)
425b1994897Sopenharmony_ci    {
426b1994897Sopenharmony_ci        ASSERT(inst_name == "mov" || inst_name == "lda" || inst_name == "sta");
427b1994897Sopenharmony_ci        std::string curr_type;
428b1994897Sopenharmony_ci        if (data_type == compiler::DataType::Type::REFERENCE) {
429b1994897Sopenharmony_ci            curr_type = "i64[]";
430b1994897Sopenharmony_ci        } else {
431b1994897Sopenharmony_ci            curr_type = ToString(data_type);
432b1994897Sopenharmony_ci        }
433b1994897Sopenharmony_ci
434b1994897Sopenharmony_ci        std::string source = ".function " + curr_type + " main(";
435b1994897Sopenharmony_ci        source += curr_type + " a0){\n";
436b1994897Sopenharmony_ci        if (inst_name == "mov") {
437b1994897Sopenharmony_ci            source += "mov" + inst_type + " v0, a0\n";
438b1994897Sopenharmony_ci            source += "lda" + inst_type + " v0\n";
439b1994897Sopenharmony_ci        } else if (inst_name == "lda") {
440b1994897Sopenharmony_ci            source += "lda" + inst_type + " a0\n";
441b1994897Sopenharmony_ci        } else if (inst_name == "sta") {
442b1994897Sopenharmony_ci            source += "lda" + inst_type + " a0\n";
443b1994897Sopenharmony_ci            source += "sta" + inst_type + " v0\n";
444b1994897Sopenharmony_ci            source += "lda" + inst_type + " v0\n";
445b1994897Sopenharmony_ci        } else {
446b1994897Sopenharmony_ci            UNREACHABLE();
447b1994897Sopenharmony_ci        }
448b1994897Sopenharmony_ci        source += "return" + inst_type + "\n";
449b1994897Sopenharmony_ci        source += "}";
450b1994897Sopenharmony_ci
451b1994897Sopenharmony_ci        ASSERT_TRUE(ParseToGraph(source, "main"));
452b1994897Sopenharmony_ci
453b1994897Sopenharmony_ci        auto graph = CreateEmptyGraph();
454b1994897Sopenharmony_ci        GRAPH(graph)
455b1994897Sopenharmony_ci        {
456b1994897Sopenharmony_ci            PARAMETER(0, 0);
457b1994897Sopenharmony_ci            INS(0).SetType(data_type);
458b1994897Sopenharmony_ci
459b1994897Sopenharmony_ci            BASIC_BLOCK(2, -1)
460b1994897Sopenharmony_ci            {
461b1994897Sopenharmony_ci                INST(1, Opcode::Return).Inputs(0);
462b1994897Sopenharmony_ci                INS(1).SetType(data_type);
463b1994897Sopenharmony_ci            }
464b1994897Sopenharmony_ci        }
465b1994897Sopenharmony_ci        ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
466b1994897Sopenharmony_ci    }
467b1994897Sopenharmony_ci
468b1994897Sopenharmony_ci    void CheckSimpleWithImm(std::string inst_name, compiler::DataType::Type data_type, std::string inst_type)
469b1994897Sopenharmony_ci    {
470b1994897Sopenharmony_ci        ASSERT(inst_name == "mov" || inst_name == "fmov" || inst_name == "lda" || inst_name == "flda");
471b1994897Sopenharmony_ci        std::string curr_type = ToString(data_type);
472b1994897Sopenharmony_ci
473b1994897Sopenharmony_ci        std::string source = ".function " + curr_type + " main(){\n";
474b1994897Sopenharmony_ci        if (inst_name == "mov") {
475b1994897Sopenharmony_ci            source += "movi" + inst_type + " v0, 0\n";
476b1994897Sopenharmony_ci            source += "lda" + inst_type + " v0\n";
477b1994897Sopenharmony_ci        } else if (inst_name == "fmov") {
478b1994897Sopenharmony_ci            source += "fmovi" + inst_type + " v0, 0.\n";
479b1994897Sopenharmony_ci            source += "lda" + inst_type + " v0\n";
480b1994897Sopenharmony_ci        } else if (inst_name == "lda") {
481b1994897Sopenharmony_ci            source += "ldai" + inst_type + " 0\n";
482b1994897Sopenharmony_ci        } else if (inst_name == "flda") {
483b1994897Sopenharmony_ci            source += "fldai" + inst_type + " 0.\n";
484b1994897Sopenharmony_ci        } else {
485b1994897Sopenharmony_ci            UNREACHABLE();
486b1994897Sopenharmony_ci        }
487b1994897Sopenharmony_ci        source += "return" + inst_type + "\n";
488b1994897Sopenharmony_ci        source += "}";
489b1994897Sopenharmony_ci
490b1994897Sopenharmony_ci        ASSERT_TRUE(ParseToGraph(source, "main"));
491b1994897Sopenharmony_ci
492b1994897Sopenharmony_ci        auto graph = CreateEmptyGraph();
493b1994897Sopenharmony_ci
494b1994897Sopenharmony_ci        GRAPH(graph)
495b1994897Sopenharmony_ci        {
496b1994897Sopenharmony_ci            CONSTANT(0, 0);
497b1994897Sopenharmony_ci            INS(0).SetType(data_type);
498b1994897Sopenharmony_ci
499b1994897Sopenharmony_ci            BASIC_BLOCK(2, -1)
500b1994897Sopenharmony_ci            {
501b1994897Sopenharmony_ci                INST(1, Opcode::Return).Inputs(0);
502b1994897Sopenharmony_ci                INS(1).SetType(data_type);
503b1994897Sopenharmony_ci            }
504b1994897Sopenharmony_ci        }
505b1994897Sopenharmony_ci        ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
506b1994897Sopenharmony_ci    }
507b1994897Sopenharmony_ci
508b1994897Sopenharmony_ci    void CheckCmp(std::string inst_name, compiler::DataType::Type data_type, std::string inst_type)
509b1994897Sopenharmony_ci    {
510b1994897Sopenharmony_ci        ASSERT(inst_name == "ucmp" || inst_name == "fcmpl" || inst_name == "fcmpg");
511b1994897Sopenharmony_ci        std::string curr_type;
512b1994897Sopenharmony_ci        if (data_type == compiler::DataType::Type::REFERENCE) {
513b1994897Sopenharmony_ci            curr_type = "i64[]";
514b1994897Sopenharmony_ci        } else {
515b1994897Sopenharmony_ci            curr_type = ToString(data_type);
516b1994897Sopenharmony_ci        }
517b1994897Sopenharmony_ci        std::string source = ".function i32 main(";
518b1994897Sopenharmony_ci        source += curr_type + " a0, ";
519b1994897Sopenharmony_ci        source += curr_type + " a1){\n";
520b1994897Sopenharmony_ci        source += "lda" + inst_type + " a0\n";
521b1994897Sopenharmony_ci        source += inst_name + inst_type + " a1\n";
522b1994897Sopenharmony_ci        source += "return\n";
523b1994897Sopenharmony_ci        source += "}";
524b1994897Sopenharmony_ci
525b1994897Sopenharmony_ci        ASSERT_TRUE(ParseToGraph(source, "main"));
526b1994897Sopenharmony_ci
527b1994897Sopenharmony_ci        auto graph = CreateEmptyGraph();
528b1994897Sopenharmony_ci        GRAPH(graph)
529b1994897Sopenharmony_ci        {
530b1994897Sopenharmony_ci            PARAMETER(0, 0);
531b1994897Sopenharmony_ci            INS(0).SetType(data_type);
532b1994897Sopenharmony_ci            PARAMETER(1, 1);
533b1994897Sopenharmony_ci            INS(1).SetType(data_type);
534b1994897Sopenharmony_ci
535b1994897Sopenharmony_ci            BASIC_BLOCK(2, -1)
536b1994897Sopenharmony_ci            {
537b1994897Sopenharmony_ci                INST(2, Opcode::Cmp).s32().Inputs(0, 1);
538b1994897Sopenharmony_ci                INST(3, Opcode::Return).s32().Inputs(2);
539b1994897Sopenharmony_ci            }
540b1994897Sopenharmony_ci        }
541b1994897Sopenharmony_ci        ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
542b1994897Sopenharmony_ci    }
543b1994897Sopenharmony_ci
544b1994897Sopenharmony_ci    void CheckFloatCmp(std::string inst_name, compiler::DataType::Type data_type, std::string inst_type, bool fcmpg)
545b1994897Sopenharmony_ci    {
546b1994897Sopenharmony_ci        ASSERT(inst_name == "fcmpl" || inst_name == "fcmpg");
547b1994897Sopenharmony_ci        std::string curr_type = ToString(data_type);
548b1994897Sopenharmony_ci
549b1994897Sopenharmony_ci        std::string source = ".function i32 main(";
550b1994897Sopenharmony_ci        source += curr_type + " a0, ";
551b1994897Sopenharmony_ci        source += curr_type + " a1){\n";
552b1994897Sopenharmony_ci        source += "lda" + inst_type + " a0\n";
553b1994897Sopenharmony_ci        source += inst_name + inst_type + " a1\n";
554b1994897Sopenharmony_ci        source += "return\n";
555b1994897Sopenharmony_ci        source += "}";
556b1994897Sopenharmony_ci
557b1994897Sopenharmony_ci        ASSERT_TRUE(ParseToGraph(source, "main"));
558b1994897Sopenharmony_ci
559b1994897Sopenharmony_ci        auto graph = CreateEmptyGraph();
560b1994897Sopenharmony_ci        GRAPH(graph)
561b1994897Sopenharmony_ci        {
562b1994897Sopenharmony_ci            PARAMETER(0, 0);
563b1994897Sopenharmony_ci            INS(0).SetType(data_type);
564b1994897Sopenharmony_ci            PARAMETER(1, 1);
565b1994897Sopenharmony_ci            INS(1).SetType(data_type);
566b1994897Sopenharmony_ci
567b1994897Sopenharmony_ci            BASIC_BLOCK(2, -1)
568b1994897Sopenharmony_ci            {
569b1994897Sopenharmony_ci                INST(2, Opcode::Cmp).s32().SrcType(data_type).Fcmpg(fcmpg).Inputs(0, 1);
570b1994897Sopenharmony_ci                INST(3, Opcode::Return).s32().Inputs(2);
571b1994897Sopenharmony_ci            }
572b1994897Sopenharmony_ci        }
573b1994897Sopenharmony_ci        ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
574b1994897Sopenharmony_ci    }
575b1994897Sopenharmony_ci
576b1994897Sopenharmony_ci    template <bool is_obj>
577b1994897Sopenharmony_ci    void CheckCondJumpWithZero(compiler::ConditionCode CC)
578b1994897Sopenharmony_ci    {
579b1994897Sopenharmony_ci        std::string cmd;
580b1994897Sopenharmony_ci        switch (CC) {
581b1994897Sopenharmony_ci            case compiler::ConditionCode::CC_EQ:
582b1994897Sopenharmony_ci                cmd = "jeqz";
583b1994897Sopenharmony_ci                break;
584b1994897Sopenharmony_ci            case compiler::ConditionCode::CC_NE:
585b1994897Sopenharmony_ci                cmd = "jnez";
586b1994897Sopenharmony_ci                break;
587b1994897Sopenharmony_ci            case compiler::ConditionCode::CC_LT:
588b1994897Sopenharmony_ci                cmd = "jltz";
589b1994897Sopenharmony_ci                break;
590b1994897Sopenharmony_ci            case compiler::ConditionCode::CC_GT:
591b1994897Sopenharmony_ci                cmd = "jgtz";
592b1994897Sopenharmony_ci                break;
593b1994897Sopenharmony_ci            case compiler::ConditionCode::CC_LE:
594b1994897Sopenharmony_ci                cmd = "jlez";
595b1994897Sopenharmony_ci                break;
596b1994897Sopenharmony_ci            case compiler::ConditionCode::CC_GE:
597b1994897Sopenharmony_ci                cmd = "jgez";
598b1994897Sopenharmony_ci                break;
599b1994897Sopenharmony_ci            default:
600b1994897Sopenharmony_ci                UNREACHABLE();
601b1994897Sopenharmony_ci        }
602b1994897Sopenharmony_ci
603b1994897Sopenharmony_ci        std::string inst_postfix = "";
604b1994897Sopenharmony_ci        std::string param_type = "i32";
605b1994897Sopenharmony_ci        auto type = compiler::DataType::INT32;
606b1994897Sopenharmony_ci        if constexpr (is_obj) {
607b1994897Sopenharmony_ci            inst_postfix = ".obj";
608b1994897Sopenharmony_ci            param_type = "i64[]";
609b1994897Sopenharmony_ci            type = compiler::DataType::REFERENCE;
610b1994897Sopenharmony_ci        }
611b1994897Sopenharmony_ci
612b1994897Sopenharmony_ci        std::string source = ".function void main(";
613b1994897Sopenharmony_ci        source += param_type + " a0) {\n";
614b1994897Sopenharmony_ci        source += "lda" + inst_postfix + " a0\n";
615b1994897Sopenharmony_ci        source += cmd + inst_postfix + " label\n";
616b1994897Sopenharmony_ci        source += "label: ";
617b1994897Sopenharmony_ci        source += "return.void\n}";
618b1994897Sopenharmony_ci
619b1994897Sopenharmony_ci        ASSERT_TRUE(ParseToGraph(source, "main"));
620b1994897Sopenharmony_ci
621b1994897Sopenharmony_ci        auto graph = CreateEmptyGraph();
622b1994897Sopenharmony_ci        GRAPH(graph)
623b1994897Sopenharmony_ci        {
624b1994897Sopenharmony_ci            PARAMETER(0, 0);
625b1994897Sopenharmony_ci            INS(0).SetType(type);
626b1994897Sopenharmony_ci            CONSTANT(2, 0).s64();
627b1994897Sopenharmony_ci
628b1994897Sopenharmony_ci            BASIC_BLOCK(2, 3, 4)
629b1994897Sopenharmony_ci            {
630b1994897Sopenharmony_ci                INST(1, Opcode::Compare).b().CC(CC).Inputs(0, 2);
631b1994897Sopenharmony_ci                INST(3, Opcode::IfImm)
632b1994897Sopenharmony_ci                    .SrcType(compiler::DataType::BOOL)
633b1994897Sopenharmony_ci                    .CC(compiler::ConditionCode::CC_NE)
634b1994897Sopenharmony_ci                    .Inputs(1)
635b1994897Sopenharmony_ci                    .Imm(0);
636b1994897Sopenharmony_ci            }
637b1994897Sopenharmony_ci            BASIC_BLOCK(3, 4) {}
638b1994897Sopenharmony_ci            BASIC_BLOCK(4, -1)
639b1994897Sopenharmony_ci            {
640b1994897Sopenharmony_ci                INST(4, Opcode::ReturnVoid).v0id();
641b1994897Sopenharmony_ci            }
642b1994897Sopenharmony_ci        }
643b1994897Sopenharmony_ci        ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
644b1994897Sopenharmony_ci    }
645b1994897Sopenharmony_ci
646b1994897Sopenharmony_ci    template <bool is_obj>
647b1994897Sopenharmony_ci    void CheckCondJump(compiler::ConditionCode CC)
648b1994897Sopenharmony_ci    {
649b1994897Sopenharmony_ci        std::string cmd;
650b1994897Sopenharmony_ci        switch (CC) {
651b1994897Sopenharmony_ci            case compiler::ConditionCode::CC_EQ:
652b1994897Sopenharmony_ci                cmd = "jeq";
653b1994897Sopenharmony_ci                break;
654b1994897Sopenharmony_ci            case compiler::ConditionCode::CC_NE:
655b1994897Sopenharmony_ci                cmd = "jne";
656b1994897Sopenharmony_ci                break;
657b1994897Sopenharmony_ci            case compiler::ConditionCode::CC_LT:
658b1994897Sopenharmony_ci                cmd = "jlt";
659b1994897Sopenharmony_ci                break;
660b1994897Sopenharmony_ci            case compiler::ConditionCode::CC_GT:
661b1994897Sopenharmony_ci                cmd = "jgt";
662b1994897Sopenharmony_ci                break;
663b1994897Sopenharmony_ci            case compiler::ConditionCode::CC_LE:
664b1994897Sopenharmony_ci                cmd = "jle";
665b1994897Sopenharmony_ci                break;
666b1994897Sopenharmony_ci            case compiler::ConditionCode::CC_GE:
667b1994897Sopenharmony_ci                cmd = "jge";
668b1994897Sopenharmony_ci                break;
669b1994897Sopenharmony_ci            default:
670b1994897Sopenharmony_ci                UNREACHABLE();
671b1994897Sopenharmony_ci        }
672b1994897Sopenharmony_ci        std::string inst_postfix = "";
673b1994897Sopenharmony_ci        std::string param_type = "i32";
674b1994897Sopenharmony_ci        auto type = compiler::DataType::INT32;
675b1994897Sopenharmony_ci        if constexpr (is_obj) {
676b1994897Sopenharmony_ci            inst_postfix = ".obj";
677b1994897Sopenharmony_ci            param_type = "i64[]";
678b1994897Sopenharmony_ci            type = compiler::DataType::REFERENCE;
679b1994897Sopenharmony_ci        }
680b1994897Sopenharmony_ci
681b1994897Sopenharmony_ci        std::string source = ".function void main(";
682b1994897Sopenharmony_ci        source += param_type + " a0, " + param_type + " a1) {\n";
683b1994897Sopenharmony_ci        source += "lda" + inst_postfix + " a0\n";
684b1994897Sopenharmony_ci        source += cmd + inst_postfix + " a1, label\n";
685b1994897Sopenharmony_ci        source += "label: ";
686b1994897Sopenharmony_ci        source += "return.void\n}";
687b1994897Sopenharmony_ci
688b1994897Sopenharmony_ci        ASSERT_TRUE(ParseToGraph(source, "main"));
689b1994897Sopenharmony_ci
690b1994897Sopenharmony_ci        auto graph = CreateEmptyGraph();
691b1994897Sopenharmony_ci        GRAPH(graph)
692b1994897Sopenharmony_ci        {
693b1994897Sopenharmony_ci            PARAMETER(0, 0);
694b1994897Sopenharmony_ci            INS(0).SetType(type);
695b1994897Sopenharmony_ci            PARAMETER(1, 1);
696b1994897Sopenharmony_ci            INS(1).SetType(type);
697b1994897Sopenharmony_ci
698b1994897Sopenharmony_ci            BASIC_BLOCK(2, 3, 4)
699b1994897Sopenharmony_ci            {
700b1994897Sopenharmony_ci                INST(2, Opcode::Compare).b().CC(CC).Inputs(0, 1);
701b1994897Sopenharmony_ci                INST(3, Opcode::IfImm)
702b1994897Sopenharmony_ci                    .SrcType(compiler::DataType::BOOL)
703b1994897Sopenharmony_ci                    .CC(compiler::ConditionCode::CC_NE)
704b1994897Sopenharmony_ci                    .Imm(0)
705b1994897Sopenharmony_ci                    .Inputs(2);
706b1994897Sopenharmony_ci            }
707b1994897Sopenharmony_ci            BASIC_BLOCK(3, 4) {}
708b1994897Sopenharmony_ci            BASIC_BLOCK(4, -1)
709b1994897Sopenharmony_ci            {
710b1994897Sopenharmony_ci                INST(4, Opcode::ReturnVoid).v0id();
711b1994897Sopenharmony_ci            }
712b1994897Sopenharmony_ci        }
713b1994897Sopenharmony_ci        ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
714b1994897Sopenharmony_ci    }
715b1994897Sopenharmony_ci
716b1994897Sopenharmony_ci    void CheckOtherPasses(panda::pandasm::Program *prog, std::string fun_name)
717b1994897Sopenharmony_ci    {
718b1994897Sopenharmony_ci        GetGraph()->RunPass<compiler::Cleanup>();
719b1994897Sopenharmony_ci        GetGraph()->RunPass<Canonicalization>();
720b1994897Sopenharmony_ci#ifndef NDEBUG
721b1994897Sopenharmony_ci        GetGraph()->SetLowLevelInstructionsEnabled();
722b1994897Sopenharmony_ci#endif
723b1994897Sopenharmony_ci        GetGraph()->RunPass<compiler::Cleanup>();
724b1994897Sopenharmony_ci        GetGraph()->RunPass<compiler::Lowering>();
725b1994897Sopenharmony_ci        GetGraph()->RunPass<compiler::Cleanup>();
726b1994897Sopenharmony_ci        EXPECT_TRUE(GetGraph()->RunPass<compiler::RegAllocLinearScan>(compiler::EmptyRegMask()));
727b1994897Sopenharmony_ci        GetGraph()->RunPass<compiler::Cleanup>();
728b1994897Sopenharmony_ci        EXPECT_TRUE(GetGraph()->RunPass<RegEncoder>());
729b1994897Sopenharmony_ci        ASSERT_TRUE(prog->function_table.find(fun_name) != prog->function_table.end());
730b1994897Sopenharmony_ci        auto &function = prog->function_table.at(fun_name);
731b1994897Sopenharmony_ci        GetGraph()->RunPass<compiler::Cleanup>();
732b1994897Sopenharmony_ci        EXPECT_TRUE(GetGraph()->RunPass<BytecodeGen>(&function, GetIrInterface()));
733b1994897Sopenharmony_ci        auto pf = pandasm::AsmEmitter::Emit(*prog);
734b1994897Sopenharmony_ci        ASSERT_NE(pf, nullptr);
735b1994897Sopenharmony_ci    }
736b1994897Sopenharmony_ci
737b1994897Sopenharmony_ci    void CheckConstArrayFilling(panda::pandasm::Program *prog, [[maybe_unused]] std::string class_name,
738b1994897Sopenharmony_ci                                std::string func_name)
739b1994897Sopenharmony_ci    {
740b1994897Sopenharmony_ci        if (prog->literalarray_table.size() == 1) {
741b1994897Sopenharmony_ci            EXPECT_TRUE(prog->literalarray_table["0"].literals_[0].tag_ == panda_file::LiteralTag::TAGVALUE);
742b1994897Sopenharmony_ci            EXPECT_TRUE(prog->literalarray_table["0"].literals_[1].tag_ == panda_file::LiteralTag::INTEGER);
743b1994897Sopenharmony_ci            EXPECT_TRUE(prog->literalarray_table["0"].literals_[2].tag_ == panda_file::LiteralTag::ARRAY_I32);
744b1994897Sopenharmony_ci            return;
745b1994897Sopenharmony_ci        }
746b1994897Sopenharmony_ci        EXPECT_TRUE(prog->literalarray_table.size() == 8);
747b1994897Sopenharmony_ci        for (const auto &elem : prog->literalarray_table) {
748b1994897Sopenharmony_ci            EXPECT_TRUE(elem.second.literals_.size() == 5);
749b1994897Sopenharmony_ci            EXPECT_TRUE(elem.second.literals_[0].tag_ == panda_file::LiteralTag::TAGVALUE);
750b1994897Sopenharmony_ci            EXPECT_TRUE(elem.second.literals_[1].tag_ == panda_file::LiteralTag::INTEGER);
751b1994897Sopenharmony_ci        }
752b1994897Sopenharmony_ci        EXPECT_TRUE(prog->literalarray_table["7"].literals_[2].tag_ == panda_file::LiteralTag::ARRAY_U1);
753b1994897Sopenharmony_ci        EXPECT_TRUE(prog->literalarray_table["6"].literals_[2].tag_ == panda_file::LiteralTag::ARRAY_I8);
754b1994897Sopenharmony_ci        EXPECT_TRUE(prog->literalarray_table["5"].literals_[2].tag_ == panda_file::LiteralTag::ARRAY_I16);
755b1994897Sopenharmony_ci        EXPECT_TRUE(prog->literalarray_table["4"].literals_[2].tag_ == panda_file::LiteralTag::ARRAY_I32);
756b1994897Sopenharmony_ci        EXPECT_TRUE(prog->literalarray_table["3"].literals_[2].tag_ == panda_file::LiteralTag::ARRAY_I64);
757b1994897Sopenharmony_ci        EXPECT_TRUE(prog->literalarray_table["2"].literals_[2].tag_ == panda_file::LiteralTag::ARRAY_F32);
758b1994897Sopenharmony_ci        EXPECT_TRUE(prog->literalarray_table["1"].literals_[2].tag_ == panda_file::LiteralTag::ARRAY_F64);
759b1994897Sopenharmony_ci        EXPECT_TRUE(prog->literalarray_table["0"].literals_[2].tag_ == panda_file::LiteralTag::ARRAY_STRING);
760b1994897Sopenharmony_ci
761b1994897Sopenharmony_ci        EXPECT_TRUE(GetGraph()->RunPass<RegEncoder>());
762b1994897Sopenharmony_ci        ASSERT_TRUE(prog->function_table.find(func_name) != prog->function_table.end());
763b1994897Sopenharmony_ci        auto &function = prog->function_table.at(func_name);
764b1994897Sopenharmony_ci        EXPECT_TRUE(GetGraph()->RunPass<BytecodeGen>(&function, GetIrInterface()));
765b1994897Sopenharmony_ci        ASSERT(pandasm::AsmEmitter::Emit(class_name + ".panda", *prog, nullptr, nullptr, false));
766b1994897Sopenharmony_ci    }
767b1994897Sopenharmony_ci
768b1994897Sopenharmony_ci    enum CheckConstArrayTypes { ACCESS, SKIP_MULTIDIM_ARRAYS };
769b1994897Sopenharmony_ci
770b1994897Sopenharmony_ci    void CheckConstArray(panda::pandasm::Program *prog, const char *class_name, std::string func_name,
771b1994897Sopenharmony_ci                         CheckConstArrayTypes type)
772b1994897Sopenharmony_ci    {
773b1994897Sopenharmony_ci        options.SetConstArrayResolver(true);
774b1994897Sopenharmony_ci
775b1994897Sopenharmony_ci        panda::pandasm::AsmEmitter::Emit(std::string(class_name) + ".panda", *prog, nullptr, nullptr, false);
776b1994897Sopenharmony_ci        auto temp_name = func_name.substr(func_name.find(".") + 1);
777b1994897Sopenharmony_ci        EXPECT_TRUE(ParseToGraph(prog, temp_name.substr(0, temp_name.find(":"))));
778b1994897Sopenharmony_ci        EXPECT_TRUE(RunOptimizations(GetGraph(), GetIrInterface()));
779b1994897Sopenharmony_ci
780b1994897Sopenharmony_ci        compiler::Inst *const_array_def_inst {nullptr};
781b1994897Sopenharmony_ci        for (auto bb : GetGraph()->GetBlocksRPO()) {
782b1994897Sopenharmony_ci            for (auto inst : bb->AllInsts()) {
783b1994897Sopenharmony_ci                switch (type) {
784b1994897Sopenharmony_ci                    case CheckConstArrayTypes::ACCESS: {
785b1994897Sopenharmony_ci                        if (inst->GetOpcode() == Opcode::LoadConstArray) {
786b1994897Sopenharmony_ci                            const_array_def_inst = inst;
787b1994897Sopenharmony_ci                            continue;
788b1994897Sopenharmony_ci                        }
789b1994897Sopenharmony_ci                        if (inst->GetOpcode() == Opcode::LoadArray) {
790b1994897Sopenharmony_ci                            EXPECT_TRUE(const_array_def_inst != nullptr);
791b1994897Sopenharmony_ci                            EXPECT_TRUE(inst->CastToLoadArray()->GetArray() == const_array_def_inst);
792b1994897Sopenharmony_ci                        }
793b1994897Sopenharmony_ci                        continue;
794b1994897Sopenharmony_ci                    }
795b1994897Sopenharmony_ci                    case CheckConstArrayTypes::SKIP_MULTIDIM_ARRAYS: {
796b1994897Sopenharmony_ci                        EXPECT_TRUE(inst->GetOpcode() != Opcode::LoadConstArray);
797b1994897Sopenharmony_ci                        continue;
798b1994897Sopenharmony_ci                    }
799b1994897Sopenharmony_ci                    default:
800b1994897Sopenharmony_ci                        UNREACHABLE();
801b1994897Sopenharmony_ci                }
802b1994897Sopenharmony_ci            }
803b1994897Sopenharmony_ci        }
804b1994897Sopenharmony_ci
805b1994897Sopenharmony_ci        EXPECT_TRUE(GetGraph()->RunPass<RegEncoder>());
806b1994897Sopenharmony_ci        ASSERT_TRUE(prog->function_table.find(func_name) != prog->function_table.end());
807b1994897Sopenharmony_ci        auto &function = prog->function_table.at(func_name);
808b1994897Sopenharmony_ci        EXPECT_TRUE(GetGraph()->RunPass<BytecodeGen>(&function, GetIrInterface()));
809b1994897Sopenharmony_ci        ASSERT(pandasm::AsmEmitter::Emit("LiteralArrayIntAccess.panda", *prog, nullptr, nullptr, false));
810b1994897Sopenharmony_ci    }
811b1994897Sopenharmony_ci};
812b1994897Sopenharmony_ci
813b1994897Sopenharmony_ci}  // namespace panda::bytecodeopt
814b1994897Sopenharmony_ci
815b1994897Sopenharmony_ci#endif  // BYTECODE_OPTIMIZER_TESTS_COMMON_H
816