[turbofan] Make AllocatedOperand an InstructionOperand::Kind.
authordcarney <dcarney@chromium.org>
Thu, 9 Apr 2015 10:40:41 +0000 (03:40 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 9 Apr 2015 10:40:43 +0000 (10:40 +0000)
This is preparatory work to have MachineTypes encoded in AllocatedOperands.

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

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

src/compiler/instruction.cc
src/compiler/instruction.h
src/compiler/register-allocator.cc
test/cctest/compiler/test-gap-resolver.cc

index 177de6f..62bd5b7 100644 (file)
@@ -46,19 +46,22 @@ std::ostream& operator<<(std::ostream& os,
                 << "]";
     case InstructionOperand::IMMEDIATE:
       return os << "[immediate:" << ImmediateOperand::cast(op).index() << "]";
-    case InstructionOperand::STACK_SLOT:
-      return os << "[stack:" << StackSlotOperand::cast(op).index() << "]";
-    case InstructionOperand::DOUBLE_STACK_SLOT:
-      return os << "[double_stack:" << DoubleStackSlotOperand::cast(op).index()
-                << "]";
-    case InstructionOperand::REGISTER:
-      return os << "["
-                << conf->general_register_name(
-                       RegisterOperand::cast(op).index()) << "|R]";
-    case InstructionOperand::DOUBLE_REGISTER:
-      return os << "["
-                << conf->double_register_name(
-                       DoubleRegisterOperand::cast(op).index()) << "|R]";
+    case InstructionOperand::ALLOCATED:
+      switch (AllocatedOperand::cast(op).allocated_kind()) {
+        case AllocatedOperand::STACK_SLOT:
+          return os << "[stack:" << StackSlotOperand::cast(op).index() << "]";
+        case AllocatedOperand::DOUBLE_STACK_SLOT:
+          return os << "[double_stack:"
+                    << DoubleStackSlotOperand::cast(op).index() << "]";
+        case AllocatedOperand::REGISTER:
+          return os << "["
+                    << conf->general_register_name(
+                           RegisterOperand::cast(op).index()) << "|R]";
+        case AllocatedOperand::DOUBLE_REGISTER:
+          return os << "["
+                    << conf->double_register_name(
+                           DoubleRegisterOperand::cast(op).index()) << "|R]";
+      }
     case InstructionOperand::INVALID:
       return os << "(x)";
   }
index 3615e37..4d6538c 100644 (file)
@@ -27,26 +27,13 @@ class Schedule;
 // A couple of reserved opcodes are used for internal use.
 const InstructionCode kSourcePositionInstruction = -1;
 
-#define ALLOCATED_OPERAND_LIST(V)       \
-  V(StackSlot, STACK_SLOT)              \
-  V(DoubleStackSlot, DOUBLE_STACK_SLOT) \
-  V(Register, REGISTER)                 \
-  V(DoubleRegister, DOUBLE_REGISTER)
-
 class InstructionOperand {
  public:
   static const int kInvalidVirtualRegister = -1;
 
-  enum Kind {
-    INVALID,
-    UNALLOCATED,
-    CONSTANT,
-    IMMEDIATE,
-    STACK_SLOT,
-    DOUBLE_STACK_SLOT,
-    REGISTER,
-    DOUBLE_REGISTER
-  };
+  // TODO(dcarney): recover bit. INVALID can be represented as UNALLOCATED with
+  // kInvalidVirtualRegister and some DCHECKS.
+  enum Kind { INVALID, UNALLOCATED, CONSTANT, IMMEDIATE, ALLOCATED };
 
   InstructionOperand()
       : InstructionOperand(INVALID, 0, kInvalidVirtualRegister) {}
@@ -55,13 +42,18 @@ class InstructionOperand {
 
 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \
   bool Is##name() const { return kind() == type; }
-  ALLOCATED_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE)
+  INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID)
+  INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED)
   INSTRUCTION_OPERAND_PREDICATE(Constant, CONSTANT)
   INSTRUCTION_OPERAND_PREDICATE(Immediate, IMMEDIATE)
-  INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED)
-  INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID)
+  INSTRUCTION_OPERAND_PREDICATE(Allocated, ALLOCATED)
 #undef INSTRUCTION_OPERAND_PREDICATE
 
+  inline bool IsRegister() const;
+  inline bool IsDoubleRegister() const;
+  inline bool IsStackSlot() const;
+  inline bool IsDoubleStackSlot() const;
+
   bool Equals(const InstructionOperand* other) const {
     return value_ == other->value_;
   }
