Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(223)

Side by Side Diff: test/cctest/compiler/test-gap-resolver.cc

Issue 2410673002: [Turbofan] Add concept of FP register aliasing on ARM 32. (Closed)
Patch Set: Add a TODO. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/zone/zone-allocator.h ('k') | test/cctest/compiler/test-run-native-calls.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/compiler/gap-resolver.h" 5 #include "src/compiler/gap-resolver.h"
6 6
7 #include "src/base/utils/random-number-generator.h" 7 #include "src/base/utils/random-number-generator.h"
8 #include "test/cctest/cctest.h" 8 #include "test/cctest/cctest.h"
9 9
10 namespace v8 { 10 namespace v8 {
11 namespace internal { 11 namespace internal {
12 namespace compiler { 12 namespace compiler {
13 13
14 const auto GetRegConfig = RegisterConfiguration::Turbofan; 14 const auto GetRegConfig = RegisterConfiguration::Turbofan;
15 15
16 // Fragments the given operand into an equivalent set of operands to simplify 16 // Fragments the given FP operand into an equivalent set of FP operands to
17 // ParallelMove equivalence testing. 17 // simplify ParallelMove equivalence testing.
18 void GetCanonicalOperands(const InstructionOperand& op, 18 void GetCanonicalOperands(const InstructionOperand& op,
19 std::vector<InstructionOperand>* fragments) { 19 std::vector<InstructionOperand>* fragments) {
20 CHECK(!kSimpleFPAliasing); 20 CHECK(!kSimpleFPAliasing);
21 CHECK(op.IsFPLocationOperand()); 21 CHECK(op.IsFPLocationOperand());
22 // TODO(bbudge) Split into float operands on platforms with non-simple FP 22 const LocationOperand& loc = LocationOperand::cast(op);
23 // register aliasing. 23 MachineRepresentation rep = loc.representation();
24 fragments->push_back(op); 24 int base = -1;
25 int aliases = GetRegConfig()->GetAliases(
26 rep, 0, MachineRepresentation::kFloat32, &base);
27 CHECK_LT(0, aliases);
28 CHECK_GE(4, aliases);
29 int index = -1;
30 int step = 1;
31 if (op.IsFPRegister()) {
32 index = loc.register_code() * aliases;
33 } else {
34 index = loc.index();
35 step = -1;
36 }
37 for (int i = 0; i < aliases; i++) {
38 fragments->push_back(AllocatedOperand(loc.location_kind(),
39 MachineRepresentation::kFloat32,
40 index + i * step));
41 }
25 } 42 }
26 43
27 // The state of our move interpreter is the mapping of operands to values. Note 44 // The state of our move interpreter is the mapping of operands to values. Note
28 // that the actual values don't really matter, all we care about is equality. 45 // that the actual values don't really matter, all we care about is equality.
29 class InterpreterState { 46 class InterpreterState {
30 public: 47 public:
31 void ExecuteInParallel(const ParallelMove* moves) { 48 void ExecuteInParallel(const ParallelMove* moves) {
32 InterpreterState copy(*this); 49 InterpreterState copy(*this);
33 for (const auto m : *moves) { 50 for (const auto m : *moves) {
34 CHECK(!m->IsRedundant()); 51 CHECK(!m->IsRedundant());
35 const InstructionOperand& src = m->source(); 52 const InstructionOperand& src = m->source();
36 const InstructionOperand& dst = m->destination(); 53 const InstructionOperand& dst = m->destination();
37 if (!kSimpleFPAliasing && src.IsFPLocationOperand() && 54 if (!kSimpleFPAliasing && src.IsFPLocationOperand() &&
38 dst.IsFPLocationOperand()) { 55 dst.IsFPLocationOperand()) {
39 // Canonicalize FP location-location moves. 56 // Canonicalize FP location-location moves by fragmenting them into
57 // an equivalent sequence of float32 moves, to simplify state
58 // equivalence testing.
40 std::vector<InstructionOperand> src_fragments; 59 std::vector<InstructionOperand> src_fragments;
41 GetCanonicalOperands(src, &src_fragments); 60 GetCanonicalOperands(src, &src_fragments);
42 CHECK(!src_fragments.empty()); 61 CHECK(!src_fragments.empty());
43 std::vector<InstructionOperand> dst_fragments; 62 std::vector<InstructionOperand> dst_fragments;
44 GetCanonicalOperands(dst, &dst_fragments); 63 GetCanonicalOperands(dst, &dst_fragments);
45 CHECK_EQ(src_fragments.size(), dst_fragments.size()); 64 CHECK_EQ(src_fragments.size(), dst_fragments.size());
46 65
47 for (size_t i = 0; i < src_fragments.size(); ++i) { 66 for (size_t i = 0; i < src_fragments.size(); ++i) {
48 write(dst_fragments[i], copy.read(src_fragments[i])); 67 write(dst_fragments[i], copy.read(src_fragments[i]));
49 } 68 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 } 127 }
109 128
110 static Key KeyFor(const InstructionOperand& op) { 129 static Key KeyFor(const InstructionOperand& op) {
111 bool is_constant = op.IsConstant(); 130 bool is_constant = op.IsConstant();
112 MachineRepresentation rep = 131 MachineRepresentation rep =
113 v8::internal::compiler::InstructionSequence::DefaultRepresentation(); 132 v8::internal::compiler::InstructionSequence::DefaultRepresentation();
114 LocationOperand::LocationKind kind; 133 LocationOperand::LocationKind kind;
115 int index; 134 int index;
116 if (!is_constant) { 135 if (!is_constant) {
117 const LocationOperand& loc_op = LocationOperand::cast(op); 136 const LocationOperand& loc_op = LocationOperand::cast(op);
118 // Canonicalize FP location operand representations to kFloat64. 137 // Preserve FP representation when FP register aliasing is complex.
138 // Otherwise, canonicalize to kFloat64.
119 if (IsFloatingPoint(loc_op.representation())) { 139 if (IsFloatingPoint(loc_op.representation())) {
120 rep = MachineRepresentation::kFloat64; 140 rep = kSimpleFPAliasing ? MachineRepresentation::kFloat64
141 : loc_op.representation();
121 } 142 }
122 if (loc_op.IsAnyRegister()) { 143 if (loc_op.IsAnyRegister()) {
123 index = loc_op.register_code(); 144 index = loc_op.register_code();
124 } else { 145 } else {
125 index = loc_op.index(); 146 index = loc_op.index();
126 } 147 }
127 kind = loc_op.location_kind(); 148 kind = loc_op.location_kind();
128 } else { 149 } else {
129 index = ConstantOperand::cast(op).virtual_register(); 150 index = ConstantOperand::cast(op).virtual_register();
130 kind = LocationOperand::REGISTER; 151 kind = LocationOperand::REGISTER;
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 CHECK_EQ(MachineRepresentation::kSimd128, rep); 335 CHECK_EQ(MachineRepresentation::kSimd128, rep);
315 return base + index * 4; 336 return base + index * 4;
316 } 337 }
317 338
318 InstructionOperand CreateRandomOperand(bool is_source, 339 InstructionOperand CreateRandomOperand(bool is_source,
319 MachineRepresentation rep) { 340 MachineRepresentation rep) {
320 auto conf = RegisterConfiguration::Turbofan(); 341 auto conf = RegisterConfiguration::Turbofan();
321 auto GetValidRegisterCode = [&conf](MachineRepresentation rep, int index) { 342 auto GetValidRegisterCode = [&conf](MachineRepresentation rep, int index) {
322 switch (rep) { 343 switch (rep) {
323 case MachineRepresentation::kFloat32: 344 case MachineRepresentation::kFloat32:
345 return conf->RegisterConfiguration::GetAllocatableFloatCode(index);
324 case MachineRepresentation::kFloat64: 346 case MachineRepresentation::kFloat64:
347 return conf->RegisterConfiguration::GetAllocatableDoubleCode(index);
325 case MachineRepresentation::kSimd128: 348 case MachineRepresentation::kSimd128:
326 return conf->RegisterConfiguration::GetAllocatableDoubleCode(index); 349 return conf->RegisterConfiguration::GetAllocatableSimd128Code(index);
327 default: 350 default:
328 return conf->RegisterConfiguration::GetAllocatableGeneralCode(index); 351 return conf->RegisterConfiguration::GetAllocatableGeneralCode(index);
329 } 352 }
330 UNREACHABLE(); 353 UNREACHABLE();
331 return static_cast<int>(Register::kCode_no_reg); 354 return static_cast<int>(Register::kCode_no_reg);
332 }; 355 };
333 int index = rng_->NextInt(kMaxIndex); 356 int index = rng_->NextInt(kMaxIndex);
334 // destination can't be Constant. 357 // destination can't be Constant.
335 switch (rng_->NextInt(is_source ? 5 : 4)) { 358 switch (rng_->NextInt(is_source ? 5 : 4)) {
336 case 0: 359 case 0:
(...skipping 24 matching lines...) Expand all
361 MoveInterpreter mi1(zone); 384 MoveInterpreter mi1(zone);
362 mi1.AssembleParallelMove(pm); 385 mi1.AssembleParallelMove(pm);
363 386
364 MoveInterpreter mi2(zone); 387 MoveInterpreter mi2(zone);
365 GapResolver resolver(&mi2); 388 GapResolver resolver(&mi2);
366 resolver.Resolve(pm); 389 resolver.Resolve(pm);
367 390
368 CHECK_EQ(mi1.state(), mi2.state()); 391 CHECK_EQ(mi1.state(), mi2.state());
369 } 392 }
370 393
394 TEST(Aliasing) {
395 // On platforms with simple aliasing, these parallel moves are ill-formed.
396 if (kSimpleFPAliasing) return;
397
398 ParallelMoveCreator pmc;
399 Zone* zone = pmc.main_zone();
400
401 auto s0 = AllocatedOperand(LocationOperand::REGISTER,
402 MachineRepresentation::kFloat32, 0);
403 auto s1 = AllocatedOperand(LocationOperand::REGISTER,
404 MachineRepresentation::kFloat32, 1);
405 auto s2 = AllocatedOperand(LocationOperand::REGISTER,
406 MachineRepresentation::kFloat32, 2);
407 auto s3 = AllocatedOperand(LocationOperand::REGISTER,
408 MachineRepresentation::kFloat32, 3);
409 auto s4 = AllocatedOperand(LocationOperand::REGISTER,
410 MachineRepresentation::kFloat32, 4);
411
412 auto d0 = AllocatedOperand(LocationOperand::REGISTER,
413 MachineRepresentation::kFloat64, 0);
414 auto d1 = AllocatedOperand(LocationOperand::REGISTER,
415 MachineRepresentation::kFloat64, 1);
416 auto d16 = AllocatedOperand(LocationOperand::REGISTER,
417 MachineRepresentation::kFloat64, 16);
418
419 // Double slots must be odd to match frame allocation.
420 auto dSlot = AllocatedOperand(LocationOperand::STACK_SLOT,
421 MachineRepresentation::kFloat64, 3);
422
423 // Cycles involving s- and d-registers.
424 {
425 std::vector<InstructionOperand> moves = {
426 s2, s0, // s2 <- s0
427 d0, d1 // d0 <- d1
428 };
429 RunTest(pmc.Create(moves), zone);
430 }
431 {
432 std::vector<InstructionOperand> moves = {
433 d0, d1, // d0 <- d1
434 s2, s0 // s2 <- s0
435 };
436 RunTest(pmc.Create(moves), zone);
437 }
438 {
439 std::vector<InstructionOperand> moves = {
440 s2, s1, // s2 <- s1
441 d0, d1 // d0 <- d1
442 };
443 RunTest(pmc.Create(moves), zone);
444 }
445 {
446 std::vector<InstructionOperand> moves = {
447 d0, d1, // d0 <- d1
448 s2, s1 // s2 <- s1
449 };
450 RunTest(pmc.Create(moves), zone);
451 }
452 // Two cycles involving a single d-register.
453 {
454 std::vector<InstructionOperand> moves = {
455 d0, d1, // d0 <- d1
456 s2, s1, // s2 <- s1
457 s3, s0 // s3 <- s0
458 };
459 RunTest(pmc.Create(moves), zone);
460 }
461 // Cycle with a float move that must be deferred until after swaps.
462 {
463 std::vector<InstructionOperand> moves = {
464 d0, d1, // d0 <- d1
465 s2, s0, // s2 <- s0
466 s3, s4 // s3 <- s4 must be deferred
467 };
468 RunTest(pmc.Create(moves), zone);
469 }
470 // Cycles involving s-registers and a non-aliased d-register.
471 {
472 std::vector<InstructionOperand> moves = {
473 d16, d0, // d16 <- d0
474 s1, s2, // s1 <- s2
475 d1, d16 // d1 <- d16
476 };
477 RunTest(pmc.Create(moves), zone);
478 }
479 {
480 std::vector<InstructionOperand> moves = {
481 s2, s1, // s1 <- s2
482 d0, d16, // d16 <- d0
483 d16, d1 // d1 <- d16
484 };
485 RunTest(pmc.Create(moves), zone);
486 }
487 {
488 std::vector<InstructionOperand> moves = {
489 d0, d16, // d0 <- d16
490 d16, d1, // s2 <- s0
491 s3, s0 // d0 <- d1
492 };
493 RunTest(pmc.Create(moves), zone);
494 }
495 // Cycle involving aliasing registers and a slot.
496 {
497 std::vector<InstructionOperand> moves = {
498 dSlot, d0, // dSlot <- d0
499 d1, dSlot, // d1 <- dSlot
500 s0, s3 // s0 <- s3
501 };
502 RunTest(pmc.Create(moves), zone);
503 }
504 }
505
371 TEST(FuzzResolver) { 506 TEST(FuzzResolver) {
372 ParallelMoveCreator pmc; 507 ParallelMoveCreator pmc;
373 for (int size = 0; size < 80; ++size) { 508 for (int size = 0; size < 80; ++size) {
374 for (int repeat = 0; repeat < 50; ++repeat) { 509 for (int repeat = 0; repeat < 50; ++repeat) {
375 RunTest(pmc.Create(size), pmc.main_zone()); 510 RunTest(pmc.Create(size), pmc.main_zone());
376 } 511 }
377 } 512 }
378 } 513 }
379 514
380 } // namespace compiler 515 } // namespace compiler
381 } // namespace internal 516 } // namespace internal
382 } // namespace v8 517 } // namespace v8
OLDNEW
« no previous file with comments | « src/zone/zone-allocator.h ('k') | test/cctest/compiler/test-run-native-calls.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698