1 /* 2 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 * 15 * Copyright (c) 2024 Huawei Device Co., Ltd. 16 * Licensed under the Apache License, Version 2.0 (the "License"); 17 * you may not use this file except in compliance with the License. 18 * You may obtain a copy of the License at 19 20 * http://www.apache.org/licenses/LICENSE-2.0 21 * 22 * Unless required by applicable law or agreed to in writing, software 23 * distributed under the License is distributed on an "AS IS" BASIS, 24 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 25 * See the License for the specific language governing permissions and 26 * limitations under the License. 27 */ 28 29 #include <gtest/gtest.h> 30 #include <utility> 31 #include <vector> 32 33 #include "graph_test.h" 34 #include "optimizer/analysis/liveness_analyzer.h" 35 #include "optimizer/ir/constants.h" 36 #include "optimizer/ir/graph.h" 37 #include "optimizer/ir/inst.h" 38 #include "optimizer/ir/locations.h" 39 #include "optimizer/optimizations/regalloc/reg_alloc_resolver.h" 40 #include "reg_acc_alloc.h" 41 #include "utils/arena_containers.h" 42 43 using namespace testing::ext; 44 45 namespace panda::compiler { 46 class RegAllocResolverTest : public testing::Test { 47 public: SetUpTestCase(void)48 static void SetUpTestCase(void) {}; TearDownTestCase(void)49 static void TearDownTestCase(void) {}; SetUp()50 void SetUp() {}; TearDown()51 void TearDown() {}; 52 53 GraphTest graph_test_; 54 55 template<typename Callback> ForEachInst(Graph * graph,Callback cb)56 static void ForEachInst(Graph *graph, Callback cb) 57 { 58 ASSERT(graph != nullptr); 59 for (auto bb : graph->GetBlocksRPO()) { 60 for (auto inst : bb->AllInsts()) { 61 cb(inst); 62 } 63 } 64 } 65 IsIntrinsic(Inst * inst,IntrinsicInst::IntrinsicId id)66 static bool IsIntrinsic(Inst *inst, IntrinsicInst::IntrinsicId id) 67 { 68 return inst->IsIntrinsic() && inst->CastToIntrinsic()->GetIntrinsicId() == id; 69 } 70 InitUsedRegs(Graph * graph,size_t count)71 static void InitUsedRegs(Graph *graph, size_t count) 72 { 73 ASSERT(graph != nullptr); 74 ArenaVector<bool> used_regs(count, false, graph->GetAllocator()->Adapter()); 75 graph->InitUsedRegs<DataType::INT64>(&used_regs); 76 } 77 }; 78 79 /** 80 * @tc.name: reg_alloc_resolver_test_001 81 * @tc.desc: Verify the AddMoveToFixedLocation function. 82 * @tc.type: FUNC 83 * @tc.require: 84 */ 85 HWTEST_F(RegAllocResolverTest, reg_alloc_resolver_test_001, TestSize.Level1) 86 { 87 std::string pfile = GRAPH_TEST_ABC_DIR "regallocTest.abc"; 88 const char *test_method_name = "func4"; 89 bool status = false; __anonb2909fe30102(Graph* graph, std::string &method_name) 90 graph_test_.TestBuildGraphFromFile(pfile, [&test_method_name, &status](Graph* graph, std::string &method_name) { 91 if (test_method_name != method_name) { 92 return; 93 } 94 95 graph->RunPass<LivenessAnalyzer>(); 96 auto intervals = graph->GetAnalysis<LivenessAnalyzer>().GetLifeIntervals(); 97 98 graph->RunPass<bytecodeopt::RegAccAlloc>(); 99 100 // Allocate registers 101 Register preassign_count = 0; 102 for (auto interval : intervals) { 103 interval->SetPreassignedReg(preassign_count++); 104 } 105 106 // Make some insts require a fixed input register, then spillfill insts are expected to be created. 107 Register fixed_input_reg = preassign_count; 108 std::vector<std::pair<Inst*, Register>> pairs; 109 ForEachInst(graph, [&pairs, &fixed_input_reg](Inst *inst) { 110 if (IsIntrinsic(inst, IntrinsicInst::IntrinsicId::ADD2_IMM8_V8) || 111 IsIntrinsic(inst, IntrinsicInst::IntrinsicId::SUB2_IMM8_V8)) { 112 EXPECT_GE(inst->GetInputsCount(), 2); 113 114 inst->SetLocation(0, Location::MakeRegister(fixed_input_reg)); 115 inst->SetLocation(1, Location::MakeRegister(fixed_input_reg + 1)); 116 pairs.emplace_back(inst, fixed_input_reg); 117 fixed_input_reg += 2; 118 } 119 }); 120 EXPECT_FALSE(pairs.empty()); 121 122 // Run resolver 123 InitUsedRegs(graph, 256); 124 RegAllocResolver(graph).Resolve(); 125 126 for (auto [inst, input_reg] : pairs) { 127 EXPECT_EQ(inst->GetSrcReg(0), input_reg); 128 EXPECT_EQ(inst->GetSrcReg(1), input_reg + 1); 129 130 auto sf_inst = inst->GetPrev(); 131 EXPECT_TRUE(sf_inst != nullptr); 132 EXPECT_TRUE(sf_inst->IsSpillFill()); 133 EXPECT_EQ(sf_inst->CastToSpillFill()->GetSpillFillType(), SpillFillType::INPUT_FILL); 134 135 auto sf_data1 = sf_inst->CastToSpillFill()->GetSpillFill(0); 136 EXPECT_EQ(sf_data1.GetSrc(), inst->GetInput(0).GetInst()->GetDstLocation()); 137 EXPECT_EQ(sf_data1.GetDst(), inst->GetLocation(0)); 138 139 auto sf_data2 = sf_inst->CastToSpillFill()->GetSpillFill(1); 140 EXPECT_EQ(sf_data2.GetSrc(), inst->GetInput(1).GetInst()->GetDstLocation()); 141 EXPECT_EQ(sf_data2.GetDst(), inst->GetLocation(1)); 142 } 143 144 status = true; 145 }); 146 EXPECT_TRUE(status); 147 } 148 } // namespace panda::compiler 149