@@ -84,7 +76,6 @@ class InstructionOperand {
 
  protected:
   InstructionOperand(Kind kind, int index, int virtual_register) {
-    if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0);
     if (kind != UNALLOCATED && kind != CONSTANT) {
       DCHECK(virtual_register == kInvalidVirtualRegister);
     }
@@ -109,6 +100,23 @@ struct PrintableInstructionOperand {
 std::ostream& operator<<(std::ostream& os,
                          const PrintableInstructionOperand& op);
 
+#define INSTRUCTION_OPERAND_CASTS(OperandType, OperandKind)      \
+                                                                 \
+  static OperandType* cast(InstructionOperand* op) {             \
+    DCHECK_EQ(OperandKind, op->kind());                          \
+    return static_cast<OperandType*>(op);                        \
+  }                                                              \
+                                                                 \
+  static const OperandType* cast(const InstructionOperand* op) { \
+    DCHECK_EQ(OperandKind, op->kind());                          \
+    return static_cast<const OperandType*>(op);                  \
+  }                                                              \
+                                                                 \
+  static OperandType cast(const InstructionOperand& op) {        \
+    DCHECK_EQ(OperandKind, op.kind());                           \
+    return *static_cast<const OperandType*>(&op);                \
+  }
+
 class UnallocatedOperand : public InstructionOperand {
  public:
   enum BasicPolicy { FIXED_SLOT, EXTENDED_POLICY };
@@ -175,21 +183,6 @@ class UnallocatedOperand : public InstructionOperand {
     return New(zone, UnallocatedOperand(ANY, virtual_register()));
   }
 
-  static const UnallocatedOperand* cast(const InstructionOperand* op) {
-    DCHECK(op->IsUnallocated());
-    return static_cast<const UnallocatedOperand*>(op);
-  }
-
-  static UnallocatedOperand* cast(InstructionOperand* op) {
-    DCHECK(op->IsUnallocated());
-    return static_cast<UnallocatedOperand*>(op);
-  }
-
-  static UnallocatedOperand cast(const InstructionOperand& op) {
-    DCHECK(op.IsUnallocated());
-    return *static_cast<const UnallocatedOperand*>(&op);
-  }
-
   // The encoding used for UnallocatedOperand operands depends on the policy
   // that is
   // stored within the operand. The FIXED_SLOT policy uses a compact encoding
@@ -297,6 +290,8 @@ class UnallocatedOperand : public InstructionOperand {
     DCHECK(basic_policy() == EXTENDED_POLICY);
     return LifetimeField::decode(value_) == USED_AT_START;
   }
+
+  INSTRUCTION_OPERAND_CASTS(UnallocatedOperand, UNALLOCATED);
 };
 
 
@@ -313,20 +308,7 @@ class ConstantOperand : public InstructionOperand {
     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);
-  }
+  INSTRUCTION_OPERAND_CASTS(ConstantOperand, CONSTANT);
 };
 
 
@@ -343,93 +325,91 @@ class ImmediateOperand : public InstructionOperand {
     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);
-  }
+  INSTRUCTION_OPERAND_CASTS(ImmediateOperand, IMMEDIATE);
 };
 
 
 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:
+  enum AllocatedKind {
+    STACK_SLOT,
+    DOUBLE_STACK_SLOT,
+    REGISTER,
+    DOUBLE_REGISTER
+  };
+
+  AllocatedOperand(AllocatedKind kind, int index)
+      : InstructionOperand(ALLOCATED, index, kInvalidVirtualRegister) {
+    if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0);
+    value_ = AllocatedKindField::update(value_, kind);
+  }
+
   int index() const {
     return static_cast<int64_t>(value_) >> IndexField::kShift;
   }
 
-  AllocatedOperand(Kind kind, int index)
-      : InstructionOperand(kind, index, kInvalidVirtualRegister) {
-    CHECK_ALLOCATED_KIND();
+  AllocatedKind allocated_kind() const {
+    return AllocatedKindField::decode(value_);
   }
 
-  static AllocatedOperand* New(Zone* zone, Kind kind, int index) {
+  static AllocatedOperand* New(Zone* zone, AllocatedKind 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);
-  }
+  INSTRUCTION_OPERAND_CASTS(AllocatedOperand, ALLOCATED);
 
-  static const AllocatedOperand* cast(const InstructionOperand* op) {
-    Kind kind = op->kind();
-    CHECK_ALLOCATED_KIND();
-    return static_cast<const AllocatedOperand*>(op);
-  }
+ private:
+  typedef BitField64<AllocatedKind, 3, 2> AllocatedKindField;
+};
 
-  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
-};
+#undef INSTRUCTION_OPERAND_CASTS
+
+
+#define ALLOCATED_OPERAND_LIST(V)       \
+  V(StackSlot, STACK_SLOT)              \
+  V(DoubleStackSlot, DOUBLE_STACK_SLOT) \
+  V(Register, REGISTER)                 \
+  V(DoubleRegister, DOUBLE_REGISTER)
 
 
-#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);                \
-    }                                                                   \
+#define ALLOCATED_OPERAND_IS(SubKind, kOperandKind)          \
+  bool InstructionOperand::Is##SubKind() const {             \
+    return IsAllocated() &&                                  \
+           AllocatedOperand::cast(this)->allocated_kind() == \
+               AllocatedOperand::kOperandKind;               \
+  }
+ALLOCATED_OPERAND_LIST(ALLOCATED_OPERAND_IS)
+#undef ALLOCATED_OPERAND_IS
+
+
+#define ALLOCATED_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_EQ(kOperandKind, AllocatedOperand::cast(op)->allocated_kind()); \
+      return reinterpret_cast<SubKind##Operand*>(op);                        \
+    }                                                                        \
+                                                                             \
+    static const SubKind##Operand* cast(const InstructionOperand* op) {      \
+      DCHECK_EQ(kOperandKind, AllocatedOperand::cast(op)->allocated_kind()); \
+      return reinterpret_cast<const SubKind##Operand*>(op);                  \
+    }                                                                        \
+                                                                             \
+    static SubKind##Operand cast(const InstructionOperand& op) {             \
+      DCHECK_EQ(kOperandKind, AllocatedOperand::cast(op).allocated_kind());  \
+      return *static_cast<const SubKind##Operand*>(&op);                     \
+    }                                                                        \
   };
