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