• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device 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 
16 #include "unit_test.h"
17 #include "optimizer/code_generator/spill_fill_encoder.h"
18 
19 namespace panda::compiler {
20 class SpillFillEncoderTest : public GraphTest {
21 };
22 
operator ==(const SpillFillData & left,const SpillFillData & right)23 bool operator==(const SpillFillData &left, const SpillFillData &right)
24 {
25     return left.SrcType() == right.SrcType() && left.SrcValue() == right.SrcValue() &&
26            left.DstType() == right.DstType() && left.DstValue() == right.DstValue() &&
27            left.GetType() == right.GetType();
28 }
29 
TEST_F(SpillFillEncoderTest,SpillFillDataSorting)30 TEST_F(SpillFillEncoderTest, SpillFillDataSorting)
31 {
32     ArenaVector<SpillFillData> spill_fills {
33         {{LocationType::REGISTER, LocationType::STACK, 1, 0, DataType::Type::INT64},
34          {LocationType::REGISTER, LocationType::STACK, 0, 2, DataType::Type::INT64},
35          {LocationType::REGISTER, LocationType::REGISTER, 0, 1, DataType::Type::INT64},
36          {LocationType::REGISTER, LocationType::REGISTER, 1, 2, DataType::Type::INT64},
37          {LocationType::IMMEDIATE, LocationType::REGISTER, 0, 0, DataType::Type::INT64},
38          {LocationType::IMMEDIATE, LocationType::REGISTER, 0, 1, DataType::Type::INT64},
39          {LocationType::STACK, LocationType::REGISTER, 0, 0, DataType::Type::INT64},
40          {LocationType::STACK, LocationType::REGISTER, 1, 1, DataType::Type::INT64},
41          {LocationType::STACK, LocationType::REGISTER, 2, 2, DataType::Type::INT64},
42          {LocationType::REGISTER, LocationType::REGISTER, 2, 4, DataType::Type::INT64},
43          {LocationType::STACK, LocationType::REGISTER, 3, 2, DataType::Type::INT64},
44          {LocationType::STACK, LocationType::STACK, 7, 9, DataType::Type::INT64},
45          {LocationType::STACK, LocationType::STACK, 8, 10, DataType::Type::INT64}},
46         GetAllocator()->Adapter()};
47 
48     ArenaVector<SpillFillData> expected_order {
49         {  // reorder spills
50          {LocationType::REGISTER, LocationType::STACK, 0, 2, DataType::Type::INT64},
51          {LocationType::REGISTER, LocationType::STACK, 1, 0, DataType::Type::INT64},
52          // skip move
53          {LocationType::REGISTER, LocationType::REGISTER, 0, 1, DataType::Type::INT64},
54          {LocationType::REGISTER, LocationType::REGISTER, 1, 2, DataType::Type::INT64},
55          // skip imm move
56          {LocationType::IMMEDIATE, LocationType::REGISTER, 0, 0, DataType::Type::INT64},
57          {LocationType::IMMEDIATE, LocationType::REGISTER, 0, 1, DataType::Type::INT64},
58          // reorder fills
59          {LocationType::STACK, LocationType::REGISTER, 2, 2, DataType::Type::INT64},
60          {LocationType::STACK, LocationType::REGISTER, 1, 1, DataType::Type::INT64},
61          {LocationType::STACK, LocationType::REGISTER, 0, 0, DataType::Type::INT64},
62          // skip move
63          {LocationType::REGISTER, LocationType::REGISTER, 2, 4, DataType::Type::INT64},
64          {LocationType::STACK, LocationType::REGISTER, 3, 2, DataType::Type::INT64},
65          // skip mem move
66          {LocationType::STACK, LocationType::STACK, 7, 9, DataType::Type::INT64},
67          {LocationType::STACK, LocationType::STACK, 8, 10, DataType::Type::INT64}},
68         GetAllocator()->Adapter()};
69 
70     SpillFillEncoder::SortSpillFillData(&spill_fills);
71     for (size_t i = 0; i < expected_order.size(); i++) {
72         EXPECT_EQ(spill_fills[i], expected_order[i]) << "Mismatch at " << i;
73     }
74 }
75 
TEST_F(SpillFillEncoderTest,CanCombineSpillFills)76 TEST_F(SpillFillEncoderTest, CanCombineSpillFills)
77 {
78     auto graph = GetGraph();
79     if (graph->GetArch() != Arch::AARCH64) {
80         GTEST_SKIP() << "Supported only on Aarch64";
81     }
82 
83     EXPECT_TRUE(SpillFillEncoder::CanCombineSpillFills(
84         {LocationType::STACK, LocationType::REGISTER, 2, 0, DataType::Type::INT64},
85         {LocationType::STACK, LocationType::REGISTER, 1, 0, DataType::Type::INT64}, graph));
86 
87     EXPECT_TRUE(SpillFillEncoder::CanCombineSpillFills(
88         {LocationType::REGISTER, LocationType::STACK, 0, 2, DataType::Type::INT64},
89         {LocationType::REGISTER, LocationType::STACK, 0, 1, DataType::Type::INT64}, graph));
90 
91     EXPECT_TRUE(SpillFillEncoder::CanCombineSpillFills(
92         {LocationType::STACK, LocationType::REGISTER, 2, 0, DataType::Type::INT32},
93         {LocationType::STACK, LocationType::REGISTER, 1, 0, DataType::Type::INT64}, graph));
94 
95     EXPECT_TRUE(SpillFillEncoder::CanCombineSpillFills(
96         {LocationType::STACK, LocationType::REGISTER, 2, 0, DataType::Type::INT32},
97         {LocationType::STACK, LocationType::REGISTER, 1, 0, DataType::Type::INT8}, graph));
98 
99     // different type of moves
100     EXPECT_FALSE(SpillFillEncoder::CanCombineSpillFills(
101         {LocationType::REGISTER, LocationType::STACK, 2, 0, DataType::Type::INT32},
102         {LocationType::STACK, LocationType::REGISTER, 1, 0, DataType::Type::INT32}, graph));
103 
104     // illegal slots order
105     EXPECT_FALSE(SpillFillEncoder::CanCombineSpillFills(
106         {LocationType::STACK, LocationType::REGISTER, 1, 0, DataType::Type::INT32},
107         {LocationType::STACK, LocationType::REGISTER, 2, 0, DataType::Type::INT32}, graph));
108 
109     EXPECT_FALSE(SpillFillEncoder::CanCombineSpillFills(
110         {LocationType::STACK, LocationType::REGISTER, 4, 0, DataType::Type::INT32},
111         {LocationType::STACK, LocationType::REGISTER, 0, 0, DataType::Type::INT32}, graph));
112 
113     // unaligned access
114     EXPECT_TRUE(SpillFillEncoder::CanCombineSpillFills(
115         {LocationType::STACK, LocationType::REGISTER, 1, 0, DataType::Type::INT32},
116         {LocationType::STACK, LocationType::REGISTER, 0, 0, DataType::Type::INT32}, graph));
117 
118     // float 32 are unsupported
119     EXPECT_FALSE(SpillFillEncoder::CanCombineSpillFills(
120         {LocationType::STACK, LocationType::REGISTER, 2, 0, DataType::Type::FLOAT32},
121         {LocationType::STACK, LocationType::REGISTER, 1, 0, DataType::Type::FLOAT32}, graph));
122 
123     // float 64 are supported
124     EXPECT_TRUE(SpillFillEncoder::CanCombineSpillFills(
125         {LocationType::STACK, LocationType::REGISTER, 2, 0, DataType::Type::FLOAT64},
126         {LocationType::STACK, LocationType::REGISTER, 1, 0, DataType::Type::FLOAT64}, graph));
127 
128     // different types
129     EXPECT_FALSE(SpillFillEncoder::CanCombineSpillFills(
130         {LocationType::STACK, LocationType::REGISTER, 2, 0, DataType::Type::INT64},
131         {LocationType::STACK, LocationType::REGISTER, 1, 0, DataType::Type::FLOAT64}, graph));
132 }
133 }  // namespace panda::compiler
134