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  */
HWTEST_F(RegAllocResolverTest, reg_alloc_resolver_test_001, TestSize.Level1)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;
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