-ALLOCATED_OPERAND_LIST(INSTRUCTION_SUBKIND_OPERAND_CLASS)
-#undef INSTRUCTION_SUBKIND_OPERAND_CLASS
+ALLOCATED_OPERAND_LIST(ALLOCATED_OPERAND_CLASS)
+#undef ALLOCATED_OPERAND_CLASS
 
 
 class MoveOperands FINAL {
index 33211c9..f3875f7 100644 (file)
@@ -707,13 +707,13 @@ InstructionOperand* RegisterAllocator::AllocateFixed(
   DCHECK(operand->HasFixedPolicy());
   InstructionOperand allocated;
   if (operand->HasFixedSlotPolicy()) {
-    allocated = AllocatedOperand(InstructionOperand::STACK_SLOT,
+    allocated = AllocatedOperand(AllocatedOperand::STACK_SLOT,
                                  operand->fixed_slot_index());
   } else if (operand->HasFixedRegisterPolicy()) {
-    allocated = AllocatedOperand(InstructionOperand::REGISTER,
+    allocated = AllocatedOperand(AllocatedOperand::REGISTER,
                                  operand->fixed_register_index());
   } else if (operand->HasFixedDoubleRegisterPolicy()) {
-    allocated = AllocatedOperand(InstructionOperand::DOUBLE_REGISTER,
+    allocated = AllocatedOperand(AllocatedOperand::DOUBLE_REGISTER,
                                  operand->fixed_register_index());
   } else {
     UNREACHABLE();
@@ -976,8 +976,8 @@ void RegisterAllocator::AssignSpillSlots() {
     auto kind = range->Kind();
     int index = frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS);
     auto op_kind = kind == DOUBLE_REGISTERS
-                       ? InstructionOperand::DOUBLE_STACK_SLOT
-                       : InstructionOperand::STACK_SLOT;
+                       ? AllocatedOperand::DOUBLE_STACK_SLOT
+                       : AllocatedOperand::STACK_SLOT;
     auto op = AllocatedOperand::New(code_zone(), op_kind, index);
     range->SetOperand(op);
   }
index a7664e0..caf9a62 100644 (file)
@@ -32,8 +32,28 @@ class InterpreterState {
   }
 
  private:
+  struct Key {
+    bool is_constant;
+    AllocatedOperand::AllocatedKind kind;
+    int index;
+
+    bool operator<(const Key& other) const {
+      if (this->is_constant != other.is_constant) {
+        return this->is_constant;
+      }
+      if (this->kind != other.kind) {
+        return this->kind < other.kind;
+      }
+      return this->index < other.index;
+    }
+
+    bool operator==(const Key& other) const {
+      return this->is_constant == other.is_constant &&
+             this->kind == other.kind && this->index == other.index;
+    }
+  };
+
   // Internally, the state is a normalized permutation of (kind,index) pairs.
-  typedef std::pair<InstructionOperand::Kind, int> Key;
   typedef Key Value;
   typedef std::map<Key, Value> OperandMap;
 
@@ -51,22 +71,27 @@ class InterpreterState {
   }
 
   static Key KeyFor(const InstructionOperand* op) {
-    int v = op->IsConstant() ? ConstantOperand::cast(op)->virtual_register()
-                             : AllocatedOperand::cast(op)->index();
-    return Key(op->kind(), v);
+    bool is_constant = op->IsConstant();
+    AllocatedOperand::AllocatedKind kind;
+    int index;
+    if (!is_constant) {
+      index = AllocatedOperand::cast(op)->index();
+      kind = AllocatedOperand::cast(op)->allocated_kind();
+    } else {
+      index = ConstantOperand::cast(op)->virtual_register();
+      kind = AllocatedOperand::REGISTER;
+    }
+    Key key = {is_constant, kind, index};
+    return key;
   }
 
-  static Value ValueFor(const InstructionOperand* op) {
-    int v = op->IsConstant() ? ConstantOperand::cast(op)->virtual_register()
-                             : AllocatedOperand::cast(op)->index();
-    return Value(op->kind(), v);
-  }
+  static Value ValueFor(const InstructionOperand* op) { return KeyFor(op); }
 
   static InstructionOperand FromKey(Key key) {
-    if (key.first == InstructionOperand::CONSTANT) {
-      return ConstantOperand(key.second);
+    if (key.is_constant) {
+      return ConstantOperand(key.index);
     }
-    return AllocatedOperand(key.first, key.second);
+    return AllocatedOperand(key.kind, key.index);
   }
 
   friend std::ostream& operator<<(std::ostream& os,