Store HIR type in HInstruction::packed_field_.

This is similar to
    https://android-review.googlesource.com/609566
though the performance impact has not been measured.
However, avoiding a virtual call reduces pressure on the
branch predictor and provides better optimization
opportunities for the C++ compiler.

As there is now no difference between HTemplateInstruction<>
and HExpression<> (the type is stored in HInstruction), we
remove the former and use HExpression<> for all instructions
that have a fixed number of inputs.

Test: Rely on TreeHugger.
Change-Id: Ib3fd111048b0ac38ee65386a7e5af70c5ccc98de
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 79d7330..295f570 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -1965,6 +1965,9 @@
 #undef DECLARE_KIND
 
   HInstruction(InstructionKind kind, SideEffects side_effects, uint32_t dex_pc)
+      : HInstruction(kind, DataType::Type::kVoid, side_effects, dex_pc) {}
+
+  HInstruction(InstructionKind kind, DataType::Type type, SideEffects side_effects, uint32_t dex_pc)
       : previous_(nullptr),
         next_(nullptr),
         block_(nullptr),
@@ -1979,6 +1982,7 @@
         side_effects_(side_effects),
         reference_type_handle_(ReferenceTypeInfo::CreateInvalid().GetTypeHandle()) {
     SetPackedField<InstructionKindField>(kind);
+    SetPackedField<TypeField>(type);
     SetPackedFlag<kFlagReferenceTypeIsExact>(ReferenceTypeInfo::CreateInvalid().IsExact());
   }
 
@@ -2036,7 +2040,9 @@
   virtual void Accept(HGraphVisitor* visitor) = 0;
   virtual const char* DebugName() const = 0;
 
-  virtual DataType::Type GetType() const { return DataType::Type::kVoid; }
+  DataType::Type GetType() const {
+    return TypeField::Decode(GetPackedFields());
+  }
 
   virtual bool NeedsEnvironment() const { return false; }
 
@@ -2342,13 +2348,18 @@
   static constexpr size_t kFieldInstructionKind = kFlagReferenceTypeIsExact + 1;
   static constexpr size_t kFieldInstructionKindSize =
       MinimumBitsToStore(static_cast<size_t>(InstructionKind::kLastInstructionKind - 1));
-  static constexpr size_t kNumberOfGenericPackedBits =
+  static constexpr size_t kFieldType =
       kFieldInstructionKind + kFieldInstructionKindSize;
+  static constexpr size_t kFieldTypeSize =
+      MinimumBitsToStore(static_cast<size_t>(DataType::Type::kLast));
+  static constexpr size_t kNumberOfGenericPackedBits = kFieldType + kFieldTypeSize;
   static constexpr size_t kMaxNumberOfPackedBits = sizeof(uint32_t) * kBitsPerByte;
 
   static_assert(kNumberOfGenericPackedBits <= kMaxNumberOfPackedBits,
                 "Too many generic packed fields");
 
+  using TypeField = BitField<DataType::Type, kFieldType, kFieldTypeSize>;
+
   const HUserRecord<HInstruction*> InputRecordAt(size_t i) const {
     return GetInputRecords()[i];
   }
@@ -2595,6 +2606,15 @@
                                 ArenaAllocKind kind)
       : HInstruction(inst_kind, side_effects, dex_pc),
         inputs_(number_of_inputs, allocator->Adapter(kind)) {}
+  HVariableInputSizeInstruction(InstructionKind inst_kind,
+                                DataType::Type type,
+                                SideEffects side_effects,
+                                uint32_t dex_pc,
+                                ArenaAllocator* allocator,
+                                size_t number_of_inputs,
+                                ArenaAllocKind kind)
+      : HInstruction(inst_kind, type, side_effects, dex_pc),
+        inputs_(number_of_inputs, allocator->Adapter(kind)) {}
 
   DEFAULT_COPY_CONSTRUCTOR(VariableInputSizeInstruction);
 
@@ -2602,11 +2622,16 @@
 };
 
 template<size_t N>
