OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/base/utils/random-number-generator.h" | 5 #include "src/base/utils/random-number-generator.h" |
6 #include "src/compiler/pipeline.h" | 6 #include "src/compiler/pipeline.h" |
7 #include "test/unittests/compiler/instruction-sequence-unittest.h" | 7 #include "test/unittests/compiler/instruction-sequence-unittest.h" |
8 #include "test/unittests/test-utils.h" | 8 #include "test/unittests/test-utils.h" |
9 #include "testing/gmock/include/gmock/gmock.h" | 9 #include "testing/gmock/include/gmock/gmock.h" |
10 | 10 |
(...skipping 23 matching lines...) Expand all Loading... |
34 loc += base::OS::SNPrintF(loc, 100, "gp_%d", i); | 34 loc += base::OS::SNPrintF(loc, 100, "gp_%d", i); |
35 *loc++ = 0; | 35 *loc++ = 0; |
36 } | 36 } |
37 for (int i = 0; i < RegisterConfiguration::kMaxFPRegisters; ++i) { | 37 for (int i = 0; i < RegisterConfiguration::kMaxFPRegisters; ++i) { |
38 double_register_names_[i] = loc; | 38 double_register_names_[i] = loc; |
39 loc += base::OS::SNPrintF(loc, 100, "fp_%d", i) + 1; | 39 loc += base::OS::SNPrintF(loc, 100, "fp_%d", i) + 1; |
40 *loc++ = 0; | 40 *loc++ = 0; |
41 } | 41 } |
42 } | 42 } |
43 | 43 |
44 | |
45 InstructionSequenceTest::InstructionSequenceTest() | 44 InstructionSequenceTest::InstructionSequenceTest() |
46 : sequence_(nullptr), | 45 : sequence_(nullptr), |
47 num_general_registers_(kDefaultNRegs), | 46 num_general_registers_(kDefaultNRegs), |
48 num_double_registers_(kDefaultNRegs), | 47 num_double_registers_(kDefaultNRegs), |
49 instruction_blocks_(zone()), | 48 instruction_blocks_(zone()), |
50 current_block_(nullptr), | 49 current_block_(nullptr), |
51 block_returns_(false) { | 50 block_returns_(false) { |
52 InitializeRegisterNames(); | 51 InitializeRegisterNames(); |
53 } | 52 } |
54 | 53 |
55 | 54 |
56 void InstructionSequenceTest::SetNumRegs(int num_general_registers, | 55 void InstructionSequenceTest::SetNumRegs(int num_general_registers, |
57 int num_double_registers) { | 56 int num_double_registers) { |
58 CHECK(!config_); | 57 CHECK(!config_); |
59 CHECK(instructions_.empty()); | 58 CHECK(instructions_.empty()); |
60 CHECK(instruction_blocks_.empty()); | 59 CHECK(instruction_blocks_.empty()); |
61 num_general_registers_ = num_general_registers; | 60 num_general_registers_ = num_general_registers; |
62 num_double_registers_ = num_double_registers; | 61 num_double_registers_ = num_double_registers; |
63 } | 62 } |
64 | 63 |
| 64 int InstructionSequenceTest::GetNumRegs(MachineRepresentation rep) { |
| 65 switch (rep) { |
| 66 case MachineRepresentation::kFloat32: |
| 67 return config()->num_float_registers(); |
| 68 case MachineRepresentation::kFloat64: |
| 69 return config()->num_double_registers(); |
| 70 case MachineRepresentation::kSimd128: |
| 71 return config()->num_simd128_registers(); |
| 72 default: |
| 73 return config()->num_general_registers(); |
| 74 } |
| 75 } |
| 76 |
| 77 int InstructionSequenceTest::GetAllocatableCode(int index, |
| 78 MachineRepresentation rep) { |
| 79 switch (rep) { |
| 80 case MachineRepresentation::kFloat32: |
| 81 return config()->GetAllocatableFloatCode(index); |
| 82 case MachineRepresentation::kFloat64: |
| 83 return config()->GetAllocatableDoubleCode(index); |
| 84 case MachineRepresentation::kSimd128: |
| 85 return config()->GetAllocatableSimd128Code(index); |
| 86 default: |
| 87 return config()->GetAllocatableGeneralCode(index); |
| 88 } |
| 89 } |
65 | 90 |
66 RegisterConfiguration* InstructionSequenceTest::config() { | 91 RegisterConfiguration* InstructionSequenceTest::config() { |
67 if (!config_) { | 92 if (!config_) { |
68 config_.reset(new RegisterConfiguration( | 93 config_.reset(new RegisterConfiguration( |
69 num_general_registers_, num_double_registers_, num_general_registers_, | 94 num_general_registers_, num_double_registers_, num_general_registers_, |
70 num_double_registers_, num_double_registers_, allocatable_codes, | 95 num_double_registers_, num_double_registers_, allocatable_codes, |
71 allocatable_double_codes, | 96 allocatable_double_codes, |
72 kSimpleFPAliasing ? RegisterConfiguration::OVERLAP | 97 kSimpleFPAliasing ? RegisterConfiguration::OVERLAP |
73 : RegisterConfiguration::COMBINE, | 98 : RegisterConfiguration::COMBINE, |
74 general_register_names_, | 99 general_register_names_, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 } | 167 } |
143 | 168 |
144 | 169 |
145 InstructionSequenceTest::TestOperand InstructionSequenceTest::Imm(int32_t imm) { | 170 InstructionSequenceTest::TestOperand InstructionSequenceTest::Imm(int32_t imm) { |
146 return TestOperand(kImmediate, imm); | 171 return TestOperand(kImmediate, imm); |
147 } | 172 } |
148 | 173 |
149 | 174 |
150 InstructionSequenceTest::VReg InstructionSequenceTest::Define( | 175 InstructionSequenceTest::VReg InstructionSequenceTest::Define( |
151 TestOperand output_op) { | 176 TestOperand output_op) { |
152 VReg vreg = NewReg(); | 177 VReg vreg = NewReg(output_op); |
153 InstructionOperand outputs[1]{ConvertOutputOp(vreg, output_op)}; | 178 InstructionOperand outputs[1]{ConvertOutputOp(vreg, output_op)}; |
154 Emit(kArchNop, 1, outputs); | 179 Emit(kArchNop, 1, outputs); |
155 return vreg; | 180 return vreg; |
156 } | 181 } |
157 | 182 |
158 | |
159 Instruction* InstructionSequenceTest::Return(TestOperand input_op_0) { | 183 Instruction* InstructionSequenceTest::Return(TestOperand input_op_0) { |
160 block_returns_ = true; | 184 block_returns_ = true; |
161 InstructionOperand inputs[1]{ConvertInputOp(input_op_0)}; | 185 InstructionOperand inputs[1]{ConvertInputOp(input_op_0)}; |
162 return Emit(kArchRet, 0, nullptr, 1, inputs); | 186 return Emit(kArchRet, 0, nullptr, 1, inputs); |
163 } | 187 } |
164 | 188 |
165 | 189 |
166 PhiInstruction* InstructionSequenceTest::Phi(VReg incoming_vreg_0, | 190 PhiInstruction* InstructionSequenceTest::Phi(VReg incoming_vreg_0, |
167 VReg incoming_vreg_1, | 191 VReg incoming_vreg_1, |
168 VReg incoming_vreg_2, | 192 VReg incoming_vreg_2, |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 TestOperand input_op_1, | 257 TestOperand input_op_1, |
234 TestOperand input_op_2, | 258 TestOperand input_op_2, |
235 TestOperand input_op_3) { | 259 TestOperand input_op_3) { |
236 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3}; | 260 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3}; |
237 return EmitI(CountInputs(arraysize(inputs), inputs), inputs); | 261 return EmitI(CountInputs(arraysize(inputs), inputs), inputs); |
238 } | 262 } |
239 | 263 |
240 | 264 |
241 InstructionSequenceTest::VReg InstructionSequenceTest::EmitOI( | 265 InstructionSequenceTest::VReg InstructionSequenceTest::EmitOI( |
242 TestOperand output_op, size_t input_size, TestOperand* inputs) { | 266 TestOperand output_op, size_t input_size, TestOperand* inputs) { |
243 VReg output_vreg = NewReg(); | 267 VReg output_vreg = NewReg(output_op); |
244 InstructionOperand outputs[1]{ConvertOutputOp(output_vreg, output_op)}; | 268 InstructionOperand outputs[1]{ConvertOutputOp(output_vreg, output_op)}; |
245 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs); | 269 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs); |
246 Emit(kArchNop, 1, outputs, input_size, mapped_inputs); | 270 Emit(kArchNop, 1, outputs, input_size, mapped_inputs); |
247 return output_vreg; | 271 return output_vreg; |
248 } | 272 } |
249 | 273 |
250 | 274 |
251 InstructionSequenceTest::VReg InstructionSequenceTest::EmitOI( | 275 InstructionSequenceTest::VReg InstructionSequenceTest::EmitOI( |
252 TestOperand output_op, TestOperand input_op_0, TestOperand input_op_1, | 276 TestOperand output_op, TestOperand input_op_0, TestOperand input_op_1, |
253 TestOperand input_op_2, TestOperand input_op_3) { | 277 TestOperand input_op_2, TestOperand input_op_3) { |
254 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3}; | 278 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3}; |
255 return EmitOI(output_op, CountInputs(arraysize(inputs), inputs), inputs); | 279 return EmitOI(output_op, CountInputs(arraysize(inputs), inputs), inputs); |
256 } | 280 } |
257 | 281 |
258 | 282 |
259 InstructionSequenceTest::VRegPair InstructionSequenceTest::EmitOOI( | 283 InstructionSequenceTest::VRegPair InstructionSequenceTest::EmitOOI( |
260 TestOperand output_op_0, TestOperand output_op_1, size_t input_size, | 284 TestOperand output_op_0, TestOperand output_op_1, size_t input_size, |
261 TestOperand* inputs) { | 285 TestOperand* inputs) { |
262 VRegPair output_vregs = std::make_pair(NewReg(), NewReg()); | 286 VRegPair output_vregs = |
| 287 std::make_pair(NewReg(output_op_0), NewReg(output_op_1)); |
263 InstructionOperand outputs[2]{ | 288 InstructionOperand outputs[2]{ |
264 ConvertOutputOp(output_vregs.first, output_op_0), | 289 ConvertOutputOp(output_vregs.first, output_op_0), |
265 ConvertOutputOp(output_vregs.second, output_op_1)}; | 290 ConvertOutputOp(output_vregs.second, output_op_1)}; |
266 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs); | 291 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs); |
267 Emit(kArchNop, 2, outputs, input_size, mapped_inputs); | 292 Emit(kArchNop, 2, outputs, input_size, mapped_inputs); |
268 return output_vregs; | 293 return output_vregs; |
269 } | 294 } |
270 | 295 |
271 | 296 |
272 InstructionSequenceTest::VRegPair InstructionSequenceTest::EmitOOI( | 297 InstructionSequenceTest::VRegPair InstructionSequenceTest::EmitOOI( |
273 TestOperand output_op_0, TestOperand output_op_1, TestOperand input_op_0, | 298 TestOperand output_op_0, TestOperand output_op_1, TestOperand input_op_0, |
274 TestOperand input_op_1, TestOperand input_op_2, TestOperand input_op_3) { | 299 TestOperand input_op_1, TestOperand input_op_2, TestOperand input_op_3) { |
275 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3}; | 300 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3}; |
276 return EmitOOI(output_op_0, output_op_1, | 301 return EmitOOI(output_op_0, output_op_1, |
277 CountInputs(arraysize(inputs), inputs), inputs); | 302 CountInputs(arraysize(inputs), inputs), inputs); |
278 } | 303 } |
279 | 304 |
280 | 305 |
281 InstructionSequenceTest::VReg InstructionSequenceTest::EmitCall( | 306 InstructionSequenceTest::VReg InstructionSequenceTest::EmitCall( |
282 TestOperand output_op, size_t input_size, TestOperand* inputs) { | 307 TestOperand output_op, size_t input_size, TestOperand* inputs) { |
283 VReg output_vreg = NewReg(); | 308 VReg output_vreg = NewReg(output_op); |
284 InstructionOperand outputs[1]{ConvertOutputOp(output_vreg, output_op)}; | 309 InstructionOperand outputs[1]{ConvertOutputOp(output_vreg, output_op)}; |
285 CHECK(UnallocatedOperand::cast(outputs[0]).HasFixedPolicy()); | 310 CHECK(UnallocatedOperand::cast(outputs[0]).HasFixedPolicy()); |
286 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs); | 311 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs); |
287 Emit(kArchCallCodeObject, 1, outputs, input_size, mapped_inputs, 0, nullptr, | 312 Emit(kArchCallCodeObject, 1, outputs, input_size, mapped_inputs, 0, nullptr, |
288 true); | 313 true); |
289 return output_vreg; | 314 return output_vreg; |
290 } | 315 } |
291 | 316 |
292 | 317 |
293 InstructionSequenceTest::VReg InstructionSequenceTest::EmitCall( | 318 InstructionSequenceTest::VReg InstructionSequenceTest::EmitCall( |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 case kUnique: | 405 case kUnique: |
381 return Unallocated(op, UnallocatedOperand::NONE); | 406 return Unallocated(op, UnallocatedOperand::NONE); |
382 case kUniqueRegister: | 407 case kUniqueRegister: |
383 return Unallocated(op, UnallocatedOperand::MUST_HAVE_REGISTER); | 408 return Unallocated(op, UnallocatedOperand::MUST_HAVE_REGISTER); |
384 case kRegister: | 409 case kRegister: |
385 return Unallocated(op, UnallocatedOperand::MUST_HAVE_REGISTER, | 410 return Unallocated(op, UnallocatedOperand::MUST_HAVE_REGISTER, |
386 UnallocatedOperand::USED_AT_START); | 411 UnallocatedOperand::USED_AT_START); |
387 case kSlot: | 412 case kSlot: |
388 return Unallocated(op, UnallocatedOperand::MUST_HAVE_SLOT, | 413 return Unallocated(op, UnallocatedOperand::MUST_HAVE_SLOT, |
389 UnallocatedOperand::USED_AT_START); | 414 UnallocatedOperand::USED_AT_START); |
390 case kFixedRegister: | 415 case kFixedRegister: { |
391 CHECK(0 <= op.value_ && op.value_ < num_general_registers_); | 416 MachineRepresentation rep = GetCanonicalRep(op); |
392 return Unallocated(op, UnallocatedOperand::FIXED_REGISTER, op.value_); | 417 CHECK(0 <= op.value_ && op.value_ < GetNumRegs(rep)); |
| 418 if (DoesRegisterAllocation()) { |
| 419 auto extended_policy = IsFloatingPoint(rep) |
| 420 ? UnallocatedOperand::FIXED_FP_REGISTER |
| 421 : UnallocatedOperand::FIXED_REGISTER; |
| 422 return Unallocated(op, extended_policy, op.value_); |
| 423 } else { |
| 424 return AllocatedOperand(LocationOperand::REGISTER, rep, op.value_); |
| 425 } |
| 426 } |
393 case kFixedSlot: | 427 case kFixedSlot: |
394 return Unallocated(op, UnallocatedOperand::FIXED_SLOT, op.value_); | 428 if (DoesRegisterAllocation()) { |
| 429 return Unallocated(op, UnallocatedOperand::FIXED_SLOT, op.value_); |
| 430 } else { |
| 431 return AllocatedOperand(LocationOperand::STACK_SLOT, |
| 432 GetCanonicalRep(op), op.value_); |
| 433 } |
395 default: | 434 default: |
396 break; | 435 break; |
397 } | 436 } |
398 CHECK(false); | 437 CHECK(false); |
399 return InstructionOperand(); | 438 return InstructionOperand(); |
400 } | 439 } |
401 | 440 |
402 | 441 |
403 InstructionOperand InstructionSequenceTest::ConvertOutputOp(VReg vreg, | 442 InstructionOperand InstructionSequenceTest::ConvertOutputOp(VReg vreg, |
404 TestOperand op) { | 443 TestOperand op) { |
405 CHECK_EQ(op.vreg_.value_, kNoValue); | 444 CHECK_EQ(op.vreg_.value_, kNoValue); |
406 op.vreg_ = vreg; | 445 op.vreg_ = vreg; |
407 switch (op.type_) { | 446 switch (op.type_) { |
408 case kSameAsFirst: | 447 case kSameAsFirst: |
409 return Unallocated(op, UnallocatedOperand::SAME_AS_FIRST_INPUT); | 448 return Unallocated(op, UnallocatedOperand::SAME_AS_FIRST_INPUT); |
410 case kRegister: | 449 case kRegister: |
411 return Unallocated(op, UnallocatedOperand::MUST_HAVE_REGISTER); | 450 return Unallocated(op, UnallocatedOperand::MUST_HAVE_REGISTER); |
412 case kFixedSlot: | 451 case kFixedSlot: |
413 return Unallocated(op, UnallocatedOperand::FIXED_SLOT, op.value_); | 452 if (DoesRegisterAllocation()) { |
414 case kFixedRegister: | 453 return Unallocated(op, UnallocatedOperand::FIXED_SLOT, op.value_); |
415 CHECK(0 <= op.value_ && op.value_ < num_general_registers_); | 454 } else { |
416 return Unallocated(op, UnallocatedOperand::FIXED_REGISTER, op.value_); | 455 return AllocatedOperand(LocationOperand::STACK_SLOT, |
| 456 GetCanonicalRep(op), op.value_); |
| 457 } |
| 458 case kFixedRegister: { |
| 459 MachineRepresentation rep = GetCanonicalRep(op); |
| 460 CHECK(0 <= op.value_ && op.value_ < GetNumRegs(rep)); |
| 461 if (DoesRegisterAllocation()) { |
| 462 auto extended_policy = IsFloatingPoint(rep) |
| 463 ? UnallocatedOperand::FIXED_FP_REGISTER |
| 464 : UnallocatedOperand::FIXED_REGISTER; |
| 465 return Unallocated(op, extended_policy, op.value_); |
| 466 } else { |
| 467 return AllocatedOperand(LocationOperand::REGISTER, rep, op.value_); |
| 468 } |
| 469 } |
417 default: | 470 default: |
418 break; | 471 break; |
419 } | 472 } |
420 CHECK(false); | 473 CHECK(false); |
421 return InstructionOperand(); | 474 return InstructionOperand(); |
422 } | 475 } |
423 | 476 |
424 | 477 |
425 InstructionBlock* InstructionSequenceTest::NewBlock(bool deferred) { | 478 InstructionBlock* InstructionSequenceTest::NewBlock(bool deferred) { |
426 CHECK(current_block_ == nullptr); | 479 CHECK(current_block_ == nullptr); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 | 559 |
507 | 560 |
508 Instruction* InstructionSequenceTest::AddInstruction(Instruction* instruction) { | 561 Instruction* InstructionSequenceTest::AddInstruction(Instruction* instruction) { |
509 sequence()->AddInstruction(instruction); | 562 sequence()->AddInstruction(instruction); |
510 return instruction; | 563 return instruction; |
511 } | 564 } |
512 | 565 |
513 } // namespace compiler | 566 } // namespace compiler |
514 } // namespace internal | 567 } // namespace internal |
515 } // namespace v8 | 568 } // namespace v8 |
OLD | NEW |