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