-class HTemplateInstruction: public HInstruction {
+class HExpression : public HInstruction {
  public:
-  HTemplateInstruction<N>(InstructionKind kind, SideEffects side_effects, uint32_t dex_pc)
+  HExpression<N>(InstructionKind kind, SideEffects side_effects, uint32_t dex_pc)
       : HInstruction(kind, side_effects, dex_pc), inputs_() {}
-  virtual ~HTemplateInstruction() {}
+  HExpression<N>(InstructionKind kind,
+                 DataType::Type type,
+                 SideEffects side_effects,
+                 uint32_t dex_pc)
+      : HInstruction(kind, type, side_effects, dex_pc), inputs_() {}
+  virtual ~HExpression() {}
 
   using HInstruction::GetInputRecords;  // Keep the const version visible.
   ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() OVERRIDE FINAL {
@@ -2614,7 +2639,7 @@
   }
 
  protected:
-  DEFAULT_COPY_CONSTRUCTOR(TemplateInstruction<N>);
+  DEFAULT_COPY_CONSTRUCTOR(Expression<N>);
 
  private:
   std::array<HUserRecord<HInstruction*>, N> inputs_;
@@ -2622,14 +2647,13 @@
   friend class SsaBuilder;
 };
 
-// HTemplateInstruction specialization for N=0.
+// HExpression specialization for N=0.
 template<>
-class HTemplateInstruction<0>: public HInstruction {
+class HExpression<0> : public HInstruction {
  public:
-  explicit HTemplateInstruction<0>(InstructionKind kind, SideEffects side_effects, uint32_t dex_pc)
-      : HInstruction(kind, side_effects, dex_pc) {}
+  using HInstruction::HInstruction;
 
-  virtual ~HTemplateInstruction() {}
+  virtual ~HExpression() {}
 
   using HInstruction::GetInputRecords;  // Keep the const version visible.
   ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() OVERRIDE FINAL {
@@ -2637,46 +2661,18 @@
   }
 
  protected:
-  DEFAULT_COPY_CONSTRUCTOR(TemplateInstruction<0>);
+  DEFAULT_COPY_CONSTRUCTOR(Expression<0>);
 
  private:
   friend class SsaBuilder;
 };
 
-template<intptr_t N>
-class HExpression : public HTemplateInstruction<N> {
- public:
-  using HInstruction::InstructionKind;
-  HExpression<N>(InstructionKind kind,
-                 DataType::Type type,
-                 SideEffects side_effects,
-                 uint32_t dex_pc)
-      : HTemplateInstruction<N>(kind, side_effects, dex_pc) {
-    this->template SetPackedField<TypeField>(type);
-  }
-  virtual ~HExpression() {}
-
-  DataType::Type GetType() const OVERRIDE {
-    return TypeField::Decode(this->GetPackedFields());
-  }
-
- protected:
-  static constexpr size_t kFieldType = HInstruction::kNumberOfGenericPackedBits;
-  static constexpr size_t kFieldTypeSize =
-      MinimumBitsToStore(static_cast<size_t>(DataType::Type::kLast));
-  static constexpr size_t kNumberOfExpressionPackedBits = kFieldType + kFieldTypeSize;
-  static_assert(kNumberOfExpressionPackedBits <= HInstruction::kMaxNumberOfPackedBits,
-                "Too many packed fields.");
-  using TypeField = BitField<DataType::Type, kFieldType, kFieldTypeSize>;
-  DEFAULT_COPY_CONSTRUCTOR(Expression<N>);
-};
-
 // Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
 // instruction that branches to the exit block.
-class HReturnVoid FINAL : public HTemplateInstruction<0> {
+class HReturnVoid FINAL : public HExpression<0> {
  public:
   explicit HReturnVoid(uint32_t dex_pc = kNoDexPc)
-      : HTemplateInstruction(kReturnVoid, SideEffects::None(), dex_pc) {
+      : HExpression(kReturnVoid, SideEffects::None(), dex_pc) {
   }
 
   bool IsControlFlow() const OVERRIDE { return true; }
@@ -2689,10 +2685,10 @@
 
 // Represents dex's RETURN opcodes. A HReturn is a control flow
 // instruction that branches to the exit block.
-class HReturn FINAL : public HTemplateInstruction<1> {
+class HReturn FINAL : public HExpression<1> {
  public:
   explicit HReturn(HInstruction* value, uint32_t dex_pc = kNoDexPc)
-      : HTemplateInstruction(kReturn, SideEffects::None(), dex_pc) {
+      : HExpression(kReturn, SideEffects::None(), dex_pc) {
     SetRawInputAt(0, value);
   }
 
@@ -2713,13 +2709,13 @@
        uint32_t dex_pc = kNoDexPc)
       : HVariableInputSizeInstruction(
             kPhi,
+            ToPhiType(type),
             SideEffects::None(),
             dex_pc,
             allocator,
             number_of_inputs,
             kArenaAllocPhiInputs),
         reg_number_(reg_number) {
-    SetPackedField<TypeField>(ToPhiType(type));
     DCHECK_NE(GetType(), DataType::Type::kVoid);
     // Phis are constructed live and marked dead if conflicting or unused.
     // Individual steps of SsaBuilder should assume that if a phi has been
@@ -2737,7 +2733,6 @@
 
   bool IsCatchPhi() const { return GetBlock()->IsCatchBlock(); }
 
-  DataType::Type GetType() const OVERRIDE { return GetPackedField<TypeField>(); }
   void SetType(DataType::Type new_type) {
     // Make sure that only valid type changes occur. The following are allowed:
     //  (1) int  -> float/ref (primitive type propagation),
@@ -2796,14 +2791,10 @@
   DEFAULT_COPY_CONSTRUCTOR(Phi);
 
  private:
-  static constexpr size_t kFieldType = HInstruction::kNumberOfGenericPackedBits;
-  static constexpr size_t kFieldTypeSize =
-      MinimumBitsToStore(static_cast<size_t>(DataType::Type::kLast));
-  static constexpr size_t kFlagIsLive = kFieldType + kFieldTypeSize;
+  static constexpr size_t kFlagIsLive = HInstruction::kNumberOfGenericPackedBits;
   static constexpr size_t kFlagCanBeNull = kFlagIsLive + 1;
   static constexpr size_t kNumberOfPhiPackedBits = kFlagCanBeNull + 1;
   static_assert(kNumberOfPhiPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
-  using TypeField = BitField<DataType::Type, kFieldType, kFieldTypeSize>;
 
   const uint32_t reg_number_;
 };
@@ -2811,10 +2802,10 @@
 // The exit instruction is the only instruction of the exit block.
 // Instructions aborting the method (HThrow and HReturn) must branch to the
 // exit block.
-class HExit FINAL : public HTemplateInstruction<0> {
+class HExit FINAL : public HExpression<0> {
  public:
   explicit HExit(uint32_t dex_pc = kNoDexPc)
-      : HTemplateInstruction(kExit, SideEffects::None(), dex_pc) {
+      : HExpression(kExit, SideEffects::None(), dex_pc) {
   }
 
   bool IsControlFlow() const OVERRIDE { return true; }
@@ -2826,10 +2817,10 @@
 };
 
 // Jumps from one block to another.
-class HGoto FINAL : public HTemplateInstruction<0> {
+class HGoto FINAL : public HExpression<0> {
  public:
   explicit HGoto(uint32_t dex_pc = kNoDexPc)
-      : HTemplateInstruction(kGoto, SideEffects::None(), dex_pc) {
+      : HExpression(kGoto, SideEffects::None(), dex_pc) {
   }
 
   bool IsClonable() const OVERRIDE { return true; }
@@ -3096,10 +3087,10 @@
 
 // Conditional branch. A block ending with an HIf instruction must have
 // two successors.
-class HIf FINAL : public HTemplateInstruction<1> {
+class HIf FINAL : public HExpression<1> {
  public:
   explicit HIf(HInstruction* input, uint32_t dex_pc = kNoDexPc)
-      : HTemplateInstruction(kIf, SideEffects::None(), dex_pc) {
+      : HExpression(kIf, SideEffects::None(), dex_pc) {
     SetRawInputAt(0, input);
   }
 
@@ -3126,7 +3117,7 @@
 // non-exceptional control flow.
 // Normal-flow successor is stored at index zero, exception handlers under
 // higher indices in no particular order.
-class HTryBoundary FINAL : public HTemplateInstruction<0> {
+class HTryBoundary FINAL : public HExpression<0> {
  public:
   enum class BoundaryKind {
     kEntry,
@@ -3135,7 +3126,7 @@
   };
 
   explicit HTryBoundary(BoundaryKind kind, uint32_t dex_pc = kNoDexPc)
-      : HTemplateInstruction(kTryBoundary, SideEffects::None(), dex_pc) {
+      : HExpression(kTryBoundary, SideEffects::None(), dex_pc) {
     SetPackedField<BoundaryKindField>(kind);
   }
 
@@ -3219,6 +3210,7 @@
               uint32_t dex_pc)
       : HVariableInputSizeInstruction(
             kDeoptimize,
+            guard->GetType(),
             SideEffects::CanTriggerGC(),
             dex_pc,
             allocator,
@@ -3242,10 +3234,6 @@
 
   DeoptimizationKind GetDeoptimizationKind() const { return GetPackedField<DeoptimizeKindField>(); }
 
-  DataType::Type GetType() const OVERRIDE {
-    return GuardsAnInput() ? GuardedInput()->GetType() : DataType::Type::kVoid;
-  }
-
   bool GuardsAnInput() const {
     return InputCount() == 2;
   }
@@ -3288,6 +3276,7 @@
   // with regard to other passes.
   HShouldDeoptimizeFlag(ArenaAllocator* allocator, uint32_t dex_pc)
       : HVariableInputSizeInstruction(kShouldDeoptimizeFlag,
+                                      DataType::Type::kInt32,
                                       SideEffects::None(),
                                       dex_pc,
                                       allocator,
@@ -3295,8 +3284,6 @@
                                       kArenaAllocCHA) {
   }
 
-  DataType::Type GetType() const OVERRIDE { return DataType::Type::kInt32; }
-
   // We do all CHA guard elimination/motion in a single pass, after which there is no
   // further guard elimination/motion since a guard might have been used for justification
   // of the elimination of another guard. Therefore, we pretend this guard cannot be moved
@@ -3360,7 +3347,7 @@
   DEFAULT_COPY_CONSTRUCTOR(ClassTableGet);
 
  private:
-  static constexpr size_t kFieldTableKind = kNumberOfExpressionPackedBits;
+  static constexpr size_t kFieldTableKind = kNumberOfGenericPackedBits;
   static constexpr size_t kFieldTableKindSize =
       MinimumBitsToStore(static_cast<size_t>(TableKind::kLast));
   static constexpr size_t kNumberOfClassTableGetPackedBits = kFieldTableKind + kFieldTableKindSize;
@@ -3375,13 +3362,13 @@
 // PackedSwitch (jump table). A block ending with a PackedSwitch instruction will
 // have one successor for each entry in the switch table, and the final successor
 // will be the block containing the next Dex opcode.
-class HPackedSwitch FINAL : public HTemplateInstruction<1> {
+class HPackedSwitch FINAL : public HExpression<1> {
  public:
   HPackedSwitch(int32_t start_value,
                 uint32_t num_entries,
                 HInstruction* input,
                 uint32_t dex_pc = kNoDexPc)
-    : HTemplateInstruction(kPackedSwitch, SideEffects::None(), dex_pc),
+    : HExpression(kPackedSwitch, SideEffects::None(), dex_pc),
       start_value_(start_value),
       num_entries_(num_entries) {
     SetRawInputAt(0, input);
@@ -3611,7 +3598,7 @@
 
  protected:
   // Needed if we merge a HCompare into a HCondition.
-  static constexpr size_t kFieldComparisonBias = kNumberOfExpressionPackedBits;
+  static constexpr size_t kFieldComparisonBias = kNumberOfGenericPackedBits;
   static constexpr size_t kFieldComparisonBiasSize =
       MinimumBitsToStore(static_cast<size_t>(ComparisonBias::kLast));
   static constexpr size_t kNumberOfConditionPackedBits =
@@ -4131,7 +4118,7 @@
   DECLARE_INSTRUCTION(Compare);
 
  protected:
-  static constexpr size_t kFieldComparisonBias = kNumberOfExpressionPackedBits;
+  static constexpr size_t kFieldComparisonBias = kNumberOfGenericPackedBits;
   static constexpr size_t kFieldComparisonBiasSize =
       MinimumBitsToStore(static_cast<size_t>(ComparisonBias::kLast));
   static constexpr size_t kNumberOfComparePackedBits =
@@ -4210,7 +4197,7 @@
   DEFAULT_COPY_CONSTRUCTOR(NewInstance);
 
  private:
-  static constexpr size_t kFlagFinalizable = kNumberOfExpressionPackedBits;
+  static constexpr size_t kFlagFinalizable = kNumberOfGenericPackedBits;
   static constexpr size_t kNumberOfNewInstancePackedBits = kFlagFinalizable + 1;
   static_assert(kNumberOfNewInstancePackedBits <= kMaxNumberOfPackedBits,
                 "Too many packed fields.");
@@ -4251,8 +4238,6 @@
   // inputs at the end of their list of inputs.
   uint32_t GetNumberOfArguments() const { return number_of_arguments_; }
 
-  DataType::Type GetType() const OVERRIDE { return GetPackedField<ReturnTypeField>(); }
-
   uint32_t GetDexMethodIndex() const { return dex_method_index_; }
 
   InvokeType GetInvokeType() const {
@@ -4305,16 +4290,11 @@
   static constexpr size_t kFieldInvokeType = kNumberOfGenericPackedBits;
   static constexpr size_t kFieldInvokeTypeSize =
       MinimumBitsToStore(static_cast<size_t>(kMaxInvokeType));
-  static constexpr size_t kFieldReturnType =
-      kFieldInvokeType + kFieldInvokeTypeSize;
-  static constexpr size_t kFieldReturnTypeSize =
-      MinimumBitsToStore(static_cast<size_t>(DataType::Type::kLast));
-  static constexpr size_t kFlagCanThrow = kFieldReturnType + kFieldReturnTypeSize;
+  static constexpr size_t kFlagCanThrow = kFieldInvokeType + kFieldInvokeTypeSize;
   static constexpr size_t kFlagAlwaysThrows = kFlagCanThrow + 1;
   static constexpr size_t kNumberOfInvokePackedBits = kFlagAlwaysThrows + 1;
   static_assert(kNumberOfInvokePackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
   using InvokeTypeField = BitField<InvokeType, kFieldInvokeType, kFieldInvokeTypeSize>;
-  using ReturnTypeField = BitField<DataType::Type, kFieldReturnType, kFieldReturnTypeSize>;
 
   HInvoke(InstructionKind kind,
           ArenaAllocator* allocator,
@@ -4327,6 +4307,7 @@
           InvokeType invoke_type)
     : HVariableInputSizeInstruction(
           kind,
+          return_type,
           SideEffects::AllExceptGCDependency(),  // Assume write/read on all fields/arrays.
           dex_pc,
           allocator,
@@ -4337,7 +4318,6 @@
       dex_method_index_(dex_method_index),
       intrinsic_(Intrinsics::kNone),
       intrinsic_optimizations_(0) {
-    SetPackedField<ReturnTypeField>(return_type);
     SetPackedField<InvokeTypeField>(invoke_type);
     SetPackedFlag<kFlagCanThrow>(true);
   }
@@ -4550,7 +4530,7 @@
   }
 
   bool CanBeNull() const OVERRIDE {
-    return GetPackedField<ReturnTypeField>() == DataType::Type::kReference && !IsStringInit();
+    return GetType() == DataType::Type::kReference && !IsStringInit();
   }
 
   // Get the index of the special input, if any.
@@ -5146,8 +5126,6 @@
     SetRawInputAt(0, value);
   }
 
-  DataType::Type GetType() const OVERRIDE { return InputAt(0)->GetType(); }
-
   bool CanBeMoved() const OVERRIDE { return true; }
 
   bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
@@ -5500,7 +5478,7 @@
 
  private:
   // Whether or not the parameter value corresponds to 'this' argument.
-  static constexpr size_t kFlagIsThis = kNumberOfExpressionPackedBits;
+  static constexpr size_t kFlagIsThis = kNumberOfGenericPackedBits;
   static constexpr size_t kFlagCanBeNull = kFlagIsThis + 1;
   static constexpr size_t kNumberOfParameterValuePackedBits = kFlagCanBeNull + 1;
   static_assert(kNumberOfParameterValuePackedBits <= kMaxNumberOfPackedBits,
@@ -5742,7 +5720,7 @@
   const FieldInfo field_info_;
 };
 
-class HInstanceFieldSet FINAL : public HTemplateInstruction<2> {
+class HInstanceFieldSet FINAL : public HExpression<2> {
  public:
   HInstanceFieldSet(HInstruction* object,
                     HInstruction* value,
@@ -5754,9 +5732,9 @@
                     uint16_t declaring_class_def_index,
                     const DexFile& dex_file,
                     uint32_t dex_pc)
-      : HTemplateInstruction(kInstanceFieldSet,
-                             SideEffects::FieldWriteOfType(field_type, is_volatile),
-                             dex_pc),
+      : HExpression(kInstanceFieldSet,
+                    SideEffects::FieldWriteOfType(field_type, is_volatile),
+                    dex_pc),
         field_info_(field,
                     field_offset,
                     field_type,
@@ -5882,13 +5860,13 @@
   // a particular HArrayGet is actually a String.charAt() by looking at the type
   // of the input but that requires holding the mutator lock, so we prefer to use
   // a flag, so that code generators don't need to do the locking.
-  static constexpr size_t kFlagIsStringCharAt = kNumberOfExpressionPackedBits;
+  static constexpr size_t kFlagIsStringCharAt = kNumberOfGenericPackedBits;
   static constexpr size_t kNumberOfArrayGetPackedBits = kFlagIsStringCharAt + 1;
   static_assert(kNumberOfArrayGetPackedBits <= HInstruction::kMaxNumberOfPackedBits,
                 "Too many packed fields.");
 };
 
-class HArraySet FINAL : public HTemplateInstruction<3> {
+class HArraySet FINAL : public HExpression<3> {
  public:
   HArraySet(HInstruction* array,
             HInstruction* index,
@@ -5910,7 +5888,7 @@
             DataType::Type expected_component_type,
             SideEffects side_effects,
             uint32_t dex_pc)
-      : HTemplateInstruction(kArraySet, side_effects, dex_pc) {
+      : HExpression(kArraySet, side_effects, dex_pc) {
     SetPackedField<ExpectedComponentTypeField>(expected_component_type);
     SetPackedFlag<kFlagNeedsTypeCheck>(value->GetType() == DataType::Type::kReference);
     SetPackedFlag<kFlagValueCanBeNull>(true);
@@ -6039,7 +6017,7 @@
   // determine whether a particular HArrayLength is actually a String.length() by
   // looking at the type of the input but that requires holding the mutator lock, so
   // we prefer to use a flag, so that code generators don't need to do the locking.
-  static constexpr size_t kFlagIsStringLength = kNumberOfExpressionPackedBits;
+  static constexpr size_t kFlagIsStringLength = kNumberOfGenericPackedBits;
   static constexpr size_t kNumberOfArrayLengthPackedBits = kFlagIsStringLength + 1;
   static_assert(kNumberOfArrayLengthPackedBits <= HInstruction::kMaxNumberOfPackedBits,
                 "Too many packed fields.");
@@ -6080,13 +6058,13 @@
   DEFAULT_COPY_CONSTRUCTOR(BoundsCheck);
 
  private:
-  static constexpr size_t kFlagIsStringCharAt = kNumberOfExpressionPackedBits;
+  static constexpr size_t kFlagIsStringCharAt = kNumberOfGenericPackedBits;
 };
 
-class HSuspendCheck FINAL : public HTemplateInstruction<0> {
+class HSuspendCheck FINAL : public HExpression<0> {
  public:
   explicit HSuspendCheck(uint32_t dex_pc = kNoDexPc)
-      : HTemplateInstruction(kSuspendCheck, SideEffects::CanTriggerGC(), dex_pc),
+      : HExpression(kSuspendCheck, SideEffects::CanTriggerGC(), dex_pc),
         slow_path_(nullptr) {
   }
 
@@ -6112,10 +6090,10 @@
 
 // Pseudo-instruction which provides the native debugger with mapping information.
 // It ensures that we can generate line number and local variables at this point.
-class HNativeDebugInfo : public HTemplateInstruction<0> {
+class HNativeDebugInfo : public HExpression<0> {
  public:
   explicit HNativeDebugInfo(uint32_t dex_pc)
-      : HTemplateInstruction<0>(kNativeDebugInfo, SideEffects::None(), dex_pc) {
+      : HExpression<0>(kNativeDebugInfo, SideEffects::None(), dex_pc) {
   }
 
   bool NeedsEnvironment() const OVERRIDE {
@@ -6174,7 +6152,10 @@
              bool is_referrers_class,
              uint32_t dex_pc,
              bool needs_access_check)
-      : HInstruction(kLoadClass, SideEffectsForArchRuntimeCalls(), dex_pc),
+      : HInstruction(kLoadClass,
+                     DataType::Type::kReference,
+                     SideEffectsForArchRuntimeCalls(),
+                     dex_pc),
         special_input_(HUserRecord<HInstruction*>(current_method)),
         type_index_(type_index),
         dex_file_(dex_file),
@@ -6285,10 +6266,6 @@
         &special_input_, (special_input_.GetInstruction() != nullptr) ? 1u : 0u);
   }
 
-  DataType::Type GetType() const OVERRIDE {
-    return DataType::Type::kReference;
-  }
-
   Handle<mirror::Class> GetClass() const {
     return klass_;
   }
@@ -6399,7 +6376,10 @@
               dex::StringIndex string_index,
               const DexFile& dex_file,
               uint32_t dex_pc)
-      : HInstruction(kLoadString, SideEffectsForArchRuntimeCalls(), dex_pc),
+      : HInstruction(kLoadString,
+                     DataType::Type::kReference,
+                     SideEffectsForArchRuntimeCalls(),
+                     dex_pc),
         special_input_(HUserRecord<HInstruction*>(current_method)),
         string_index_(string_index),
         dex_file_(dex_file) {
@@ -6474,10 +6454,6 @@
         &special_input_, (special_input_.GetInstruction() != nullptr) ? 1u : 0u);
   }
 
-  DataType::Type GetType() const OVERRIDE {
-    return DataType::Type::kReference;
-  }
-
   DECLARE_INSTRUCTION(LoadString);
 
  protected:
@@ -6633,7 +6609,7 @@
   const FieldInfo field_info_;
 };
 
-class HStaticFieldSet FINAL : public HTemplateInstruction<2> {
+class HStaticFieldSet FINAL : public HExpression<2> {
  public:
   HStaticFieldSet(HInstruction* cls,
                   HInstruction* value,
@@ -6645,9 +6621,9 @@
                   uint16_t declaring_class_def_index,
                   const DexFile& dex_file,
                   uint32_t dex_pc)
-      : HTemplateInstruction(kStaticFieldSet,
-                             SideEffects::FieldWriteOfType(field_type, is_volatile),
-                             dex_pc),
+      : HExpression(kStaticFieldSet,
+                    SideEffects::FieldWriteOfType(field_type, is_volatile),
+                    dex_pc),
         field_info_(field,
                     field_offset,
                     field_type,
@@ -6714,16 +6690,14 @@
   const uint32_t field_index_;
 };
 
-class HUnresolvedInstanceFieldSet FINAL : public HTemplateInstruction<2> {
+class HUnresolvedInstanceFieldSet FINAL : public HExpression<2> {
  public:
   HUnresolvedInstanceFieldSet(HInstruction* obj,
                               HInstruction* value,
                               DataType::Type field_type,
                               uint32_t field_index,
                               uint32_t dex_pc)
-      : HTemplateInstruction(kUnresolvedInstanceFieldSet,
-                             SideEffects::AllExceptGCDependency(),
-                             dex_pc),
+      : HExpression(kUnresolvedInstanceFieldSet, SideEffects::AllExceptGCDependency(), dex_pc),
         field_index_(field_index) {
     SetPackedField<FieldTypeField>(field_type);
     DCHECK_EQ(DataType::Kind(field_type), DataType::Kind(value->GetType()));
@@ -6784,15 +6758,13 @@
   const uint32_t field_index_;
 };
 
-class HUnresolvedStaticFieldSet FINAL : public HTemplateInstruction<1> {
+class HUnresolvedStaticFieldSet FINAL : public HExpression<1> {
  public:
   HUnresolvedStaticFieldSet(HInstruction* value,
                             DataType::Type field_type,
                             uint32_t field_index,
                             uint32_t dex_pc)
-      : HTemplateInstruction(kUnresolvedStaticFieldSet,
-                             SideEffects::AllExceptGCDependency(),
-                             dex_pc),
+      : HExpression(kUnresolvedStaticFieldSet, SideEffects::AllExceptGCDependency(), dex_pc),
         field_index_(field_index) {
     SetPackedField<FieldTypeField>(field_type);
     DCHECK_EQ(DataType::Kind(field_type), DataType::Kind(value->GetType()));
@@ -6841,10 +6813,10 @@
 
 // Implicit part of move-exception which clears thread-local exception storage.
 // Must not be removed because the runtime expects the TLS to get cleared.
-class HClearException FINAL : public HTemplateInstruction<0> {
+class HClearException FINAL : public HExpression<0> {
  public:
   explicit HClearException(uint32_t dex_pc = kNoDexPc)
-      : HTemplateInstruction(kClearException, SideEffects::AllWrites(), dex_pc) {
+      : HExpression(kClearException, SideEffects::AllWrites(), dex_pc) {
   }
 
   DECLARE_INSTRUCTION(ClearException);
@@ -6853,10 +6825,10 @@
   DEFAULT_COPY_CONSTRUCTOR(ClearException);
 };
 
-class HThrow FINAL : public HTemplateInstruction<1> {
+class HThrow FINAL : public HExpression<1> {
  public:
   HThrow(HInstruction* exception, uint32_t dex_pc)
-      : HTemplateInstruction(kThrow, SideEffects::CanTriggerGC(), dex_pc) {
+      : HExpression(kThrow, SideEffects::CanTriggerGC(), dex_pc) {
     SetRawInputAt(0, exception);
   }
 
@@ -6897,6 +6869,7 @@
 class HTypeCheckInstruction : public HVariableInputSizeInstruction {
  public:
   HTypeCheckInstruction(InstructionKind kind,
+                        DataType::Type type,
                         HInstruction* object,
                         HInstruction* target_class_or_null,
                         TypeCheckKind check_kind,
@@ -6908,6 +6881,7 @@
                         SideEffects side_effects)
       : HVariableInputSizeInstruction(
           kind,
+          type,
           side_effects,
           dex_pc,
           allocator,
@@ -7010,6 +6984,7 @@
               HIntConstant* bitstring_path_to_root,
               HIntConstant* bitstring_mask)
       : HTypeCheckInstruction(kInstanceOf,
+                              DataType::Type::kBool,
                               object,
                               target_class_or_null,
                               check_kind,
@@ -7020,8 +6995,6 @@
                               bitstring_mask,
                               SideEffectsForArchRuntimeCalls(check_kind)) {}
 
-  DataType::Type GetType() const OVERRIDE { return DataType::Type::kBool; }
-
   bool NeedsEnvironment() const OVERRIDE {
     return CanCallRuntime(GetTypeCheckKind());
   }
@@ -7074,7 +7047,7 @@
  private:
   // Represents the top constraint that can_be_null_ cannot exceed (i.e. if this
   // is false then CanBeNull() cannot be true).
-  static constexpr size_t kFlagUpperCanBeNull = kNumberOfExpressionPackedBits;
+  static constexpr size_t kFlagUpperCanBeNull = kNumberOfGenericPackedBits;
   static constexpr size_t kFlagCanBeNull = kFlagUpperCanBeNull + 1;
   static constexpr size_t kNumberOfBoundTypePackedBits = kFlagCanBeNull + 1;
   static_assert(kNumberOfBoundTypePackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
@@ -7099,6 +7072,7 @@
              HIntConstant* bitstring_path_to_root,
              HIntConstant* bitstring_mask)
       : HTypeCheckInstruction(kCheckCast,
+                              DataType::Type::kVoid,
                               object,
                               target_class_or_null,
                               check_kind,
@@ -7148,13 +7122,12 @@
 };
 std::ostream& operator<<(std::ostream& os, const MemBarrierKind& kind);
 
-class HMemoryBarrier FINAL : public HTemplateInstruction<0> {
+class HMemoryBarrier FINAL : public HExpression<0> {
  public:
   explicit HMemoryBarrier(MemBarrierKind barrier_kind, uint32_t dex_pc = kNoDexPc)
-      : HTemplateInstruction(
-            kMemoryBarrier,
-            SideEffects::AllWritesAndReads(),  // Assume write/read on all fields/arrays.
-            dex_pc) {
+      : HExpression(kMemoryBarrier,
+                    SideEffects::AllWritesAndReads(),  // Assume write/read on all fields/arrays.
+                    dex_pc) {
     SetPackedField<BarrierKindField>(barrier_kind);
   }
 
@@ -7331,7 +7304,7 @@
   DEFAULT_COPY_CONSTRUCTOR(ConstructorFence);
 };
 
-class HMonitorOperation FINAL : public HTemplateInstruction<1> {
+class HMonitorOperation FINAL : public HExpression<1> {
  public:
   enum class OperationKind {
     kEnter,
@@ -7340,10 +7313,9 @@
   };
 
   HMonitorOperation(HInstruction* object, OperationKind kind, uint32_t dex_pc)
-    : HTemplateInstruction(
-          kMonitorOperation,
-          SideEffects::AllExceptGCDependency(),  // Assume write/read on all fields/arrays.
-          dex_pc) {
+    : HExpression(kMonitorOperation,
+                  SideEffects::AllExceptGCDependency(),  // Assume write/read on all fields/arrays.
+                  dex_pc) {
     SetPackedField<OperationKindField>(kind);
     SetRawInputAt(0, object);
   }
@@ -7493,10 +7465,10 @@
 
 static constexpr size_t kDefaultNumberOfMoves = 4;
 
-class HParallelMove FINAL : public HTemplateInstruction<0> {
+class HParallelMove FINAL : public HExpression<0> {
  public:
   explicit HParallelMove(ArenaAllocator* allocator, uint32_t dex_pc = kNoDexPc)
-      : HTemplateInstruction(kParallelMove, SideEffects::None(), dex_pc),
+      : HExpression(kParallelMove, SideEffects::None(), dex_pc),
         moves_(allocator->Adapter(kArenaAllocMoveOperands)) {
     moves_.reserve(kDefaultNumberOfMoves);
   }
diff --git a/compiler/optimizing/nodes_mips.h b/compiler/optimizing/nodes_mips.h
index d0e0fef..05b27a7 100644
--- a/compiler/optimizing/nodes_mips.h
+++ b/compiler/optimizing/nodes_mips.h
@@ -39,14 +39,14 @@
 };
 
 // Mips version of HPackedSwitch that holds a pointer to the base method address.
-class HMipsPackedSwitch FINAL : public HTemplateInstruction<2> {
+class HMipsPackedSwitch FINAL : public HExpression<2> {
  public:
   HMipsPackedSwitch(int32_t start_value,
                     int32_t num_entries,
                     HInstruction* input,
                     HMipsComputeBaseMethodAddress* method_base,
                     uint32_t dex_pc)
-    : HTemplateInstruction(kMipsPackedSwitch, SideEffects::None(), dex_pc),
+    : HExpression(kMipsPackedSwitch, SideEffects::None(), dex_pc),
       start_value_(start_value),
       num_entries_(num_entries) {
     SetRawInputAt(0, input);
diff --git a/compiler/optimizing/nodes_vector.h b/compiler/optimizing/nodes_vector.h
index 1a484e1..c5e9a8d 100644
--- a/compiler/optimizing/nodes_vector.h
+++ b/compiler/optimizing/nodes_vector.h
@@ -79,13 +79,14 @@
                 size_t vector_length,
                 uint32_t dex_pc)
       : HVariableInputSizeInstruction(kind,
+                                      kSIMDType,
                                       side_effects,
                                       dex_pc,
                                       allocator,
                                       number_of_inputs,
                                       kArenaAllocVectorNode),
         vector_length_(vector_length) {
-    SetPackedField<TypeField>(packed_type);
+    SetPackedField<PackedTypeField>(packed_type);
     DCHECK_LT(1u, vector_length);
   }
 
@@ -99,14 +100,9 @@
     return vector_length_ * DataType::Size(GetPackedType());
   }
 
-  // Returns the type of the vector operation.
-  DataType::Type GetType() const OVERRIDE {
-    return kSIMDType;
-  }
-
   // Returns the true component type packed in a vector.
   DataType::Type GetPackedType() const {
-    return GetPackedField<TypeField>();
+    return GetPackedField<PackedTypeField>();
   }
 
   // Assumes vector nodes cannot be moved by default. Each concrete implementation
@@ -185,12 +181,12 @@
 
  protected:
   // Additional packed bits.
-  static constexpr size_t kFieldType = HInstruction::kNumberOfGenericPackedBits;
-  static constexpr size_t kFieldTypeSize =
+  static constexpr size_t kFieldPackedType = HInstruction::kNumberOfGenericPackedBits;
+  static constexpr size_t kFieldPackedTypeSize =
       MinimumBitsToStore(static_cast<size_t>(DataType::Type::kLast));
-  static constexpr size_t kNumberOfVectorOpPackedBits = kFieldType + kFieldTypeSize;
+  static constexpr size_t kNumberOfVectorOpPackedBits = kFieldPackedType + kFieldPackedTypeSize;
   static_assert(kNumberOfVectorOpPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
-  using TypeField = BitField<DataType::Type, kFieldType, kFieldTypeSize>;
+  using PackedTypeField = BitField<DataType::Type, kFieldPackedType, kFieldPackedTypeSize>;
 
   DEFAULT_COPY_CONSTRUCTOR(VecOperation);
 
@@ -358,11 +354,9 @@
     DCHECK(HasConsistentPackedTypes(input, packed_type));
     DCHECK_LT(index, vector_length);
     DCHECK_EQ(index, 0u);
-  }
-
-  // Yields a single component in the vector.
-  DataType::Type GetType() const OVERRIDE {
-    return GetPackedType();
+    // Yields a single component in the vector.
+    // Overrides the kSIMDType set by the VecOperation constructor.
+    SetPackedField<TypeField>(packed_type);
   }
 
   // An extract needs to stay in place, since SIMD registers are not
diff --git a/compiler/optimizing/nodes_x86.h b/compiler/optimizing/nodes_x86.h
index 4c32be7..d1e7f68 100644
--- a/compiler/optimizing/nodes_x86.h
+++ b/compiler/optimizing/nodes_x86.h
@@ -89,14 +89,14 @@
 };
 
 // X86 version of HPackedSwitch that holds a pointer to the base method address.
-class HX86PackedSwitch FINAL : public HTemplateInstruction<2> {
+class HX86PackedSwitch FINAL : public HExpression<2> {
  public:
   HX86PackedSwitch(int32_t start_value,
                    int32_t num_entries,
                    HInstruction* input,
                    HX86ComputeBaseMethodAddress* method_base,
                    uint32_t dex_pc)
-    : HTemplateInstruction(kX86PackedSwitch, SideEffects::None(), dex_pc),
+    : HExpression(kX86PackedSwitch, SideEffects::None(), dex_pc),
       start_value_(start_value),
       num_entries_(num_entries) {
     SetRawInputAt(0, input);