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 31 #include "graph_test.h" 32 #include "optimizer/ir/basicblock.h" 33 #include "optimizer/ir/constants.h" 34 #include "optimizer/ir/datatype.h" 35 #include "optimizer/ir/graph.h" 36 #include "optimizer/ir/inst.h" 37 #include "optimizer/ir/spill_fill_data.h" 38 #include "optimizer/optimizations/regalloc/spill_fills_resolver.h" 39 #include "tests/graph_comparator.h" 40 #include "utils/arch.h" 41 #include "utils/arena_containers.h" 42 43 using namespace testing::ext; 44 45 namespace panda::compiler { 46 class SpillFillsResolverTest : 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 CreateGraphWithStart(Arch arch=Arch::NONE)53 static Graph* CreateGraphWithStart(Arch arch = Arch::NONE) 54 { 55 auto allocator = new ArenaAllocator(SpaceType::SPACE_TYPE_COMPILER); 56 auto local_allocator = new ArenaAllocator(SpaceType::SPACE_TYPE_COMPILER); 57 auto graph = allocator->New<Graph>(allocator, local_allocator, arch); 58 graph->CreateStartBlock(); 59 return graph; 60 } 61 InitUsedRegs(Graph * graph,size_t count)62 static void InitUsedRegs(Graph *graph, size_t count) 63 { 64 ASSERT(graph != nullptr); 65 ArenaVector<bool> used_regs(count, false, graph->GetAllocator()->Adapter()); 66 graph->InitUsedRegs<DataType::INT64>(&used_regs); 67 } 68 }; 69 70 /** 71 * @tc.name: spill_fills_resolver_test_001 72 * @tc.desc: Verify resolve move overwrite. 73 * @tc.type: FUNC 74 * @tc.require: 75 */ 76 HWTEST_F(SpillFillsResolverTest, spill_fills_resolver_test_001, TestSize.Level1) 77 { 78 auto graph = CreateGraphWithStart(); 79 auto sf_inst = graph->CreateInstSpillFill(); 80 sf_inst->AddMove(0, 1, DataType::INT32); 81 sf_inst->AddMove(1, 2, DataType::INT32); 82 83 auto expect_sf_inst = graph->CreateInstSpillFill(); 84 expect_sf_inst->AddMove(1, 2, DataType::INT32); 85 expect_sf_inst->AddMove(0, 1, DataType::INT32); 86 87 SpillFillsResolver resolver(graph); 88 resolver.VisitInstruction(sf_inst); 89 90 EXPECT_TRUE(GraphComparator().Compare(sf_inst, expect_sf_inst)); 91 } 92 93 /** 94 * @tc.name: spill_fills_resolver_test_002 95 * @tc.desc: Verify resolve stack overwrite. 96 * @tc.type: FUNC 97 * @tc.require: 98 */ 99 HWTEST_F(SpillFillsResolverTest, spill_fills_resolver_test_002, TestSize.Level1) 100 { 101 auto graph = CreateGraphWithStart(); 102 graph->SetStackSlotsCount(3); 103 auto sf_inst = graph->CreateInstSpillFill(); 104 sf_inst->AddMemCopy(0, 1, DataType::FLOAT64); 105 sf_inst->AddMemCopy(1, 2, DataType::FLOAT64); 106 107 auto expect_sf_inst = graph->CreateInstSpillFill(); 108 expect_sf_inst->AddMemCopy(1, 2, DataType::FLOAT64); 109 expect_sf_inst->AddMemCopy(0, 1, DataType::FLOAT64); 110 111 SpillFillsResolver resolver(graph, INVALID_REG, 0, 3); 112 resolver.ResolveIfRequired(sf_inst); 113 114 EXPECT_TRUE(GraphComparator().Compare(sf_inst, expect_sf_inst)); 115 } 116 117 /** 118 * @tc.name: spill_fills_resolver_test_003 119 * @tc.desc: Verify resolve cyclic move overwrite. 120 * @tc.type: FUNC 121 * @tc.require: 122 */ 123 HWTEST_F(SpillFillsResolverTest, spill_fills_resolver_test_003, TestSize.Level1) 124 { 125 auto graph = CreateGraphWithStart(); 126 auto sf_inst = graph->CreateInstSpillFill(); 127 sf_inst->AddMove(3, 1, DataType::FLOAT64); 128 sf_inst->AddMove(2, 3, DataType::FLOAT64); 129 sf_inst->AddMove(1, 2, DataType::FLOAT64); 130 131 auto expect_sf_inst = graph->CreateInstSpillFill(); 132 expect_sf_inst->AddMove(1, 0, DataType::FLOAT64); 133 expect_sf_inst->AddMove(3, 1, DataType::FLOAT64); 134 expect_sf_inst->AddMove(2, 3, DataType::FLOAT64); 135 expect_sf_inst->AddMove(0, 2, DataType::FLOAT64); 136 137 SpillFillsResolver resolver(graph, INVALID_REG, 0, 5); 138 resolver.VisitInstruction(sf_inst); 139 140 EXPECT_TRUE(GraphComparator().Compare(sf_inst, expect_sf_inst)); 141 } 142 143 /** 144 * @tc.name: spill_fills_resolver_test_004 145 * @tc.desc: Verify resolve cyclic move overwrite with preassigned resolver register. 146 * @tc.type: FUNC 147 * @tc.require: 148 */ 149 HWTEST_F(SpillFillsResolverTest, spill_fills_resolver_test_004, TestSize.Level1) 150 { 151 auto graph = CreateGraphWithStart(); 152 InitUsedRegs(graph, 6); 153 auto sf_inst = graph->CreateInstSpillFill(); 154 sf_inst->AddMove(3, 1, DataType::INT32); 155 sf_inst->AddMove(2, 3, DataType::INT32); 156 sf_inst->AddMove(1, 2, DataType::INT32); 157 158 auto expect_sf_inst = graph->CreateInstSpillFill(); 159 expect_sf_inst->AddMove(1, 5, DataType::INT32); 160 expect_sf_inst->AddMove(3, 1, DataType::INT32); 161 expect_sf_inst->AddMove(2, 3, DataType::INT32); 162 expect_sf_inst->AddMove(5, 2, DataType::INT32); 163 164 SpillFillsResolver resolver(graph, 5, 6, 0); 165 resolver.VisitInstruction(sf_inst); 166 167 EXPECT_TRUE(GraphComparator().Compare(sf_inst, expect_sf_inst)); 168 } 169 170 /** 171 * @tc.name: spill_fills_resolver_test_005 172 * @tc.desc: Verify resolve cyclic move overwrite on AARCH32. 173 * @tc.type: FUNC 174 * @tc.require: 175 */ 176 HWTEST_F(SpillFillsResolverTest, spill_fills_resolver_test_005, TestSize.Level1) 177 { 178 auto graph = CreateGraphWithStart(Arch::AARCH32); 179 graph->SetStackSlotsCount(1); 180 auto sf_inst = graph->CreateInstSpillFill(); 181 sf_inst->AddMove(3, 1, DataType::FLOAT64); 182 sf_inst->AddMove(2, 3, DataType::FLOAT64); 183 sf_inst->AddMove(1, 2, DataType::FLOAT64); 184 185 auto expect_sf_inst = graph->CreateInstSpillFill(); 186 expect_sf_inst->AddSpill(1, 0, DataType::FLOAT64); 187 expect_sf_inst->AddMove(3, 1, DataType::FLOAT64); 188 expect_sf_inst->AddMove(2, 3, DataType::FLOAT64); 189 expect_sf_inst->AddFill(0, 2, DataType::FLOAT64); 190 191 SpillFillsResolver resolver(graph, INVALID_REG, 0, 5); 192 resolver.VisitInstruction(sf_inst); 193 194 EXPECT_TRUE(GraphComparator().Compare(sf_inst, expect_sf_inst)); 195 } 196 } // namespace panda::compiler 197