[turbofan] cleanup InstructionOperand a little
authordcarney <dcarney@chromium.org>
Thu, 9 Apr 2015 09:15:28 +0000 (02:15 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 9 Apr 2015 09:15:32 +0000 (09:15 +0000)
- ConstantOperand was using a too-small field too store its virtual register
- drop ConvertTo, replace it with simple copy
- split AllocatedOperand off from Immediate and Constant to make assignment clearer, also paving the way for small Immediates
- put zone first in *Operand::New
- driveby: drop delayed ssa deconstruction experiment

R=titzer@chromium.org
BUG=

Review URL: https://codereview.chromium.org/1050803002

Cr-Commit-Position: refs/heads/master@{#27692}

23 files changed:
src/compiler/arm/code-generator-arm.cc
src/compiler/arm64/code-generator-arm64.cc
src/compiler/code-generator-impl.h
src/compiler/code-generator.cc
src/compiler/gap-resolver.cc
src/compiler/graph-visualizer.cc
src/compiler/ia32/code-generator-ia32.cc
src/compiler/instruction.cc
src/compiler/instruction.h
src/compiler/mips/code-generator-mips.cc
src/compiler/mips64/code-generator-mips64.cc
src/compiler/move-optimizer.cc
src/compiler/ppc/code-generator-ppc.cc
src/compiler/register-allocator-verifier.cc
src/compiler/register-allocator.cc
src/compiler/register-allocator.h
src/compiler/x64/code-generator-x64.cc
src/flag-definitions.h
test/cctest/compiler/test-gap-resolver.cc
test/cctest/compiler/test-jump-threading.cc
test/unittests/compiler/instruction-selector-unittest.cc
test/unittests/compiler/instruction-selector-unittest.h
test/unittests/compiler/move-optimizer-unittest.cc

index 059dadd5e021c37ed805c54d4b625543bb47ca73..4c5b2924c58275d1a7fefccf29708956673d401f 100644 (file)
@@ -151,7 +151,8 @@ class ArmOperandConverter FINAL : public InstructionOperandConverter {
     DCHECK(!op->IsDoubleRegister());
     DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
     // The linkage computes where all spill slots are located.
-    FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), 0);
+    FrameOffset offset = linkage()->GetFrameOffset(
+        AllocatedOperand::cast(op)->index(), frame(), 0);
     return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset());
   }
 };
index c0f22b70636ba0c54b8dff29de08af5394040485..964ef3813102582422c230c6c8ec2d350e469c09 100644 (file)
@@ -188,7 +188,8 @@ class Arm64OperandConverter FINAL : public InstructionOperandConverter {
     DCHECK(!op->IsDoubleRegister());
     DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
     // The linkage computes where all spill slots are located.
-    FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), 0);
+    FrameOffset offset = linkage()->GetFrameOffset(
+        AllocatedOperand::cast(op)->index(), frame(), 0);
     return MemOperand(offset.from_stack_pointer() ? masm->StackPointer() : fp,
                       offset.offset());
   }
index 74233ac6fe1dcdc47f0371d0fa99349bfbbb5042..87feddb9eb604d0da7679d9d1eb54f59999e65a6 100644 (file)
@@ -90,20 +90,20 @@ class InstructionOperandConverter {
   }
 
   Register ToRegister(InstructionOperand* op) {
-    DCHECK(op->IsRegister());
-    return Register::FromAllocationIndex(op->index());
+    return Register::FromAllocationIndex(RegisterOperand::cast(op)->index());
   }
 
   DoubleRegister ToDoubleRegister(InstructionOperand* op) {
-    DCHECK(op->IsDoubleRegister());
-    return DoubleRegister::FromAllocationIndex(op->index());
+    return DoubleRegister::FromAllocationIndex(
+        DoubleRegisterOperand::cast(op)->index());
   }
 
   Constant ToConstant(InstructionOperand* op) {
     if (op->IsImmediate()) {
-      return gen_->code()->GetImmediate(op->index());
+      return gen_->code()->GetImmediate(ImmediateOperand::cast(op)->index());
     }
-    return gen_->code()->GetConstant(op->index());
+    return gen_->code()->GetConstant(
+        ConstantOperand::cast(op)->virtual_register());
   }
 
   double ToDouble(InstructionOperand* op) { return ToConstant(op).ToFloat64(); }
index f1a0975fe286f225a379131c65f0f665f7e24ee5..1fa61041d9b0648d3a39d988aaeaa4fd2b84cd21 100644 (file)
@@ -176,9 +176,11 @@ void CodeGenerator::RecordSafepoint(PointerMap* pointers, Safepoint::Kind kind,
   for (int i = 0; i < operands->length(); i++) {
     InstructionOperand* pointer = operands->at(i);
     if (pointer->IsStackSlot()) {
-      safepoint.DefinePointerSlot(pointer->index(), zone());
+      safepoint.DefinePointerSlot(StackSlotOperand::cast(pointer)->index(),
+                                  zone());
     } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) {
-      Register reg = Register::FromAllocationIndex(pointer->index());
+      Register reg = Register::FromAllocationIndex(
+          RegisterOperand::cast(pointer)->index());
       safepoint.DefinePointerRegister(reg, zone());
     }
   }
