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

Side by Side Diff: src/compiler/instruction.h

Issue 1389373002: [turbofan] Create ExplicitOperands to specify operands without virtual registers (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Tweaks Created 5 years, 2 months 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
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 #ifndef V8_COMPILER_INSTRUCTION_H_ 5 #ifndef V8_COMPILER_INSTRUCTION_H_
6 #define V8_COMPILER_INSTRUCTION_H_ 6 #define V8_COMPILER_INSTRUCTION_H_
7 7
8 #include <deque> 8 #include <deque>
9 #include <iosfwd> 9 #include <iosfwd>
10 #include <map> 10 #include <map>
(...skipping 13 matching lines...) Expand all
24 namespace compiler { 24 namespace compiler {
25 25
26 class Schedule; 26 class Schedule;
27 27
28 class InstructionOperand { 28 class InstructionOperand {
29 public: 29 public:
30 static const int kInvalidVirtualRegister = -1; 30 static const int kInvalidVirtualRegister = -1;
31 31
32 // TODO(dcarney): recover bit. INVALID can be represented as UNALLOCATED with 32 // TODO(dcarney): recover bit. INVALID can be represented as UNALLOCATED with
33 // kInvalidVirtualRegister and some DCHECKS. 33 // kInvalidVirtualRegister and some DCHECKS.
34 enum Kind { INVALID, UNALLOCATED, CONSTANT, IMMEDIATE, ALLOCATED }; 34 enum Kind { INVALID, UNALLOCATED, CONSTANT, IMMEDIATE, EXPLICIT, ALLOCATED };
35 35
36 InstructionOperand() : InstructionOperand(INVALID) {} 36 InstructionOperand() : InstructionOperand(INVALID) {}
37 37
38 Kind kind() const { return KindField::decode(value_); } 38 Kind kind() const { return KindField::decode(value_); }
39 39
40 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \ 40 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \
41 bool Is##name() const { return kind() == type; } 41 bool Is##name() const { return kind() == type; }
42 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID) 42 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID)
43 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED) 43 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED)
44 INSTRUCTION_OPERAND_PREDICATE(Constant, CONSTANT) 44 INSTRUCTION_OPERAND_PREDICATE(Constant, CONSTANT)
45 INSTRUCTION_OPERAND_PREDICATE(Immediate, IMMEDIATE) 45 INSTRUCTION_OPERAND_PREDICATE(Immediate, IMMEDIATE)
46 INSTRUCTION_OPERAND_PREDICATE(Explicit, EXPLICIT)
Mircea Trofin 2015/10/15 15:05:38 Maybe this would be a good time to add a short des
danno 2015/10/23 08:07:49 Done
46 INSTRUCTION_OPERAND_PREDICATE(Allocated, ALLOCATED) 47 INSTRUCTION_OPERAND_PREDICATE(Allocated, ALLOCATED)
47 #undef INSTRUCTION_OPERAND_PREDICATE 48 #undef INSTRUCTION_OPERAND_PREDICATE
48 49
49 inline bool IsRegister() const; 50 inline bool IsRegister() const;
50 inline bool IsDoubleRegister() const; 51 inline bool IsDoubleRegister() const;
51 inline bool IsStackSlot() const; 52 inline bool IsStackSlot() const;
52 inline bool IsDoubleStackSlot() const; 53 inline bool IsDoubleStackSlot() const;
53 54
54 template <typename SubKindOperand> 55 template <typename SubKindOperand>
55 static SubKindOperand* New(Zone* zone, const SubKindOperand& op) { 56 static SubKindOperand* New(Zone* zone, const SubKindOperand& op) {
56 void* buffer = zone->New(sizeof(op)); 57 void* buffer = zone->New(sizeof(op));
57 return new (buffer) SubKindOperand(op); 58 return new (buffer) SubKindOperand(op);
58 } 59 }
59 60
60 static void ReplaceWith(InstructionOperand* dest, 61 static void ReplaceWith(InstructionOperand* dest,
61 const InstructionOperand* src) { 62 const InstructionOperand* src) {
62 *dest = *src; 63 *dest = *src;
63 } 64 }
64 65
65 bool Equals(const InstructionOperand& that) const { 66 bool Equals(const InstructionOperand& that) const {
66 return this->value_ == that.value_; 67 return this->value_ == that.value_;
67 } 68 }
68 69
69 bool Compare(const InstructionOperand& that) const { 70 bool Compare(const InstructionOperand& that) const {
70 return this->value_ < that.value_; 71 return this->value_ < that.value_;
71 } 72 }
72 73
73 bool EqualsModuloType(const InstructionOperand& that) const { 74 bool EqualsCanonicalizeType(const InstructionOperand& that) const {
74 return this->GetValueModuloType() == that.GetValueModuloType(); 75 return this->GetValueCanonicalizeType() == that.GetValueCanonicalizeType();
75 } 76 }
76 77
77 bool CompareModuloType(const InstructionOperand& that) const { 78 bool CompareCanonicalizeType(const InstructionOperand& that) const {
78 return this->GetValueModuloType() < that.GetValueModuloType(); 79 return this->GetValueCanonicalizeType() < that.GetValueCanonicalizeType();
79 } 80 }
80 81
81 protected: 82 protected:
82 explicit InstructionOperand(Kind kind) : value_(KindField::encode(kind)) {} 83 explicit InstructionOperand(Kind kind) : value_(KindField::encode(kind)) {}
83 84
84 inline uint64_t GetValueModuloType() const; 85 inline uint64_t GetValueCanonicalizeType() const;
85 86
86 class KindField : public BitField64<Kind, 0, 3> {}; 87 class KindField : public BitField64<Kind, 0, 3> {};
87 88
88 uint64_t value_; 89 uint64_t value_;
89 }; 90 };
90 91
91 92
92 struct PrintableInstructionOperand { 93 struct PrintableInstructionOperand {
93 const RegisterConfiguration* register_configuration_; 94 const RegisterConfiguration* register_configuration_;
94 InstructionOperand op_; 95 InstructionOperand op_;
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 } 347 }
347 348
348 INSTRUCTION_OPERAND_CASTS(ImmediateOperand, IMMEDIATE); 349 INSTRUCTION_OPERAND_CASTS(ImmediateOperand, IMMEDIATE);
349 350
350 STATIC_ASSERT(KindField::kSize == 3); 351 STATIC_ASSERT(KindField::kSize == 3);
351 class TypeField : public BitField64<ImmediateType, 3, 1> {}; 352 class TypeField : public BitField64<ImmediateType, 3, 1> {};
352 class ValueField : public BitField64<int32_t, 32, 32> {}; 353 class ValueField : public BitField64<int32_t, 32, 32> {};
353 }; 354 };
354 355
355 356
356 class AllocatedOperand : public InstructionOperand { 357 class LocationOperand : public InstructionOperand {
357 public: 358 public:
358 // TODO(dcarney): machine_type makes this now redundant. Just need to know is 359 enum LocationKind { REGISTER, STACK_SLOT };
359 // the operand is a slot or a register.
360 enum AllocatedKind {
361 STACK_SLOT,
362 DOUBLE_STACK_SLOT,
363 REGISTER,
364 DOUBLE_REGISTER
365 };
366 360
367 AllocatedOperand(AllocatedKind kind, MachineType machine_type, int index) 361 LocationOperand(InstructionOperand::Kind operand_kind,
368 : InstructionOperand(ALLOCATED) { 362 LocationOperand::LocationKind location_kind,
369 DCHECK_IMPLIES(kind == REGISTER || kind == DOUBLE_REGISTER, index >= 0); 363 MachineType machine_type, int index)
364 : InstructionOperand(operand_kind) {
365 DCHECK_IMPLIES(location_kind == REGISTER, index >= 0);
370 DCHECK(IsSupportedMachineType(machine_type)); 366 DCHECK(IsSupportedMachineType(machine_type));
371 value_ |= AllocatedKindField::encode(kind); 367 value_ |= LocationKindField::encode(location_kind);
372 value_ |= MachineTypeField::encode(machine_type); 368 value_ |= MachineTypeField::encode(machine_type);
373 value_ |= static_cast<int64_t>(index) << IndexField::kShift; 369 value_ |= static_cast<int64_t>(index) << IndexField::kShift;
374 } 370 }
375 371
376 int index() const { 372 int index() const {
377 DCHECK(STACK_SLOT == allocated_kind() || 373 DCHECK(IsStackSlot() || IsDoubleStackSlot());
378 DOUBLE_STACK_SLOT == allocated_kind());
379 return static_cast<int64_t>(value_) >> IndexField::kShift; 374 return static_cast<int64_t>(value_) >> IndexField::kShift;
380 } 375 }
381 376
382 Register GetRegister() const { 377 Register GetRegister() const {
383 DCHECK(REGISTER == allocated_kind() || DOUBLE_REGISTER == allocated_kind()); 378 DCHECK(IsRegister());
384 return Register::from_code(static_cast<int64_t>(value_) >> 379 return Register::from_code(static_cast<int64_t>(value_) >>
385 IndexField::kShift); 380 IndexField::kShift);
386 } 381 }
387 382
388 DoubleRegister GetDoubleRegister() const { 383 DoubleRegister GetDoubleRegister() const {
389 DCHECK(REGISTER == allocated_kind() || DOUBLE_REGISTER == allocated_kind()); 384 DCHECK(IsDoubleRegister());
390 return DoubleRegister::from_code(static_cast<int64_t>(value_) >> 385 return DoubleRegister::from_code(static_cast<int64_t>(value_) >>
391 IndexField::kShift); 386 IndexField::kShift);
392 } 387 }
393 388
394 AllocatedKind allocated_kind() const { 389 LocationKind location_kind() const {
395 return AllocatedKindField::decode(value_); 390 return LocationKindField::decode(value_);
396 } 391 }
397 392
398 MachineType machine_type() const { return MachineTypeField::decode(value_); } 393 MachineType machine_type() const { return MachineTypeField::decode(value_); }
399 394
400 static AllocatedOperand* New(Zone* zone, AllocatedKind kind,
401 MachineType machine_type, int index) {
402 return InstructionOperand::New(zone,
403 AllocatedOperand(kind, machine_type, index));
404 }
405
406 static bool IsSupportedMachineType(MachineType machine_type) { 395 static bool IsSupportedMachineType(MachineType machine_type) {
407 if (RepresentationOf(machine_type) != machine_type) return false; 396 if (RepresentationOf(machine_type) != machine_type) return false;
408 switch (machine_type) { 397 switch (machine_type) {
409 case kRepWord32: 398 case kRepWord32:
410 case kRepWord64: 399 case kRepWord64:
411 case kRepFloat32: 400 case kRepFloat32:
412 case kRepFloat64: 401 case kRepFloat64:
413 case kRepTagged: 402 case kRepTagged:
414 return true; 403 return true;
415 default: 404 default:
416 return false; 405 return false;
417 } 406 }
418 } 407 }
419 408
420 INSTRUCTION_OPERAND_CASTS(AllocatedOperand, ALLOCATED); 409 static LocationOperand* cast(InstructionOperand* op) {
410 DCHECK(ALLOCATED == op->kind() || EXPLICIT == op->kind());
411 return static_cast<LocationOperand*>(op);
412 }
413
414 static const LocationOperand* cast(const InstructionOperand* op) {
415 DCHECK(ALLOCATED == op->kind() || EXPLICIT == op->kind());
416 return static_cast<const LocationOperand*>(op);
417 }
418
419 static LocationOperand cast(const InstructionOperand& op) {
420 DCHECK(ALLOCATED == op.kind() || EXPLICIT == op.kind());
421 return *static_cast<const LocationOperand*>(&op);
422 }
421 423
422 STATIC_ASSERT(KindField::kSize == 3); 424 STATIC_ASSERT(KindField::kSize == 3);
423 class AllocatedKindField : public BitField64<AllocatedKind, 3, 2> {}; 425 class LocationKindField : public BitField64<LocationKind, 3, 2> {};
424 class MachineTypeField : public BitField64<MachineType, 5, 16> {}; 426 class MachineTypeField : public BitField64<MachineType, 5, 16> {};
425 class IndexField : public BitField64<int32_t, 35, 29> {}; 427 class IndexField : public BitField64<int32_t, 35, 29> {};
426 }; 428 };
427 429
428 430
431 class ExplicitOperand : public LocationOperand {
432 public:
433 ExplicitOperand(LocationKind kind, MachineType machine_type, int index)
434 : LocationOperand(EXPLICIT, kind, machine_type, index) {}
435
436 static ExplicitOperand* New(Zone* zone, LocationKind kind,
437 MachineType machine_type, int index) {
438 return InstructionOperand::New(zone,
439 ExplicitOperand(kind, machine_type, index));
440 }
441
442 INSTRUCTION_OPERAND_CASTS(ExplicitOperand, EXPLICIT);
443 };
444
445
446 class AllocatedOperand : public LocationOperand {
447 public:
448 AllocatedOperand(LocationKind kind, MachineType machine_type, int index)
449 : LocationOperand(ALLOCATED, kind, machine_type, index) {}
450
451 static AllocatedOperand* New(Zone* zone, LocationKind kind,
452 MachineType machine_type, int index) {
453 return InstructionOperand::New(zone,
454 AllocatedOperand(kind, machine_type, index));
455 }
456
457 INSTRUCTION_OPERAND_CASTS(AllocatedOperand, ALLOCATED);
458 };
459
460
429 #undef INSTRUCTION_OPERAND_CASTS 461 #undef INSTRUCTION_OPERAND_CASTS
430 462
431 463
432 #define ALLOCATED_OPERAND_LIST(V) \ 464 bool InstructionOperand::IsRegister() const {
433 V(StackSlot, STACK_SLOT) \ 465 return (IsAllocated() || IsExplicit()) &&
434 V(DoubleStackSlot, DOUBLE_STACK_SLOT) \ 466 LocationOperand::cast(this)->location_kind() ==
435 V(Register, REGISTER) \ 467 LocationOperand::REGISTER &&
436 V(DoubleRegister, DOUBLE_REGISTER) 468 !IsFloatingPoint(LocationOperand::cast(this)->machine_type());
469 }
437 470
471 bool InstructionOperand::IsDoubleRegister() const {
472 return (IsAllocated() || IsExplicit()) &&
473 LocationOperand::cast(this)->location_kind() ==
474 LocationOperand::REGISTER &&
475 IsFloatingPoint(LocationOperand::cast(this)->machine_type());
476 }
438 477
439 #define ALLOCATED_OPERAND_IS(SubKind, kOperandKind) \ 478 bool InstructionOperand::IsStackSlot() const {
440 bool InstructionOperand::Is##SubKind() const { \ 479 return (IsAllocated() || IsExplicit()) &&
441 return IsAllocated() && \ 480 LocationOperand::cast(this)->location_kind() ==
442 AllocatedOperand::cast(this)->allocated_kind() == \ 481 LocationOperand::STACK_SLOT &&
443 AllocatedOperand::kOperandKind; \ 482 !IsFloatingPoint(LocationOperand::cast(this)->machine_type());
444 } 483 }
445 ALLOCATED_OPERAND_LIST(ALLOCATED_OPERAND_IS)
446 #undef ALLOCATED_OPERAND_IS
447 484
485 bool InstructionOperand::IsDoubleStackSlot() const {
486 return (IsAllocated() || IsExplicit()) &&
487 LocationOperand::cast(this)->location_kind() ==
488 LocationOperand::STACK_SLOT &&
489 IsFloatingPoint(LocationOperand::cast(this)->machine_type());
490 }
448 491
449 // TODO(dcarney): these subkinds are now pretty useless, nuke. 492 uint64_t InstructionOperand::GetValueCanonicalizeType() const {
450 #define ALLOCATED_OPERAND_CLASS(SubKind, kOperandKind) \ 493 if (IsAllocated() || IsExplicit()) {
451 class SubKind##Operand final : public AllocatedOperand { \
452 public: \
453 explicit SubKind##Operand(MachineType machine_type, int index) \
454 : AllocatedOperand(kOperandKind, machine_type, index) {} \
455 \
456 static SubKind##Operand* New(Zone* zone, MachineType machine_type, \
457 int index) { \
458 return InstructionOperand::New(zone, \
459 SubKind##Operand(machine_type, index)); \
460 } \
461 \
462 static SubKind##Operand* cast(InstructionOperand* op) { \
463 DCHECK_EQ(kOperandKind, AllocatedOperand::cast(op)->allocated_kind()); \
464 return reinterpret_cast<SubKind##Operand*>(op); \
465 } \
466 \
467 static const SubKind##Operand* cast(const InstructionOperand* op) { \
468 DCHECK_EQ(kOperandKind, AllocatedOperand::cast(op)->allocated_kind()); \
469 return reinterpret_cast<const SubKind##Operand*>(op); \
470 } \
471 \
472 static SubKind##Operand cast(const InstructionOperand& op) { \
473 DCHECK_EQ(kOperandKind, AllocatedOperand::cast(op).allocated_kind()); \
474 return *static_cast<const SubKind##Operand*>(&op); \
475 } \
476 };
477 ALLOCATED_OPERAND_LIST(ALLOCATED_OPERAND_CLASS)
478 #undef ALLOCATED_OPERAND_CLASS
479
480
481 uint64_t InstructionOperand::GetValueModuloType() const {
482 if (IsAllocated()) {
483 // TODO(dcarney): put machine type last and mask. 494 // TODO(dcarney): put machine type last and mask.
484 return AllocatedOperand::MachineTypeField::update(this->value_, kMachNone); 495 MachineType canonicalized_machine_type =
496 IsFloatingPoint(LocationOperand::cast(this)->machine_type())
497 ? kMachFloat64
498 : kMachNone;
499 return LocationOperand::MachineTypeField::update(
500 this->value_, canonicalized_machine_type);
485 } 501 }
486 return this->value_; 502 return this->value_;
487 } 503 }
488 504
489 505
490 // Required for maps that don't care about machine type. 506 // Required for maps that don't care about machine type.
491 struct CompareOperandModuloType { 507 struct CompareOperandModuloType {
492 bool operator()(const InstructionOperand& a, 508 bool operator()(const InstructionOperand& a,
493 const InstructionOperand& b) const { 509 const InstructionOperand& b) const {
494 return a.CompareModuloType(b); 510 return a.CompareCanonicalizeType(b);
495 } 511 }
496 }; 512 };
497 513
498 514
499 class MoveOperands final : public ZoneObject { 515 class MoveOperands final : public ZoneObject {
500 public: 516 public:
501 MoveOperands(const InstructionOperand& source, 517 MoveOperands(const InstructionOperand& source,
502 const InstructionOperand& destination) 518 const InstructionOperand& destination)
503 : source_(source), destination_(destination) { 519 : source_(source), destination_(destination) {
504 DCHECK(!source.IsInvalid() && !destination.IsInvalid()); 520 DCHECK(!source.IsInvalid() && !destination.IsInvalid());
(...skipping 11 matching lines...) Expand all
516 532
517 // The gap resolver marks moves as "in-progress" by clearing the 533 // The gap resolver marks moves as "in-progress" by clearing the
518 // destination (but not the source). 534 // destination (but not the source).
519 bool IsPending() const { 535 bool IsPending() const {
520 return destination_.IsInvalid() && !source_.IsInvalid(); 536 return destination_.IsInvalid() && !source_.IsInvalid();
521 } 537 }
522 void SetPending() { destination_ = InstructionOperand(); } 538 void SetPending() { destination_ = InstructionOperand(); }
523 539
524 // True if this move a move into the given destination operand. 540 // True if this move a move into the given destination operand.
525 bool Blocks(const InstructionOperand& operand) const { 541 bool Blocks(const InstructionOperand& operand) const {
526 return !IsEliminated() && source().EqualsModuloType(operand); 542 return !IsEliminated() && source().EqualsCanonicalizeType(operand);
527 } 543 }
528 544
529 // A move is redundant if it's been eliminated or if its source and 545 // A move is redundant if it's been eliminated or if its source and
530 // destination are the same. 546 // destination are the same.
531 bool IsRedundant() const { 547 bool IsRedundant() const {
532 DCHECK_IMPLIES(!destination_.IsInvalid(), !destination_.IsConstant()); 548 DCHECK_IMPLIES(!destination_.IsInvalid(), !destination_.IsConstant());
533 return IsEliminated() || source_.EqualsModuloType(destination_); 549 return IsEliminated() || source_.EqualsCanonicalizeType(destination_);
534 } 550 }
535 551
536 // We clear both operands to indicate move that's been eliminated. 552 // We clear both operands to indicate move that's been eliminated.
537 void Eliminate() { source_ = destination_ = InstructionOperand(); } 553 void Eliminate() { source_ = destination_ = InstructionOperand(); }
538 bool IsEliminated() const { 554 bool IsEliminated() const {
539 DCHECK_IMPLIES(source_.IsInvalid(), destination_.IsInvalid()); 555 DCHECK_IMPLIES(source_.IsInvalid(), destination_.IsInvalid());
540 return source_.IsInvalid(); 556 return source_.IsInvalid();
541 } 557 }
542 558
543 private: 559 private:
(...skipping 684 matching lines...) Expand 10 before | Expand all | Expand 10 after
1228 1244
1229 1245
1230 std::ostream& operator<<(std::ostream& os, 1246 std::ostream& operator<<(std::ostream& os,
1231 const PrintableInstructionSequence& code); 1247 const PrintableInstructionSequence& code);
1232 1248
1233 } // namespace compiler 1249 } // namespace compiler
1234 } // namespace internal 1250 } // namespace internal
1235 } // namespace v8 1251 } // namespace v8
1236 1252
1237 #endif // V8_COMPILER_INSTRUCTION_H_ 1253 #endif // V8_COMPILER_INSTRUCTION_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698