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