Line data Source code
1 : // Copyright 2014 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 "src/globals.h"
7 : #include "src/macro-assembler.h"
8 :
9 : namespace v8 {
10 : namespace internal {
11 :
12 : namespace {
13 :
14 : #define REGISTER_COUNT(R) 1 +
15 : static const int kMaxAllocatableGeneralRegisterCount =
16 : ALLOCATABLE_GENERAL_REGISTERS(REGISTER_COUNT)0;
17 : static const int kMaxAllocatableDoubleRegisterCount =
18 : ALLOCATABLE_DOUBLE_REGISTERS(REGISTER_COUNT)0;
19 :
20 : static const int kAllocatableGeneralCodes[] = {
21 : #define REGISTER_CODE(R) Register::kCode_##R,
22 : ALLOCATABLE_GENERAL_REGISTERS(REGISTER_CODE)};
23 : #undef REGISTER_CODE
24 :
25 : #define REGISTER_CODE(R) DoubleRegister::kCode_##R,
26 : static const int kAllocatableDoubleCodes[] = {
27 : ALLOCATABLE_DOUBLE_REGISTERS(REGISTER_CODE)};
28 : #if V8_TARGET_ARCH_ARM
29 : static const int kAllocatableNoVFP32DoubleCodes[] = {
30 : ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(REGISTER_CODE)};
31 : #endif // V8_TARGET_ARCH_ARM
32 : #undef REGISTER_CODE
33 :
34 : static const char* const kGeneralRegisterNames[] = {
35 : #define REGISTER_NAME(R) #R,
36 : GENERAL_REGISTERS(REGISTER_NAME)
37 : #undef REGISTER_NAME
38 : };
39 :
40 : static const char* const kFloatRegisterNames[] = {
41 : #define REGISTER_NAME(R) #R,
42 : FLOAT_REGISTERS(REGISTER_NAME)
43 : #undef REGISTER_NAME
44 : };
45 :
46 : static const char* const kDoubleRegisterNames[] = {
47 : #define REGISTER_NAME(R) #R,
48 : DOUBLE_REGISTERS(REGISTER_NAME)
49 : #undef REGISTER_NAME
50 : };
51 :
52 : static const char* const kSimd128RegisterNames[] = {
53 : #define REGISTER_NAME(R) #R,
54 : SIMD128_REGISTERS(REGISTER_NAME)
55 : #undef REGISTER_NAME
56 : };
57 :
58 : STATIC_ASSERT(RegisterConfiguration::kMaxGeneralRegisters >=
59 : Register::kNumRegisters);
60 : STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >=
61 : FloatRegister::kMaxNumRegisters);
62 : STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >=
63 : DoubleRegister::kMaxNumRegisters);
64 : STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >=
65 : Simd128Register::kMaxNumRegisters);
66 :
67 : enum CompilerSelector { CRANKSHAFT, TURBOFAN };
68 :
69 : class ArchDefaultRegisterConfiguration : public RegisterConfiguration {
70 : public:
71 89353 : explicit ArchDefaultRegisterConfiguration(CompilerSelector compiler)
72 : : RegisterConfiguration(
73 : Register::kNumRegisters, DoubleRegister::kMaxNumRegisters,
74 : #if V8_TARGET_ARCH_IA32
75 : kMaxAllocatableGeneralRegisterCount,
76 : kMaxAllocatableDoubleRegisterCount,
77 : #elif V8_TARGET_ARCH_X87
78 : kMaxAllocatableGeneralRegisterCount,
79 : compiler == TURBOFAN ? 1 : kMaxAllocatableDoubleRegisterCount,
80 : #elif V8_TARGET_ARCH_X64
81 : kMaxAllocatableGeneralRegisterCount,
82 : kMaxAllocatableDoubleRegisterCount,
83 : #elif V8_TARGET_ARCH_ARM
84 : kMaxAllocatableGeneralRegisterCount,
85 : CpuFeatures::IsSupported(VFP32DREGS)
86 : ? kMaxAllocatableDoubleRegisterCount
87 : : (ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(REGISTER_COUNT) 0),
88 : #elif V8_TARGET_ARCH_ARM64
89 : kMaxAllocatableGeneralRegisterCount,
90 : kMaxAllocatableDoubleRegisterCount,
91 : #elif V8_TARGET_ARCH_MIPS
92 : kMaxAllocatableGeneralRegisterCount,
93 : kMaxAllocatableDoubleRegisterCount,
94 : #elif V8_TARGET_ARCH_MIPS64
95 : kMaxAllocatableGeneralRegisterCount,
96 : kMaxAllocatableDoubleRegisterCount,
97 : #elif V8_TARGET_ARCH_PPC
98 : kMaxAllocatableGeneralRegisterCount,
99 : kMaxAllocatableDoubleRegisterCount,
100 : #elif V8_TARGET_ARCH_S390
101 : kMaxAllocatableGeneralRegisterCount,
102 : kMaxAllocatableDoubleRegisterCount,
103 : #else
104 : #error Unsupported target architecture.
105 : #endif
106 : kAllocatableGeneralCodes,
107 : #if V8_TARGET_ARCH_ARM
108 : CpuFeatures::IsSupported(VFP32DREGS)
109 : ? kAllocatableDoubleCodes
110 : : kAllocatableNoVFP32DoubleCodes,
111 : #else
112 : kAllocatableDoubleCodes,
113 : #endif
114 : kSimpleFPAliasing ? AliasingKind::OVERLAP : AliasingKind::COMBINE,
115 : kGeneralRegisterNames, kFloatRegisterNames, kDoubleRegisterNames,
116 89353 : kSimd128RegisterNames) {
117 89353 : }
118 : };
119 :
120 : template <CompilerSelector compiler>
121 : struct RegisterConfigurationInitializer {
122 : static void Construct(ArchDefaultRegisterConfiguration* config) {
123 89353 : new (config) ArchDefaultRegisterConfiguration(compiler);
124 : }
125 : };
126 :
127 : static base::LazyInstance<ArchDefaultRegisterConfiguration,
128 : RegisterConfigurationInitializer<CRANKSHAFT>>::type
129 : kDefaultRegisterConfigurationForCrankshaft = LAZY_INSTANCE_INITIALIZER;
130 :
131 : static base::LazyInstance<ArchDefaultRegisterConfiguration,
132 : RegisterConfigurationInitializer<TURBOFAN>>::type
133 : kDefaultRegisterConfigurationForTurboFan = LAZY_INSTANCE_INITIALIZER;
134 :
135 : } // namespace
136 :
137 74093911 : const RegisterConfiguration* RegisterConfiguration::Crankshaft() {
138 74094050 : return &kDefaultRegisterConfigurationForCrankshaft.Get();
139 : }
140 :
141 2815475 : const RegisterConfiguration* RegisterConfiguration::Turbofan() {
142 2815485 : return &kDefaultRegisterConfigurationForTurboFan.Get();
143 : }
144 :
145 89407 : RegisterConfiguration::RegisterConfiguration(
146 : int num_general_registers, int num_double_registers,
147 : int num_allocatable_general_registers, int num_allocatable_double_registers,
148 : const int* allocatable_general_codes, const int* allocatable_double_codes,
149 : AliasingKind fp_aliasing_kind, const char* const* general_register_names,
150 : const char* const* float_register_names,
151 : const char* const* double_register_names,
152 : const char* const* simd128_register_names)
153 : : num_general_registers_(num_general_registers),
154 : num_float_registers_(0),
155 : num_double_registers_(num_double_registers),
156 : num_simd128_registers_(0),
157 : num_allocatable_general_registers_(num_allocatable_general_registers),
158 : num_allocatable_float_registers_(0),
159 : num_allocatable_double_registers_(num_allocatable_double_registers),
160 : num_allocatable_simd128_registers_(0),
161 : allocatable_general_codes_mask_(0),
162 : allocatable_float_codes_mask_(0),
163 : allocatable_double_codes_mask_(0),
164 : allocatable_simd128_codes_mask_(0),
165 : allocatable_general_codes_(allocatable_general_codes),
166 : allocatable_double_codes_(allocatable_double_codes),
167 : fp_aliasing_kind_(fp_aliasing_kind),
168 : general_register_names_(general_register_names),
169 : float_register_names_(float_register_names),
170 : double_register_names_(double_register_names),
171 89407 : simd128_register_names_(simd128_register_names) {
172 : DCHECK(num_general_registers_ <= RegisterConfiguration::kMaxGeneralRegisters);
173 : DCHECK(num_double_registers_ <= RegisterConfiguration::kMaxFPRegisters);
174 1162054 : for (int i = 0; i < num_allocatable_general_registers_; ++i) {
175 1072647 : allocatable_general_codes_mask_ |= (1 << allocatable_general_codes_[i]);
176 : }
177 1340707 : for (int i = 0; i < num_allocatable_double_registers_; ++i) {
178 1340707 : allocatable_double_codes_mask_ |= (1 << allocatable_double_codes_[i]);
179 : }
180 :
181 89407 : if (fp_aliasing_kind_ == COMBINE) {
182 : num_float_registers_ = num_double_registers_ * 2 <= kMaxFPRegisters
183 1 : ? num_double_registers_ * 2
184 1 : : kMaxFPRegisters;
185 : num_allocatable_float_registers_ = 0;
186 4 : for (int i = 0; i < num_allocatable_double_registers_; i++) {
187 3 : int base_code = allocatable_double_codes_[i] * 2;
188 3 : if (base_code >= kMaxFPRegisters) continue;
189 2 : allocatable_float_codes_[num_allocatable_float_registers_++] = base_code;
190 2 : allocatable_float_codes_[num_allocatable_float_registers_++] =
191 2 : base_code + 1;
192 2 : allocatable_float_codes_mask_ |= (0x3 << base_code);
193 : }
194 1 : num_simd128_registers_ = num_double_registers_ / 2;
195 : num_allocatable_simd128_registers_ = 0;
196 1 : int last_simd128_code = allocatable_double_codes_[0] / 2;
197 3 : for (int i = 1; i < num_allocatable_double_registers_; i++) {
198 2 : int next_simd128_code = allocatable_double_codes_[i] / 2;
199 : // This scheme assumes allocatable_double_codes_ are strictly increasing.
200 : DCHECK_GE(next_simd128_code, last_simd128_code);
201 2 : if (last_simd128_code == next_simd128_code) {
202 1 : allocatable_simd128_codes_[num_allocatable_simd128_registers_++] =
203 1 : next_simd128_code;
204 1 : allocatable_simd128_codes_mask_ |= (0x1 << next_simd128_code);
205 : }
206 : last_simd128_code = next_simd128_code;
207 : }
208 : } else {
209 : DCHECK(fp_aliasing_kind_ == OVERLAP);
210 89406 : num_float_registers_ = num_simd128_registers_ = num_double_registers_;
211 : num_allocatable_float_registers_ = num_allocatable_simd128_registers_ =
212 89406 : num_allocatable_double_registers_;
213 1430110 : for (int i = 0; i < num_allocatable_float_registers_; ++i) {
214 : allocatable_float_codes_[i] = allocatable_simd128_codes_[i] =
215 1340704 : allocatable_double_codes_[i];
216 : }
217 : allocatable_float_codes_mask_ = allocatable_simd128_codes_mask_ =
218 89406 : allocatable_double_codes_mask_;
219 : }
220 89407 : }
221 :
222 : // Assert that kFloat32, kFloat64, and kSimd128 are consecutive values.
223 : STATIC_ASSERT(static_cast<int>(MachineRepresentation::kSimd128) ==
224 : static_cast<int>(MachineRepresentation::kFloat64) + 1);
225 : STATIC_ASSERT(static_cast<int>(MachineRepresentation::kFloat64) ==
226 : static_cast<int>(MachineRepresentation::kFloat32) + 1);
227 :
228 12 : int RegisterConfiguration::GetAliases(MachineRepresentation rep, int index,
229 : MachineRepresentation other_rep,
230 : int* alias_base_index) const {
231 : DCHECK(fp_aliasing_kind_ == COMBINE);
232 : DCHECK(IsFloatingPoint(rep) && IsFloatingPoint(other_rep));
233 12 : if (rep == other_rep) {
234 2 : *alias_base_index = index;
235 2 : return 1;
236 : }
237 : int rep_int = static_cast<int>(rep);
238 : int other_rep_int = static_cast<int>(other_rep);
239 10 : if (rep_int > other_rep_int) {
240 6 : int shift = rep_int - other_rep_int;
241 6 : int base_index = index << shift;
242 6 : if (base_index >= kMaxFPRegisters) {
243 : // Alias indices would be out of FP register range.
244 : return 0;
245 : }
246 3 : *alias_base_index = base_index;
247 3 : return 1 << shift;
248 : }
249 4 : int shift = other_rep_int - rep_int;
250 4 : *alias_base_index = index >> shift;
251 4 : return 1;
252 : }
253 :
254 34 : bool RegisterConfiguration::AreAliases(MachineRepresentation rep, int index,
255 : MachineRepresentation other_rep,
256 : int other_index) const {
257 : DCHECK(fp_aliasing_kind_ == COMBINE);
258 : DCHECK(IsFloatingPoint(rep) && IsFloatingPoint(other_rep));
259 34 : if (rep == other_rep) {
260 6 : return index == other_index;
261 : }
262 : int rep_int = static_cast<int>(rep);
263 : int other_rep_int = static_cast<int>(other_rep);
264 28 : if (rep_int > other_rep_int) {
265 16 : int shift = rep_int - other_rep_int;
266 16 : return index == other_index >> shift;
267 : }
268 12 : int shift = other_rep_int - rep_int;
269 12 : return index >> shift == other_index;
270 : }
271 :
272 : #undef REGISTER_COUNT
273 :
274 : } // namespace internal
275 : } // namespace v8
|