@@ -512,18 +514,19 @@ void CodeGenerator::AddTranslationForOperand(Translation* translation,
     // rather than creating an int value.
     if (type == kMachBool || type == kRepBit || type == kMachInt32 ||
         type == kMachInt8 || type == kMachInt16) {
-      translation->StoreInt32StackSlot(op->index());
+      translation->StoreInt32StackSlot(StackSlotOperand::cast(op)->index());
     } else if (type == kMachUint32 || type == kMachUint16 ||
                type == kMachUint8) {
-      translation->StoreUint32StackSlot(op->index());
+      translation->StoreUint32StackSlot(StackSlotOperand::cast(op)->index());
     } else if ((type & kRepMask) == kRepTagged) {
-      translation->StoreStackSlot(op->index());
+      translation->StoreStackSlot(StackSlotOperand::cast(op)->index());
     } else {
       CHECK(false);
     }
   } else if (op->IsDoubleStackSlot()) {
     DCHECK((type & (kRepFloat32 | kRepFloat64)) != 0);
-    translation->StoreDoubleStackSlot(op->index());
+    translation->StoreDoubleStackSlot(
+        DoubleStackSlotOperand::cast(op)->index());
   } else if (op->IsRegister()) {
     InstructionOperandConverter converter(this, instr);
     // TODO(jarin) kMachBool and kRepBit should materialize true and false
index f369607170b2429c9c0d21f19f6836770b53dc59..cdf80857f0e3260292e513a82b4f2b27e62942c8 100644 (file)
@@ -15,12 +15,10 @@ namespace compiler {
 typedef ZoneList<MoveOperands>::iterator op_iterator;
 
 #ifdef ENABLE_SLOW_DCHECKS
-// TODO(svenpanne) Brush up InstructionOperand with comparison?
 struct InstructionOperandComparator {
   bool operator()(const InstructionOperand* x,
                   const InstructionOperand* y) const {
-    return (x->kind() < y->kind()) ||
-           (x->kind() == y->kind() && x->index() < y->index());
+    return *x < *y;
   }
 };
 #endif
index 339750985201ee54ff42b54ddefe3b1b885fa0f1..5d255f064ec2c32fce563097778c9f989aab214d 100644 (file)
@@ -708,7 +708,7 @@ void GraphC1Visualizer::PrintLiveRange(LiveRange* range, const char* type) {
     PrintIndent();
     os_ << range->id() << " " << type;
     if (range->HasRegisterAssigned()) {
-      InstructionOperand op = range->GetAssignedOperand();
+      AllocatedOperand op = AllocatedOperand::cast(range->GetAssignedOperand());
       int assigned_reg = op.index();
       if (op.IsDoubleRegister()) {
         os_ << " \"" << DoubleRegister::AllocationIndexToString(assigned_reg)
@@ -718,18 +718,21 @@ void GraphC1Visualizer::PrintLiveRange(LiveRange* range, const char* type) {
         os_ << " \"" << Register::AllocationIndexToString(assigned_reg) << "\"";
       }
     } else if (range->IsSpilled()) {
+      auto top = range->TopLevel();
       int index = -1;
-      if (range->TopLevel()->HasSpillRange()) {
+      if (top->HasSpillRange()) {
         index = kMaxInt;  // This hasn't been set yet.
+      } else if (top->GetSpillOperand()->IsConstant()) {
+        os_ << " \"const(nostack):"
+            << ConstantOperand::cast(top->GetSpillOperand())->virtual_register()
+            << "\"";
       } else {
-        index = range->TopLevel()->GetSpillOperand()->index();
-      }
-      if (range->TopLevel()->Kind() == DOUBLE_REGISTERS) {
-        os_ << " \"double_stack:" << index << "\"";
-      } else if (range->TopLevel()->Kind() == GENERAL_REGISTERS) {
-        os_ << " \"stack:" << index << "\"";
-      } else {
-        os_ << " \"const(nostack):" << index << "\"";
+        index = AllocatedOperand::cast(top->GetSpillOperand())->index();
+        if (top->Kind() == DOUBLE_REGISTERS) {
+          os_ << " \"double_stack:" << index << "\"";
+        } else if (top->Kind() == GENERAL_REGISTERS) {
+          os_ << " \"stack:" << index << "\"";
+        }
       }
     }
     int parent_index = -1;
index 298f53cca6337bcbba9f3cf6182f4a256555aa1f..7ec7eba8111f51012561545c8547822258134412 100644 (file)
@@ -47,7 +47,8 @@ class IA32OperandConverter : public InstructionOperandConverter {
     }
     DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
     // The linkage computes where all spill slots are located.
-    FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), extra);
+    FrameOffset offset = linkage()->GetFrameOffset(
+        AllocatedOperand::cast(op)->index(), frame(), extra);
     return Operand(offset.from_stack_pointer() ? esp : ebp, offset.offset());
   }
 
index 45bd3f75c12268357e1ebe464006ec18bc8c4746..177de6f379a4fc231677f5c8caccccec264cbd7f 100644 (file)
@@ -42,17 +42,23 @@ std::ostream& operator<<(std::ostream& os,
       }
     }
     case InstructionOperand::CONSTANT:
-      return os << "[constant:" << op.index() << "]";
+      return os << "[constant:" << ConstantOperand::cast(op).virtual_register()
+                << "]";
     case InstructionOperand::IMMEDIATE:
-      return os << "[immediate:" << op.index() << "]";
+      return os << "[immediate:" << ImmediateOperand::cast(op).index() << "]";
     case InstructionOperand::STACK_SLOT:
-      return os << "[stack:" << op.index() << "]";
+      return os << "[stack:" << StackSlotOperand::cast(op).index() << "]";
     case InstructionOperand::DOUBLE_STACK_SLOT:
-      return os << "[double_stack:" << op.index() << "]";
+      return os << "[double_stack:" << DoubleStackSlotOperand::cast(op).index()
+                << "]";
     case InstructionOperand::REGISTER:
-      return os << "[" << conf->general_register_name(op.index()) << "|R]";
+      return os << "["
+                << conf->general_register_name(
+                       RegisterOperand::cast(op).index()) << "|R]";
     case InstructionOperand::DOUBLE_REGISTER:
-      return os << "[" << conf->double_register_name(op.index()) << "|R]";
+      return os << "["
+                << conf->double_register_name(
+                       DoubleRegisterOperand::cast(op).index()) << "|R]";
     case InstructionOperand::INVALID:
       return os << "(x)";
   }
