Line data Source code
1 : // Copyright 2016 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/register-configuration.h"
6 : #include "testing/gtest-support.h"
7 :
8 : namespace v8 {
9 : namespace internal {
10 :
11 : const MachineRepresentation kFloat32 = MachineRepresentation::kFloat32;
12 : const MachineRepresentation kFloat64 = MachineRepresentation::kFloat64;
13 : const MachineRepresentation kSimd128 = MachineRepresentation::kSimd128;
14 :
15 : class RegisterConfigurationUnitTest : public ::testing::Test {
16 : public:
17 2 : RegisterConfigurationUnitTest() = default;
18 2 : ~RegisterConfigurationUnitTest() override = default;
19 : };
20 :
21 15419 : TEST_F(RegisterConfigurationUnitTest, BasicProperties) {
22 1 : const int kNumGeneralRegs = 3;
23 1 : const int kNumDoubleRegs = 4;
24 1 : const int kNumAllocatableGeneralRegs = 2;
25 1 : const int kNumAllocatableDoubleRegs = 2;
26 1 : int general_codes[kNumAllocatableGeneralRegs] = {1, 2};
27 1 : int double_codes[kNumAllocatableDoubleRegs] = {2, 3};
28 :
29 : RegisterConfiguration test(kNumGeneralRegs, kNumDoubleRegs,
30 : kNumAllocatableGeneralRegs,
31 : kNumAllocatableDoubleRegs, general_codes,
32 1 : double_codes, RegisterConfiguration::OVERLAP);
33 :
34 2 : EXPECT_EQ(test.num_general_registers(), kNumGeneralRegs);
35 2 : EXPECT_EQ(test.num_double_registers(), kNumDoubleRegs);
36 2 : EXPECT_EQ(test.num_allocatable_general_registers(),
37 0 : kNumAllocatableGeneralRegs);
38 2 : EXPECT_EQ(test.num_allocatable_double_registers(), kNumAllocatableDoubleRegs);
39 2 : EXPECT_EQ(test.num_allocatable_float_registers(), kNumAllocatableDoubleRegs);
40 2 : EXPECT_EQ(test.num_allocatable_simd128_registers(),
41 0 : kNumAllocatableDoubleRegs);
42 :
43 2 : EXPECT_EQ(test.allocatable_general_codes_mask(),
44 0 : (1 << general_codes[0]) | (1 << general_codes[1]));
45 2 : EXPECT_EQ(test.GetAllocatableGeneralCode(0), general_codes[0]);
46 2 : EXPECT_EQ(test.GetAllocatableGeneralCode(1), general_codes[1]);
47 2 : EXPECT_EQ(test.allocatable_double_codes_mask(),
48 0 : (1 << double_codes[0]) | (1 << double_codes[1]));
49 2 : EXPECT_EQ(test.GetAllocatableFloatCode(0), double_codes[0]);
50 2 : EXPECT_EQ(test.GetAllocatableDoubleCode(0), double_codes[0]);
51 2 : EXPECT_EQ(test.GetAllocatableSimd128Code(0), double_codes[0]);
52 2 : EXPECT_EQ(test.GetAllocatableFloatCode(1), double_codes[1]);
53 2 : EXPECT_EQ(test.GetAllocatableDoubleCode(1), double_codes[1]);
54 2 : EXPECT_EQ(test.GetAllocatableSimd128Code(1), double_codes[1]);
55 1 : }
56 :
57 15419 : TEST_F(RegisterConfigurationUnitTest, CombineAliasing) {
58 : const int kNumGeneralRegs = 3;
59 : const int kNumDoubleRegs = 4;
60 : const int kNumAllocatableGeneralRegs = 2;
61 : const int kNumAllocatableDoubleRegs = 3;
62 1 : int general_codes[] = {1, 2};
63 1 : int double_codes[] = {2, 3, 16}; // reg 16 should not alias registers 32, 33.
64 :
65 : RegisterConfiguration test(kNumGeneralRegs, kNumDoubleRegs,
66 : kNumAllocatableGeneralRegs,
67 : kNumAllocatableDoubleRegs, general_codes,
68 1 : double_codes, RegisterConfiguration::COMBINE);
69 :
70 : // There are 3 allocatable double regs, but only 2 can alias float regs.
71 2 : EXPECT_EQ(test.num_allocatable_float_registers(), 4);
72 :
73 : // Test that float registers combine in pairs to form double registers.
74 3 : EXPECT_EQ(test.GetAllocatableFloatCode(0), double_codes[0] * 2);
75 3 : EXPECT_EQ(test.GetAllocatableFloatCode(1), double_codes[0] * 2 + 1);
76 3 : EXPECT_EQ(test.GetAllocatableFloatCode(2), double_codes[1] * 2);
77 3 : EXPECT_EQ(test.GetAllocatableFloatCode(3), double_codes[1] * 2 + 1);
78 :
79 : // There are 3 allocatable double regs, but only 2 pair to form 1 SIMD reg.
80 2 : EXPECT_EQ(test.num_allocatable_simd128_registers(), 1);
81 :
82 : // Test that even-odd pairs of double regs combine to form a SIMD reg.
83 3 : EXPECT_EQ(test.GetAllocatableSimd128Code(0), double_codes[0] / 2);
84 :
85 : // Registers alias themselves.
86 2 : EXPECT_TRUE(test.AreAliases(kFloat32, 0, kFloat32, 0));
87 2 : EXPECT_TRUE(test.AreAliases(kFloat64, 0, kFloat64, 0));
88 2 : EXPECT_TRUE(test.AreAliases(kSimd128, 0, kSimd128, 0));
89 : // Registers don't alias other registers of the same size.
90 2 : EXPECT_FALSE(test.AreAliases(kFloat32, 1, kFloat32, 0));
91 2 : EXPECT_FALSE(test.AreAliases(kFloat64, 1, kFloat64, 0));
92 2 : EXPECT_FALSE(test.AreAliases(kSimd128, 1, kSimd128, 0));
93 : // Float registers combine in pairs to alias a double with index / 2, and
94 : // in 4's to alias a simd128 with index / 4.
95 2 : EXPECT_TRUE(test.AreAliases(kFloat32, 0, kFloat64, 0));
96 2 : EXPECT_TRUE(test.AreAliases(kFloat32, 1, kFloat64, 0));
97 2 : EXPECT_TRUE(test.AreAliases(kFloat32, 0, kSimd128, 0));
98 2 : EXPECT_TRUE(test.AreAliases(kFloat32, 1, kSimd128, 0));
99 2 : EXPECT_TRUE(test.AreAliases(kFloat32, 2, kSimd128, 0));
100 2 : EXPECT_TRUE(test.AreAliases(kFloat32, 3, kSimd128, 0));
101 2 : EXPECT_TRUE(test.AreAliases(kFloat64, 0, kFloat32, 0));
102 2 : EXPECT_TRUE(test.AreAliases(kFloat64, 0, kFloat32, 1));
103 2 : EXPECT_TRUE(test.AreAliases(kSimd128, 0, kFloat32, 0));
104 2 : EXPECT_TRUE(test.AreAliases(kSimd128, 0, kFloat32, 1));
105 1 : EXPECT_TRUE(test.AreAliases(kSimd128, 0, kFloat32, 2));
106 2 : EXPECT_TRUE(test.AreAliases(kSimd128, 0, kFloat32, 3));
107 :
108 2 : EXPECT_FALSE(test.AreAliases(kFloat32, 0, kFloat64, 1));
109 2 : EXPECT_FALSE(test.AreAliases(kFloat32, 1, kFloat64, 1));
110 2 : EXPECT_FALSE(test.AreAliases(kFloat32, 0, kSimd128, 1));
111 2 : EXPECT_FALSE(test.AreAliases(kFloat32, 1, kSimd128, 1));
112 2 : EXPECT_FALSE(test.AreAliases(kFloat64, 0, kSimd128, 1));
113 2 : EXPECT_FALSE(test.AreAliases(kFloat64, 1, kSimd128, 1));
114 :
115 2 : EXPECT_TRUE(test.AreAliases(kFloat64, 0, kFloat32, 1));
116 2 : EXPECT_TRUE(test.AreAliases(kFloat64, 1, kFloat32, 2));
117 2 : EXPECT_TRUE(test.AreAliases(kFloat64, 1, kFloat32, 3));
118 2 : EXPECT_TRUE(test.AreAliases(kFloat64, 2, kFloat32, 4));
119 2 : EXPECT_TRUE(test.AreAliases(kFloat64, 2, kFloat32, 5));
120 :
121 2 : EXPECT_TRUE(test.AreAliases(kSimd128, 0, kFloat64, 1));
122 2 : EXPECT_TRUE(test.AreAliases(kSimd128, 1, kFloat64, 2));
123 2 : EXPECT_TRUE(test.AreAliases(kSimd128, 1, kFloat64, 3));
124 2 : EXPECT_TRUE(test.AreAliases(kSimd128, 2, kFloat64, 4));
125 2 : EXPECT_TRUE(test.AreAliases(kSimd128, 2, kFloat64, 5));
126 :
127 1 : int alias_base_index = -1;
128 2 : EXPECT_EQ(test.GetAliases(kFloat32, 0, kFloat32, &alias_base_index), 1);
129 2 : EXPECT_EQ(alias_base_index, 0);
130 2 : EXPECT_EQ(test.GetAliases(kFloat64, 1, kFloat64, &alias_base_index), 1);
131 2 : EXPECT_EQ(alias_base_index, 1);
132 2 : EXPECT_EQ(test.GetAliases(kFloat32, 0, kFloat64, &alias_base_index), 1);
133 2 : EXPECT_EQ(alias_base_index, 0);
134 2 : EXPECT_EQ(test.GetAliases(kFloat32, 1, kFloat64, &alias_base_index), 1);
135 2 : EXPECT_EQ(test.GetAliases(kFloat32, 2, kFloat64, &alias_base_index), 1);
136 2 : EXPECT_EQ(alias_base_index, 1);
137 2 : EXPECT_EQ(test.GetAliases(kFloat32, 3, kFloat64, &alias_base_index), 1);
138 2 : EXPECT_EQ(alias_base_index, 1);
139 2 : EXPECT_EQ(test.GetAliases(kFloat64, 0, kFloat32, &alias_base_index), 2);
140 2 : EXPECT_EQ(alias_base_index, 0);
141 2 : EXPECT_EQ(test.GetAliases(kFloat64, 1, kFloat32, &alias_base_index), 2);
142 2 : EXPECT_EQ(alias_base_index, 2);
143 :
144 : // Non-allocatable codes still alias.
145 2 : EXPECT_EQ(test.GetAliases(kFloat64, 2, kFloat32, &alias_base_index), 2);
146 2 : EXPECT_EQ(alias_base_index, 4);
147 : // High numbered double and simd regs don't alias nonexistent float registers.
148 2 : EXPECT_EQ(
149 : test.GetAliases(kFloat64, RegisterConfiguration::kMaxFPRegisters / 2,
150 : kFloat32, &alias_base_index),
151 0 : 0);
152 2 : EXPECT_EQ(
153 : test.GetAliases(kFloat64, RegisterConfiguration::kMaxFPRegisters / 2 + 1,
154 : kFloat32, &alias_base_index),
155 0 : 0);
156 2 : EXPECT_EQ(
157 : test.GetAliases(kFloat64, RegisterConfiguration::kMaxFPRegisters - 1,
158 : kFloat32, &alias_base_index),
159 0 : 0);
160 1 : }
161 :
162 : } // namespace internal
163 9249 : } // namespace v8
|