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 */
HWTEST_F(SpillFillsResolverTest, spill_fills_resolver_test_001, TestSize.Level1)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 */
HWTEST_F(SpillFillsResolverTest, spill_fills_resolver_test_002, TestSize.Level1)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 */
HWTEST_F(SpillFillsResolverTest, spill_fills_resolver_test_003, TestSize.Level1)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 */
HWTEST_F(SpillFillsResolverTest, spill_fills_resolver_test_004, TestSize.Level1)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 */
HWTEST_F(SpillFillsResolverTest, spill_fills_resolver_test_005, TestSize.Level1)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