@@ -173,7 +179,7 @@ std::ostream& operator<<(std::ostream& os,
 
 void PointerMap::RecordPointer(InstructionOperand* op, Zone* zone) {
   // Do not record arguments as pointers.
-  if (op->IsStackSlot() && op->index() < 0) return;
+  if (op->IsStackSlot() && StackSlotOperand::cast(op)->index() < 0) return;
   DCHECK(!op->IsDoubleRegister() && !op->IsDoubleStackSlot());
   pointer_operands_.Add(op, zone);
 }
@@ -181,7 +187,7 @@ void PointerMap::RecordPointer(InstructionOperand* op, Zone* zone) {
 
 void PointerMap::RemovePointer(InstructionOperand* op) {
   // Do not record arguments as pointers.
-  if (op->IsStackSlot() && op->index() < 0) return;
+  if (op->IsStackSlot() && StackSlotOperand::cast(op)->index() < 0) return;
   DCHECK(!op->IsDoubleRegister() && !op->IsDoubleStackSlot());
   for (int i = 0; i < pointer_operands_.length(); ++i) {
     if (pointer_operands_[i]->Equals(op)) {
@@ -194,7 +200,7 @@ void PointerMap::RemovePointer(InstructionOperand* op) {
 
 void PointerMap::RecordUntagged(InstructionOperand* op, Zone* zone) {
   // Do not record arguments as pointers.
-  if (op->IsStackSlot() && op->index() < 0) return;
+  if (op->IsStackSlot() && StackSlotOperand::cast(op)->index() < 0) return;
   DCHECK(!op->IsDoubleRegister() && !op->IsDoubleStackSlot());
   untagged_operands_.Add(op, zone);
 }
@@ -593,6 +599,16 @@ int InstructionSequence::GetFrameStateDescriptorCount() {
 }
 
 
+RpoNumber InstructionSequence::InputRpo(Instruction* instr, size_t index) {
+  InstructionOperand* operand = instr->InputAt(index);
+  Constant constant =
+      operand->IsImmediate()
+          ? GetImmediate(ImmediateOperand::cast(operand)->index())
+          : GetConstant(ConstantOperand::cast(operand)->virtual_register());
+  return constant.ToRpoNumber();
+}
+
+
 FrameStateDescriptor::FrameStateDescriptor(
     Zone* zone, const FrameStateCallInfo& state_info, size_t parameters_count,
     size_t locals_count, size_t stack_count, FrameStateDescriptor* outer_state)
index a5616b2a56352eac3961538edb52b2ec667f8d72..3615e37affcc9053f029df2f67b34c36e949d893 100644 (file)
@@ -27,9 +27,7 @@ class Schedule;
 // A couple of reserved opcodes are used for internal use.
 const InstructionCode kSourcePositionInstruction = -1;
 
-#define INSTRUCTION_OPERAND_LIST(V)     \
-  V(Constant, CONSTANT)                 \
-  V(Immediate, IMMEDIATE)               \
+#define ALLOCATED_OPERAND_LIST(V)       \
   V(StackSlot, STACK_SLOT)              \
   V(DoubleStackSlot, DOUBLE_STACK_SLOT) \
   V(Register, REGISTER)                 \
@@ -50,65 +48,50 @@ class InstructionOperand {
     DOUBLE_REGISTER
   };
 
-  InstructionOperand() { ConvertTo(INVALID, 0, kInvalidVirtualRegister); }
-
-  InstructionOperand(Kind kind, int index) {
-    DCHECK(kind != UNALLOCATED && kind != INVALID);
-    ConvertTo(kind, index, kInvalidVirtualRegister);
-  }
-
-  static InstructionOperand* New(Zone* zone, Kind kind, int index) {
-    return New(zone, InstructionOperand(kind, index));
-  }
+  InstructionOperand()
+      : InstructionOperand(INVALID, 0, kInvalidVirtualRegister) {}
 
   Kind kind() const { return KindField::decode(value_); }
-  // TODO(dcarney): move this to subkind operand.
-  int index() const {
-    DCHECK(kind() != UNALLOCATED && kind() != INVALID);
-    return static_cast<int64_t>(value_) >> IndexField::kShift;
-  }
+
 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \
   bool Is##name() const { return kind() == type; }
-  INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE)
+  ALLOCATED_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE)
+  INSTRUCTION_OPERAND_PREDICATE(Constant, CONSTANT)
+  INSTRUCTION_OPERAND_PREDICATE(Immediate, IMMEDIATE)
   INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED)
   INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID)
 #undef INSTRUCTION_OPERAND_PREDICATE
+
   bool Equals(const InstructionOperand* other) const {
     return value_ == other->value_;
   }
 
-  void ConvertTo(Kind kind, int index) {
-    DCHECK(kind != UNALLOCATED && kind != INVALID);
-    ConvertTo(kind, index, kInvalidVirtualRegister);
-  }
-
   // Useful for map/set keys.
   bool operator<(const InstructionOperand& op) const {
     return value_ < op.value_;
   }
 
- protected:
   template <typename SubKindOperand>
   static SubKindOperand* New(Zone* zone, const SubKindOperand& op) {
     void* buffer = zone->New(sizeof(op));
     return new (buffer) SubKindOperand(op);
   }
 
-  InstructionOperand(Kind kind, int index, int virtual_register) {
-    ConvertTo(kind, index, virtual_register);
+  static void ReplaceWith(InstructionOperand* dest,
+                          const InstructionOperand* src) {
+    *dest = *src;
   }
 
-  void ConvertTo(Kind kind, int index, int virtual_register) {
+ protected:
+  InstructionOperand(Kind kind, int index, int virtual_register) {
     if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0);
-    if (kind != UNALLOCATED) {
+    if (kind != UNALLOCATED && kind != CONSTANT) {
       DCHECK(virtual_register == kInvalidVirtualRegister);
     }
     value_ = KindField::encode(kind);
     value_ |=
         VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
     value_ |= static_cast<int64_t>(index) << IndexField::kShift;
-    DCHECK(((kind == UNALLOCATED || kind == INVALID) && index == 0) ||
-           this->index() == index);
   }
 
   typedef BitField64<Kind, 0, 3> KindField;
@@ -317,6 +300,138 @@ class UnallocatedOperand : public InstructionOperand {
 };
 
 
+class ConstantOperand : public InstructionOperand {
+ public:
+  explicit ConstantOperand(int virtual_register)
+      : InstructionOperand(CONSTANT, 0, virtual_register) {}
+
+  int32_t virtual_register() const {
+    return static_cast<int32_t>(VirtualRegisterField::decode(value_));
+  }
+
+  static ConstantOperand* New(Zone* zone, int virtual_register) {
+    return InstructionOperand::New(zone, ConstantOperand(virtual_register));
+  }
+
+  static ConstantOperand* cast(InstructionOperand* op) {
+    DCHECK(op->kind() == CONSTANT);
+    return static_cast<ConstantOperand*>(op);
+  }
+
+  static const ConstantOperand* cast(const InstructionOperand* op) {
+    DCHECK(op->kind() == CONSTANT);
+    return static_cast<const ConstantOperand*>(op);
+  }
+
+  static ConstantOperand cast(const InstructionOperand& op) {
+    DCHECK(op.kind() == CONSTANT);
+    return *static_cast<const ConstantOperand*>(&op);
+  }
+};
+
+
+class ImmediateOperand : public InstructionOperand {
+ public:
+  explicit ImmediateOperand(int index)
+      : InstructionOperand(IMMEDIATE, index, kInvalidVirtualRegister) {}
+
+  int index() const {
+    return static_cast<int64_t>(value_) >> IndexField::kShift;
+  }
+
+  static ImmediateOperand* New(Zone* zone, int index) {
+    return InstructionOperand::New(zone, ImmediateOperand(index));
+  }
+
+  static ImmediateOperand* cast(InstructionOperand* op) {
+    DCHECK(op->kind() == IMMEDIATE);
+    return static_cast<ImmediateOperand*>(op);
+  }
+
+  static const ImmediateOperand* cast(const InstructionOperand* op) {
+    DCHECK(op->kind() == IMMEDIATE);
+    return static_cast<const ImmediateOperand*>(op);
+  }
+
+  static ImmediateOperand cast(const InstructionOperand& op) {
+    DCHECK(op.kind() == IMMEDIATE);
+    return *static_cast<const ImmediateOperand*>(&op);
+  }
+};
+
+
+class AllocatedOperand : public InstructionOperand {
+#define ALLOCATED_OPERAND_CHECK(Name, Kind) || kind == Kind
+#define CHECK_ALLOCATED_KIND()                                   \
+  DCHECK(false ALLOCATED_OPERAND_LIST(ALLOCATED_OPERAND_CHECK)); \
+  USE(kind);
+
+ public:
+  int index() const {
+    return static_cast<int64_t>(value_) >> IndexField::kShift;
+  }
+
+  AllocatedOperand(Kind kind, int index)
+      : InstructionOperand(kind, index, kInvalidVirtualRegister) {
+    CHECK_ALLOCATED_KIND();
+  }
+
+  static AllocatedOperand* New(Zone* zone, Kind kind, int index) {
+    return InstructionOperand::New(zone, AllocatedOperand(kind, index));
+  }
+
+  static AllocatedOperand* cast(InstructionOperand* op) {
+    Kind kind = op->kind();
+    CHECK_ALLOCATED_KIND();
+    return static_cast<AllocatedOperand*>(op);
+  }
+
+  static const AllocatedOperand* cast(const InstructionOperand* op) {
+    Kind kind = op->kind();
+    CHECK_ALLOCATED_KIND();
+    return static_cast<const AllocatedOperand*>(op);
+  }
+
+  static AllocatedOperand cast(const InstructionOperand& op) {
+    Kind kind = op.kind();
+    CHECK_ALLOCATED_KIND();
+    return *static_cast<const AllocatedOperand*>(&op);
+  }
+
+#undef CHECK_ALLOCATED_KIND
+#undef ALLOCATED_OPERAND_CAST_CHECK
+};
+
+
+#define INSTRUCTION_SUBKIND_OPERAND_CLASS(SubKind, kOperandKind)        \
+  class SubKind##Operand FINAL : public AllocatedOperand {              \
+   public:                                                              \
+    explicit SubKind##Operand(int index)                                \
+        : AllocatedOperand(kOperandKind, index) {}                      \
+                                                                        \
+    static SubKind##Operand* New(Zone* zone, int index) {               \
+      return InstructionOperand::New(zone, SubKind##Operand(index));    \
+    }                                                                   \
+                                                                        \
+    static SubKind##Operand* cast(InstructionOperand* op) {             \
+      DCHECK(op->kind() == kOperandKind);                               \
+      return reinterpret_cast<SubKind##Operand*>(op);                   \
+    }                                                                   \
+                                                                        \
+    static const SubKind##Operand* cast(const InstructionOperand* op) { \
+      DCHECK(op->kind() == kOperandKind);                               \
+      return reinterpret_cast<const SubKind##Operand*>(op);             \
+    }                                                                   \
+                                                                        \
+    static SubKind##Operand cast(const InstructionOperand& op) {        \
+      DCHECK(op.kind() == kOperandKind);                                \
+      return *static_cast<const SubKind##Operand*>(&op);                \
+    }                                                                   \
+  };
+ALLOCATED_OPERAND_LIST(INSTRUCTION_SUBKIND_OPERAND_CLASS)
+#undef INSTRUCTION_SUBKIND_OPERAND_CLASS
+
+
 class MoveOperands FINAL {
  public:
   MoveOperands(InstructionOperand* source, InstructionOperand* destination)
@@ -337,11 +452,11 @@ class MoveOperands FINAL {
     return !IsEliminated() && source()->Equals(operand);
   }
 
-  // A move is redundant if it's been eliminated, if its source and
-  // destination are the same, or if its destination is  constant.
+  // A move is redundant if it's been eliminated or if its source and
+  // destination are the same.
   bool IsRedundant() const {
-    return IsEliminated() || source_->Equals(destination_) ||
-           (destination_ != NULL && destination_->IsConstant());
+    DCHECK_IMPLIES(destination_ != nullptr, !destination_->IsConstant());
+    return IsEliminated() || source_->Equals(destination_);
   }
 
   // We clear both operands to indicate move that's been eliminated.
@@ -366,35 +481,6 @@ struct PrintableMoveOperands {
 std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo);
 
 
-#define INSTRUCTION_SUBKIND_OPERAND_CLASS(SubKind, kOperandKind)        \
-  class SubKind##Operand FINAL : public InstructionOperand {            \
-   public:                                                              \
-    explicit SubKind##Operand(int index)                                \
-        : InstructionOperand(kOperandKind, index) {}                    \
-                                                                        \
-    static SubKind##Operand* New(int index, Zone* zone) {               \
-      return InstructionOperand::New(zone, SubKind##Operand(index));    \
-    }                                                                   \
-                                                                        \
-    static SubKind##Operand* cast(InstructionOperand* op) {             \
-      DCHECK(op->kind() == kOperandKind);                               \
-      return reinterpret_cast<SubKind##Operand*>(op);                   \
-    }                                                                   \
-                                                                        \
-    static const SubKind##Operand* cast(const InstructionOperand* op) { \
-      DCHECK(op->kind() == kOperandKind);                               \
-      return reinterpret_cast<const SubKind##Operand*>(op);             \
-    }                                                                   \
-                                                                        \
-    static SubKind##Operand cast(const InstructionOperand& op) {        \
-      DCHECK(op.kind() == kOperandKind);                                \
-      return *static_cast<const SubKind##Operand*>(&op);                \
-    }                                                                   \
-  };
-INSTRUCTION_OPERAND_LIST(INSTRUCTION_SUBKIND_OPERAND_CLASS)
-#undef INSTRUCTION_SUBKIND_OPERAND_CLASS
-
-
 class ParallelMove FINAL : public ZoneObject {
  public:
   explicit ParallelMove(Zone* zone) : move_operands_(4, zone) {}
@@ -1016,12 +1102,7 @@ class InstructionSequence FINAL : public ZoneObject {
   FrameStateDescriptor* GetFrameStateDescriptor(StateId deoptimization_id);
   int GetFrameStateDescriptorCount();
 
-  RpoNumber InputRpo(Instruction* instr, size_t index) {
-    InstructionOperand* operand = instr->InputAt(index);
-    Constant constant = operand->IsImmediate() ? GetImmediate(operand->index())
-                                               : GetConstant(operand->index());
-    return constant.ToRpoNumber();
-  }
+  RpoNumber InputRpo(Instruction* instr, size_t index);
 
  private:
   friend std::ostream& operator<<(std::ostream& os,
index ec545156e55704b2d5701b2c56ace6baaa6376ff..1dee98b9f425c35cf660277a488e772c8de1a18b 100644 (file)
@@ -110,7 +110,8 @@ class MipsOperandConverter FINAL : public InstructionOperandConverter {
     DCHECK(!op->IsDoubleRegister());
     DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
     // The linkage computes where all spill slots are located.
-    FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), 0);
+    FrameOffset offset = linkage()->GetFrameOffset(
+        AllocatedOperand::cast(op)->index(), frame(), 0);
     return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset());
   }
 };
index 8091ff96928c54c19a999556a8d6cd2f9f228ac4..2058b153b55fd6ed92b786d54487e08bfb926ee3 100644 (file)
@@ -110,7 +110,8 @@ class MipsOperandConverter FINAL : public InstructionOperandConverter {
     DCHECK(!op->IsDoubleRegister());
     DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
     // The linkage computes where all spill slots are located.
-    FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), 0);
+    FrameOffset offset = linkage()->GetFrameOffset(
+        AllocatedOperand::cast(op)->index(), frame(), 0);
     return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset());
   }
 };
index 7c2911e7f5aea03f9a87bc1257088ab43826fe14..56fdf038f40a6da08d09b728325dd6fb96686451 100644 (file)
@@ -256,8 +256,7 @@ void MoveOptimizer::FinalizeMoves(Instruction* instr) {
       loads.push_back(move);
       // Replace source with copy for later use.
       auto dest = move->destination();
-      move->set_destination(
-          InstructionOperand::New(code_zone(), dest->kind(), dest->index()));
+      move->set_destination(InstructionOperand::New(code_zone(), *dest));
       continue;
     }
     if ((found->destination()->IsStackSlot() ||
@@ -266,12 +265,10 @@ void MoveOptimizer::FinalizeMoves(Instruction* instr) {
           move->destination()->IsDoubleStackSlot())) {
       // Found a better source for this load.  Smash it in place to affect other
       // loads that have already been split.
-      InstructionOperand::Kind found_kind = found->destination()->kind();
-      int found_index = found->destination()->index();
       auto next_dest =
-          InstructionOperand::New(code_zone(), found_kind, found_index);
+          InstructionOperand::New(code_zone(), *found->destination());
       auto dest = move->destination();
-      found->destination()->ConvertTo(dest->kind(), dest->index());
+      InstructionOperand::ReplaceWith(found->destination(), dest);
       move->set_destination(next_dest);
     }
     // move from load destination.
index 44a82c36b621e09b23dc0d4d87391fad495e3dd3..b421f694c8c520190d0250e45e83304e4270ba7a 100644 (file)
@@ -103,7 +103,8 @@ class PPCOperandConverter FINAL : public InstructionOperandConverter {
     DCHECK(!op->IsDoubleRegister());
     DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
     // The linkage computes where all spill slots are located.
-    FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), 0);
+    FrameOffset offset = linkage()->GetFrameOffset(
+        AllocatedOperand::cast(op)->index(), frame(), 0);
     return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset());
   }
 };
index 7958ffc6ececd8dfe5d020af0fda464b4bcb33a7..912a4c7d82afcb6f3b9d7f9017ccdfe616a201db 100644 (file)
@@ -119,7 +119,7 @@ void RegisterAllocatorVerifier::BuildConstraint(const InstructionOperand* op,
   constraint->virtual_register_ = InstructionOperand::kInvalidVirtualRegister;
   if (op->IsConstant()) {
     constraint->type_ = kConstant;
-    constraint->value_ = ConstantOperand::cast(op)->index();
+    constraint->value_ = ConstantOperand::cast(op)->virtual_register();
     constraint->virtual_register_ = constraint->value_;
   } else if (op->IsImmediate()) {
     constraint->type_ = kImmediate;
@@ -180,29 +180,30 @@ void RegisterAllocatorVerifier::CheckConstraint(
   switch (constraint->type_) {
     case kConstant:
       CHECK(op->IsConstant());
-      CHECK_EQ(op->index(), constraint->value_);
+      CHECK_EQ(ConstantOperand::cast(op)->virtual_register(),
+               constraint->value_);
       return;
     case kImmediate:
       CHECK(op->IsImmediate());
-      CHECK_EQ(op->index(), constraint->value_);
+      CHECK_EQ(ImmediateOperand::cast(op)->index(), constraint->value_);
       return;
     case kRegister:
       CHECK(op->IsRegister());
       return;
     case kFixedRegister:
       CHECK(op->IsRegister());
-      CHECK_EQ(op->index(), constraint->value_);
+      CHECK_EQ(RegisterOperand::cast(op)->index(), constraint->value_);
       return;
     case kDoubleRegister:
       CHECK(op->IsDoubleRegister());
       return;
     case kFixedDoubleRegister:
       CHECK(op->IsDoubleRegister());
-      CHECK_EQ(op->index(), constraint->value_);
+      CHECK_EQ(DoubleRegisterOperand::cast(op)->index(), constraint->value_);
       return;
     case kFixedSlot:
       CHECK(op->IsStackSlot());
-      CHECK_EQ(op->index(), constraint->value_);
+      CHECK_EQ(StackSlotOperand::cast(op)->index(), constraint->value_);
       return;
     case kSlot:
       CHECK(op->IsStackSlot());
@@ -343,11 +344,11 @@ class OperandMap : public ZoneObject {
 
   void DropRegisters(const RegisterConfiguration* config) {
     for (int i = 0; i < config->num_general_registers(); ++i) {
-      InstructionOperand op(InstructionOperand::REGISTER, i);
+      RegisterOperand op(i);
       Drop(&op);
     }
     for (int i = 0; i < config->num_double_registers(); ++i) {
-      InstructionOperand op(InstructionOperand::DOUBLE_REGISTER, i);
+      DoubleRegisterOperand op(i);
       Drop(&op);
     }
   }
index a0cdec1cd71218584eeafff3b888fecaabe25711..33211c9017d2992197cd1a441308da2e9d53c063 100644 (file)
@@ -165,6 +165,7 @@ void LiveRange::SpillAtDefinition(Zone* zone, int gap_index,
 void LiveRange::CommitSpillsAtDefinition(InstructionSequence* sequence,
                                          InstructionOperand* op,
                                          bool might_be_duplicated) {
+  DCHECK_IMPLIES(op->IsConstant(), spills_at_definition_ == nullptr);
   DCHECK(!IsChild());
   auto zone = sequence->zone();
   for (auto to_spill = spills_at_definition_; to_spill != nullptr;
@@ -194,7 +195,7 @@ void LiveRange::CommitSpillsAtDefinition(InstructionSequence* sequence,
 
 void LiveRange::SetSpillOperand(InstructionOperand* operand) {
   DCHECK(HasNoSpillType());
-  DCHECK(!operand->IsUnallocated());
+  DCHECK(!operand->IsUnallocated() && !operand->IsImmediate());
   spill_type_ = SpillType::kSpillOperand;
   spill_operand_ = operand;
 }
@@ -208,9 +209,8 @@ void LiveRange::SetSpillRange(SpillRange* spill_range) {
 }
 
 
-void LiveRange::CommitSpillOperand(InstructionOperand* operand) {
+void LiveRange::CommitSpillOperand(AllocatedOperand* operand) {
   DCHECK(HasSpillRange());
-  DCHECK(!operand->IsUnallocated());
   DCHECK(!IsChild());
   spill_type_ = SpillType::kSpillOperand;
   spill_operand_ = operand;
@@ -274,9 +274,9 @@ InstructionOperand* LiveRange::GetAssignedOperand(
     DCHECK(!IsSpilled());
     switch (Kind()) {
       case GENERAL_REGISTERS:
-        return cache->RegisterOperand(assigned_register());
+        return cache->GetRegisterOperand(assigned_register());
       case DOUBLE_REGISTERS:
-        return cache->DoubleRegisterOperand(assigned_register());
+        return cache->GetDoubleRegisterOperand(assigned_register());
       default:
         UNREACHABLE();
     }
@@ -537,14 +537,14 @@ void LiveRange::ConvertUsesToOperand(InstructionOperand* op,
     switch (pos->type()) {
       case UsePositionType::kRequiresSlot:
         if (spill_op != nullptr) {
-          pos->operand()->ConvertTo(spill_op->kind(), spill_op->index());
+          InstructionOperand::ReplaceWith(pos->operand(), spill_op);
         }
         break;
       case UsePositionType::kRequiresRegister:
         DCHECK(op->IsRegister() || op->IsDoubleRegister());
       // Fall through.
       case UsePositionType::kAny:
-        pos->operand()->ConvertTo(op->kind(), op->index());
+        InstructionOperand::ReplaceWith(pos->operand(), op);
         break;
     }
   }
@@ -599,12 +599,10 @@ LifetimePosition LiveRange::FirstIntersection(LiveRange* other) {
 
 InstructionOperandCache::InstructionOperandCache() {
   for (size_t i = 0; i < arraysize(general_register_operands_); ++i) {
-    general_register_operands_[i] =
-        i::compiler::RegisterOperand(static_cast<int>(i));
+    general_register_operands_[i] = RegisterOperand(static_cast<int>(i));
   }
   for (size_t i = 0; i < arraysize(double_register_operands_); ++i) {
-    double_register_operands_[i] =
-        i::compiler::DoubleRegisterOperand(static_cast<int>(i));
+    double_register_operands_[i] = DoubleRegisterOperand(static_cast<int>(i));
   }
 }
 
@@ -707,18 +705,20 @@ InstructionOperand* RegisterAllocator::AllocateFixed(
     UnallocatedOperand* operand, int pos, bool is_tagged) {
   TRACE("Allocating fixed reg for op %d\n", operand->virtual_register());
   DCHECK(operand->HasFixedPolicy());
+  InstructionOperand allocated;
   if (operand->HasFixedSlotPolicy()) {
-    operand->ConvertTo(InstructionOperand::STACK_SLOT,
-                       operand->fixed_slot_index());
+    allocated = AllocatedOperand(InstructionOperand::STACK_SLOT,
+                                 operand->fixed_slot_index());
   } else if (operand->HasFixedRegisterPolicy()) {
-    int reg_index = operand->fixed_register_index();
-    operand->ConvertTo(InstructionOperand::REGISTER, reg_index);
+    allocated = AllocatedOperand(InstructionOperand::REGISTER,
+                                 operand->fixed_register_index());
   } else if (operand->HasFixedDoubleRegisterPolicy()) {
-    int reg_index = operand->fixed_register_index();
-    operand->ConvertTo(InstructionOperand::DOUBLE_REGISTER, reg_index);
+    allocated = AllocatedOperand(InstructionOperand::DOUBLE_REGISTER,
+                                 operand->fixed_register_index());
   } else {
     UNREACHABLE();
   }
+  InstructionOperand::ReplaceWith(operand, &allocated);
   if (is_tagged) {
     TRACE("Fixed reg is tagged at %d\n", pos);
     auto instr = InstructionAt(pos);
@@ -789,11 +789,12 @@ LiveRange* RegisterAllocator::LiveRangeFor(InstructionOperand* operand) {
   if (operand->IsUnallocated()) {
     return LiveRangeFor(UnallocatedOperand::cast(operand)->virtual_register());
   } else if (operand->IsConstant()) {
-    return LiveRangeFor(ConstantOperand::cast(operand)->index());
+    return LiveRangeFor(ConstantOperand::cast(operand)->virtual_register());
   } else if (operand->IsRegister()) {
-    return FixedLiveRangeFor(operand->index());
+    return FixedLiveRangeFor(RegisterOperand::cast(operand)->index());
   } else if (operand->IsDoubleRegister()) {
-    return FixedDoubleLiveRangeFor(operand->index());
+    return FixedDoubleLiveRangeFor(
+        DoubleRegisterOperand::cast(operand)->index());
   } else {
     return nullptr;
   }
@@ -922,7 +923,7 @@ bool SpillRange::TryMerge(SpillRange* other) {
 }
 
 
-void SpillRange::SetOperand(InstructionOperand* op) {
+void SpillRange::SetOperand(AllocatedOperand* op) {
   for (auto range : live_ranges()) {
     DCHECK(range->GetSpillRange() == this);
     range->CommitSpillOperand(op);
@@ -977,7 +978,7 @@ void RegisterAllocator::AssignSpillSlots() {
     auto op_kind = kind == DOUBLE_REGISTERS
                        ? InstructionOperand::DOUBLE_STACK_SLOT
                        : InstructionOperand::STACK_SLOT;
-    auto op = InstructionOperand::New(code_zone(), op_kind, index);
+    auto op = AllocatedOperand::New(code_zone(), op_kind, index);
     range->SetOperand(op);
   }
 }
@@ -1117,8 +1118,9 @@ void RegisterAllocator::MeetRegisterConstraintsForLastInstructionInBlock(
       AllocateFixed(output, -1, false);
       // This value is produced on the stack, we never need to spill it.
       if (output->IsStackSlot()) {
-        DCHECK(output->index() < frame_->GetSpillSlotCount());
-        range->SetSpillOperand(output);
+        DCHECK(StackSlotOperand::cast(output)->index() <
+               frame_->GetSpillSlotCount());
+        range->SetSpillOperand(StackSlotOperand::cast(output));
         range->SetSpillStartIndex(end);
         assigned = true;
       }
@@ -1160,7 +1162,7 @@ void RegisterAllocator::MeetConstraintsAfter(int instr_index) {
   for (size_t i = 0; i < first->OutputCount(); i++) {
     InstructionOperand* output = first->OutputAt(i);
     if (output->IsConstant()) {
-      int output_vreg = output->index();
+      int output_vreg = ConstantOperand::cast(output)->virtual_register();
       auto range = LiveRangeFor(output_vreg);
       range->SetSpillStartIndex(instr_index + 1);
       range->SetSpillOperand(output);
@@ -1176,8 +1178,9 @@ void RegisterAllocator::MeetConstraintsAfter(int instr_index) {
 
       // This value is produced on the stack, we never need to spill it.
       if (first_output->IsStackSlot()) {
-        DCHECK(first_output->index() < frame_->GetSpillSlotCount());
-        range->SetSpillOperand(first_output);
+        DCHECK(StackSlotOperand::cast(first_output)->index() <
+               frame_->GetSpillSlotCount());
+        range->SetSpillOperand(StackSlotOperand::cast(first_output));
         range->SetSpillStartIndex(instr_index + 1);
         assigned = true;
       }
@@ -1241,7 +1244,8 @@ void RegisterAllocator::MeetConstraintsBefore(int instr_index) {
 bool RegisterAllocator::IsOutputRegisterOf(Instruction* instr, int index) {
   for (size_t i = 0; i < instr->OutputCount(); i++) {
     auto output = instr->OutputAt(i);
-    if (output->IsRegister() && output->index() == index) return true;
+    if (output->IsRegister() && RegisterOperand::cast(output)->index() == index)
+      return true;
   }
   return false;
 }
@@ -1251,7 +1255,9 @@ bool RegisterAllocator::IsOutputDoubleRegisterOf(Instruction* instr,
                                                  int index) {
   for (size_t i = 0; i < instr->OutputCount(); i++) {
     auto output = instr->OutputAt(i);
-    if (output->IsDoubleRegister() && output->index() == index) return true;
+    if (output->IsDoubleRegister() &&
+        DoubleRegisterOperand::cast(output)->index() == index)
+      return true;
   }
   return false;
 }
@@ -1279,7 +1285,7 @@ void RegisterAllocator::ProcessInstructions(const InstructionBlock* block,
         int out_vreg = UnallocatedOperand::cast(output)->virtual_register();
         live->Remove(out_vreg);
       } else if (output->IsConstant()) {
-        int out_vreg = output->index();
+        int out_vreg = ConstantOperand::cast(output)->virtual_register();
         live->Remove(out_vreg);
       }
       Define(curr_position, output, nullptr);
@@ -1367,7 +1373,6 @@ void RegisterAllocator::ProcessInstructions(const InstructionBlock* block,
           int to_vreg = UnallocatedOperand::cast(to)->virtual_register();
           auto to_range = LiveRangeFor(to_vreg);
           if (to_range->is_phi()) {
-            DCHECK(!FLAG_turbo_delay_ssa_decon);
             if (to_range->is_non_loop_phi()) {
               hint = to_range->current_hint_operand();
             }
@@ -1401,15 +1406,13 @@ void RegisterAllocator::ResolvePhis(const InstructionBlock* block) {
     DCHECK(res.second);
     USE(res);
     auto& output = phi->output();
-    if (!FLAG_turbo_delay_ssa_decon) {
-      for (size_t i = 0; i < phi->operands().size(); ++i) {
-        InstructionBlock* cur_block =
-            code()->InstructionBlockAt(block->predecessors()[i]);
-        AddGapMove(cur_block->last_instruction_index(), Instruction::END,
-                   &phi->inputs()[i], &output);
-        DCHECK(!InstructionAt(cur_block->last_instruction_index())
-                    ->HasPointerMap());
-      }
+    for (size_t i = 0; i < phi->operands().size(); ++i) {
+      InstructionBlock* cur_block =
+          code()->InstructionBlockAt(block->predecessors()[i]);
+      AddGapMove(cur_block->last_instruction_index(), Instruction::END,
+                 &phi->inputs()[i], &output);
+      DCHECK(
+          !InstructionAt(cur_block->last_instruction_index())->HasPointerMap());
     }
     auto live_range = LiveRangeFor(phi_vreg);
     int gap_index = block->first_instruction_index();
@@ -1664,27 +1667,6 @@ void RegisterAllocator::ResolveControlFlow() {
   LiveRangeFinder finder(*this);
   for (auto block : code()->instruction_blocks()) {
     if (CanEagerlyResolveControlFlow(block)) continue;
-    if (FLAG_turbo_delay_ssa_decon) {
-      // resolve phis
-      for (auto phi : block->phis()) {
-        auto* block_bound =
-            finder.ArrayFor(phi->virtual_register())->FindSucc(block);
-        auto phi_output =
-            block_bound->range_->GetAssignedOperand(operand_cache());
-        phi->output().ConvertTo(phi_output->kind(), phi_output->index());
-        size_t pred_index = 0;
-        for (auto pred : block->predecessors()) {
-          const InstructionBlock* pred_block = code()->InstructionBlockAt(pred);
-          auto* pred_bound = finder.ArrayFor(phi->operands()[pred_index])
-                                 ->FindPred(pred_block);
-          auto pred_op =
-              pred_bound->range_->GetAssignedOperand(operand_cache());
-          phi->inputs()[pred_index] = *pred_op;
-          ResolveControlFlow(block, phi_output, pred_block, pred_op);
-          pred_index++;
-        }
-      }
-    }
     auto live = live_in_sets_[block->rpo_number().ToInt()];
     BitVector::Iterator iterator(live);
     while (!iterator.Done()) {
@@ -1745,26 +1727,24 @@ void RegisterAllocator::BuildLiveRanges() {
       // block.
       int phi_vreg = phi->virtual_register();
       live->Remove(phi_vreg);
-      if (!FLAG_turbo_delay_ssa_decon) {
-        InstructionOperand* hint = nullptr;
-        InstructionOperand* phi_operand = nullptr;
-        auto instr = GetLastInstruction(
-            code()->InstructionBlockAt(block->predecessors()[0]));
-        auto move = instr->GetParallelMove(Instruction::END);
-        for (int j = 0; j < move->move_operands()->length(); ++j) {
-          auto to = move->move_operands()->at(j).destination();
-          if (to->IsUnallocated() &&
-              UnallocatedOperand::cast(to)->virtual_register() == phi_vreg) {
-            hint = move->move_operands()->at(j).source();
-            phi_operand = to;
-            break;
-          }
+      InstructionOperand* hint = nullptr;
+      InstructionOperand* phi_operand = nullptr;
+      auto instr = GetLastInstruction(
+          code()->InstructionBlockAt(block->predecessors()[0]));
+      auto move = instr->GetParallelMove(Instruction::END);
+      for (int j = 0; j < move->move_operands()->length(); ++j) {
+        auto to = move->move_operands()->at(j).destination();
+        if (to->IsUnallocated() &&
+            UnallocatedOperand::cast(to)->virtual_register() == phi_vreg) {
+          hint = move->move_operands()->at(j).source();
+          phi_operand = to;
+          break;
         }
-        DCHECK(hint != nullptr);
-        auto block_start = LifetimePosition::GapFromInstructionIndex(
-            block->first_instruction_index());
-        Define(block_start, phi_operand, hint);
       }
+      DCHECK(hint != nullptr);
+      auto block_start = LifetimePosition::GapFromInstructionIndex(
+          block->first_instruction_index());
+      Define(block_start, phi_operand, hint);
     }
 
     // Now live is live_in for this block except not including values live
@@ -2184,7 +2164,7 @@ bool RegisterAllocator::TryAllocateFreeReg(LiveRange* current) {
 
   auto hint = current->FirstHint();
   if (hint != nullptr && (hint->IsRegister() || hint->IsDoubleRegister())) {
-    int register_index = hint->index();
+    int register_index = AllocatedOperand::cast(hint)->index();
     TRACE("Found reg hint %s (free until [%d) for live range %d (end %d[).\n",
           RegisterName(register_index), free_until_pos[register_index].Value(),
           current->id(), current->End().Value());
index d5bd0e7dc8caa3e59294124044ea4bc47c01785d..5160b89aa582c67ce82dde8b4208dda085e3952c 100644 (file)
@@ -215,15 +215,15 @@ class InstructionOperandCache FINAL : public ZoneObject {
  public:
   InstructionOperandCache();
 
-  InstructionOperand* RegisterOperand(int index) {
+  RegisterOperand* GetRegisterOperand(int index) {
     DCHECK(index >= 0 &&
            index < static_cast<int>(arraysize(general_register_operands_)));
-    return &general_register_operands_[index];
+    return RegisterOperand::cast(&general_register_operands_[index]);
   }
-  InstructionOperand* DoubleRegisterOperand(int index) {
+  DoubleRegisterOperand* GetDoubleRegisterOperand(int index) {
     DCHECK(index >= 0 &&
            index < static_cast<int>(arraysize(double_register_operands_)));
-    return &double_register_operands_[index];
+    return DoubleRegisterOperand::cast(&double_register_operands_[index]);
   }
 
  private:
@@ -345,7 +345,7 @@ class LiveRange FINAL : public ZoneObject {
                          InstructionOperand* operand);
   void SetSpillOperand(InstructionOperand* operand);
   void SetSpillRange(SpillRange* spill_range);
-  void CommitSpillOperand(InstructionOperand* operand);
+  void CommitSpillOperand(AllocatedOperand* operand);
   void CommitSpillsAtDefinition(InstructionSequence* sequence,
                                 InstructionOperand* operand,
                                 bool might_be_duplicated);
@@ -423,7 +423,7 @@ class SpillRange FINAL : public ZoneObject {
   RegisterKind Kind() const { return live_ranges_[0]->Kind(); }
   bool IsEmpty() const { return live_ranges_.empty(); }
   bool TryMerge(SpillRange* other);
-  void SetOperand(InstructionOperand* op);
+  void SetOperand(AllocatedOperand* op);
 
  private:
   LifetimePosition End() const { return end_position_; }
index b684ab3ad1bd5159c9b8ad197b3bad4d66895fff..6377f5cae5a0e040a45d8654bfe25527e7022b22 100644 (file)
@@ -44,7 +44,8 @@ class X64OperandConverter : public InstructionOperandConverter {
   Operand ToOperand(InstructionOperand* op, int extra = 0) {
     DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
     // The linkage computes where all spill slots are located.
-    FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), extra);
+    FrameOffset offset = linkage()->GetFrameOffset(
+        AllocatedOperand::cast(op)->index(), frame(), extra);
     return Operand(offset.from_stack_pointer() ? rsp : rbp, offset.offset());
   }
 
index a2e53085008350c3696805155253a58e642b9a85..da95b1e52425dbf4e36b3217afb7b592362ebbb0 100644 (file)
@@ -409,9 +409,6 @@ DEFINE_BOOL(turbo_builtin_inlining, true, "enable builtin inlining in TurboFan")
 DEFINE_BOOL(trace_turbo_inlining, false, "trace TurboFan inlining")
 DEFINE_BOOL(loop_assignment_analysis, true, "perform loop assignment analysis")
 DEFINE_BOOL(turbo_profiling, false, "enable profiling in TurboFan")
-// TODO(dcarney): this is just for experimentation, remove when default.
-DEFINE_BOOL(turbo_delay_ssa_decon, false,
-            "delay ssa deconstruction in TurboFan register allocator")
 DEFINE_BOOL(turbo_verify_allocation, DEBUG_BOOL,
             "verify register allocation in TurboFan")
 DEFINE_BOOL(turbo_move_optimization, true, "optimize gap moves in TurboFan")
index 818a0bd23873a938547a98975f223e0dd8e643fc..a7664e06484a8592a1423fff88e139d92f797657 100644 (file)
@@ -51,11 +51,22 @@ class InterpreterState {
   }
 
   static Key KeyFor(const InstructionOperand* op) {
-    return Key(op->kind(), op->index());
+    int v = op->IsConstant() ? ConstantOperand::cast(op)->virtual_register()
+                             : AllocatedOperand::cast(op)->index();
+    return Key(op->kind(), v);
   }
 
   static Value ValueFor(const InstructionOperand* op) {
-    return Value(op->kind(), op->index());
+    int v = op->IsConstant() ? ConstantOperand::cast(op)->virtual_register()
+                             : AllocatedOperand::cast(op)->index();
+    return Value(op->kind(), v);
+  }
+
+  static InstructionOperand FromKey(Key key) {
+    if (key.first == InstructionOperand::CONSTANT) {
+      return ConstantOperand(key.second);
+    }
+    return AllocatedOperand(key.first, key.second);
   }
 
   friend std::ostream& operator<<(std::ostream& os,
@@ -63,8 +74,8 @@ class InterpreterState {
     for (OperandMap::const_iterator it = is.values_.begin();
          it != is.values_.end(); ++it) {
       if (it != is.values_.begin()) os << " ";
-      InstructionOperand source(it->first.first, it->first.second);
-      InstructionOperand destination(it->second.first, it->second.second);
+      InstructionOperand source = FromKey(it->first);
+      InstructionOperand destination = FromKey(it->second);
       MoveOperands mo(&source, &destination);
       PrintableMoveOperands pmo = {RegisterConfiguration::ArchDefault(), &mo};
       os << pmo;
@@ -115,7 +126,7 @@ class ParallelMoveCreator : public HandleAndZoneScope {
     ParallelMove* parallel_move = new (main_zone()) ParallelMove(main_zone());
     std::set<InstructionOperand*, InstructionOperandComparator> seen;
     for (int i = 0; i < size; ++i) {
-      MoveOperands mo(CreateRandomOperand(), CreateRandomOperand());
+      MoveOperands mo(CreateRandomOperand(true), CreateRandomOperand(false));
       if (!mo.IsRedundant() && seen.find(mo.destination()) == seen.end()) {
         parallel_move->AddMove(mo.source(), mo.destination(), main_zone());
         seen.insert(mo.destination());
@@ -128,24 +139,24 @@ class ParallelMoveCreator : public HandleAndZoneScope {
   struct InstructionOperandComparator {
     bool operator()(const InstructionOperand* x,
                     const InstructionOperand* y) const {
-      return (x->kind() < y->kind()) ||
-             (x->kind() == y->kind() && x->index() < y->index());
+      return *x < *y;
     }
   };
 
-  InstructionOperand* CreateRandomOperand() {
+  InstructionOperand* CreateRandomOperand(bool is_source) {
     int index = rng_->NextInt(6);
-    switch (rng_->NextInt(5)) {
+    // destination can't be Constant.
+    switch (rng_->NextInt(is_source ? 5 : 4)) {
       case 0:
-        return ConstantOperand::New(index, main_zone());
+        return StackSlotOperand::New(main_zone(), index);
       case 1:
-        return StackSlotOperand::New(index, main_zone());
+        return DoubleStackSlotOperand::New(main_zone(), index);
       case 2:
-        return DoubleStackSlotOperand::New(index, main_zone());
+        return RegisterOperand::New(main_zone(), index);
       case 3:
-        return RegisterOperand::New(index, main_zone());
+        return DoubleRegisterOperand::New(main_zone(), index);
       case 4:
-        return DoubleRegisterOperand::New(index, main_zone());
+        return ConstantOperand::New(main_zone(), index);
     }
     UNREACHABLE();
     return NULL;
index 300da3338efe8a08cc544b1cbc82f5e3f10815ef..1dc31bd94ddffe79117e5f374a5ddc0af7438e11 100644 (file)
@@ -59,15 +59,15 @@ class TestCode : public HandleAndZoneScope {
     Start();
     sequence_.AddInstruction(Instruction::New(main_zone(), kArchNop));
     int index = static_cast<int>(sequence_.instructions().size()) - 1;
-    AddGapMove(index, RegisterOperand::New(13, main_zone()),
-               RegisterOperand::New(13, main_zone()));
+    AddGapMove(index, RegisterOperand::New(main_zone(), 13),
+               RegisterOperand::New(main_zone(), 13));
   }
   void NonRedundantMoves() {
     Start();
     sequence_.AddInstruction(Instruction::New(main_zone(), kArchNop));
     int index = static_cast<int>(sequence_.instructions().size()) - 1;
-    AddGapMove(index, ImmediateOperand::New(11, main_zone()),
-               RegisterOperand::New(11, main_zone()));
+    AddGapMove(index, ImmediateOperand::New(main_zone(), 11),
+               RegisterOperand::New(main_zone(), 11));
   }
   void Other() {
     Start();
index e52580dc649b4f08022e1f2d3b2e7b9178736caf..58946e96d056619e31d5e4bc86ce5a22204bba04 100644 (file)
@@ -76,16 +76,17 @@ InstructionSelectorTest::Stream InstructionSelectorTest::StreamBuilder::Build(
       InstructionOperand* output = instr->OutputAt(i);
       EXPECT_NE(InstructionOperand::IMMEDIATE, output->kind());
       if (output->IsConstant()) {
-        s.constants_.insert(std::make_pair(
-            output->index(), sequence.GetConstant(output->index())));
+        int vreg = ConstantOperand::cast(output)->virtual_register();
+        s.constants_.insert(std::make_pair(vreg, sequence.GetConstant(vreg)));
       }
     }
     for (size_t i = 0; i < instr->InputCount(); ++i) {
       InstructionOperand* input = instr->InputAt(i);
       EXPECT_NE(InstructionOperand::CONSTANT, input->kind());
       if (input->IsImmediate()) {
-        s.immediates_.insert(std::make_pair(
-            input->index(), sequence.GetImmediate(input->index())));
+        int index = ImmediateOperand::cast(input)->index();
+        s.immediates_.insert(
+            std::make_pair(index, sequence.GetImmediate(index)));
       }
     }
     s.instructions_.push_back(instr);
index 983e5c0aed3b40c31790734f810c6107ae15761e..2be283fd691f940a571e594e4903e68a7e88022a 100644 (file)
@@ -166,7 +166,9 @@ class InstructionSelectorTest : public TestWithContext,
     }
 
     int ToVreg(const InstructionOperand* operand) const {
-      if (operand->IsConstant()) return operand->index();
+      if (operand->IsConstant()) {
+        return ConstantOperand::cast(operand)->virtual_register();
+      }
       EXPECT_EQ(InstructionOperand::UNALLOCATED, operand->kind());
       return UnallocatedOperand::cast(operand)->virtual_register();
     }
@@ -202,14 +204,15 @@ class InstructionSelectorTest : public TestWithContext,
     Constant ToConstant(const InstructionOperand* operand) const {
       ConstantMap::const_iterator i;
       if (operand->IsConstant()) {
-        i = constants_.find(operand->index());
+        i = constants_.find(ConstantOperand::cast(operand)->virtual_register());
+        EXPECT_EQ(ConstantOperand::cast(operand)->virtual_register(), i->first);
         EXPECT_FALSE(constants_.end() == i);
       } else {
         EXPECT_EQ(InstructionOperand::IMMEDIATE, operand->kind());
-        i = immediates_.find(operand->index());
+        i = immediates_.find(ImmediateOperand::cast(operand)->index());
+        EXPECT_EQ(ImmediateOperand::cast(operand)->index(), i->first);
         EXPECT_FALSE(immediates_.end() == i);
       }
-      EXPECT_EQ(operand->index(), i->first);
       return i->second;
     }
 
index 26afc7837bc4886a57ea09c25fea97691355e70e..206f10891d1ce69e159683cc16214e2d4deecb37 100644 (file)
@@ -67,12 +67,12 @@ class MoveOptimizerTest : public InstructionSequenceTest {
     CHECK_NE(kNoValue, op.value_);
     switch (op.type_) {
       case kConstant:
-        return ConstantOperand::New(op.value_, zone());
+        return ConstantOperand::New(zone(), op.value_);
       case kFixedSlot:
-        return StackSlotOperand::New(op.value_, zone());
+        return StackSlotOperand::New(zone(), op.value_);
       case kFixedRegister:
         CHECK(0 <= op.value_ && op.value_ < num_general_registers());
-        return RegisterOperand::New(op.value_, zone());
+        return RegisterOperand::New(zone(), op.value_);
       default:
         break;
     }