Fix iCache misses for GetKind on x86,x86_64

GetKind() takes about 2.6% of total compilation time on x86_64.
The primary reason is that the target call GetKindInternal() is often
beyond the page boundary causing frequent i-cache misses.
This patch removes the virtual call to GetKindInternal () and instead
keeps the InstructionKind into each constructed instruction.
Since we have about 121 instructions in total as of now,
it takes about 7 extra bits in each instruction.
dex2oat runs about 12% faster with --compiler-filter=everything on an
APK of 25MB.

Test: Tested the patch by running host art tests.

Rebased.

Change-Id: Ia7bbcd67180151e4565507164a718acbb6284885
Signed-off-by: Gupta Kumar, Sanjiv <sanjiv.kumar.gupta@intel.com>
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index f91d37b..0534685 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -1518,7 +1518,6 @@
   private:                                                                \
   H##type& operator=(const H##type&) = delete;                            \
   public:                                                                 \
-  InstructionKind GetKindInternal() const OVERRIDE { return k##type; }    \
   const char* DebugName() const OVERRIDE { return #type; }                \
   bool InstructionTypeEquals(const HInstruction* other) const OVERRIDE {  \
     return other->Is##type();                                             \
@@ -1952,7 +1951,14 @@
 
 class HInstruction : public ArenaObject<kArenaAllocInstruction> {
  public:
-  HInstruction(SideEffects side_effects, uint32_t dex_pc)
+#define DECLARE_KIND(type, super) k##type,
+  enum InstructionKind {
+    FOR_EACH_INSTRUCTION(DECLARE_KIND)
+    kLastInstructionKind
+  };
+#undef DECLARE_KIND
+
+  HInstruction(InstructionKind kind, SideEffects side_effects, uint32_t dex_pc)
       : previous_(nullptr),
         next_(nullptr),
         block_(nullptr),
@@ -1966,16 +1972,12 @@
         lifetime_position_(kNoLifetime),
         side_effects_(side_effects),
         reference_type_handle_(ReferenceTypeInfo::CreateInvalid().GetTypeHandle()) {
+    SetPackedField<InstructionKindField>(kind);
     SetPackedFlag<kFlagReferenceTypeIsExact>(ReferenceTypeInfo::CreateInvalid().IsExact());
   }
 
   virtual ~HInstruction() {}
 
-#define DECLARE_KIND(type, super) k##type,
-  enum InstructionKind {
-    FOR_EACH_INSTRUCTION(DECLARE_KIND)
-  };
-#undef DECLARE_KIND
 
   HInstruction* GetNext() const { return next_; }
   HInstruction* GetPrevious() const { return previous_; }
@@ -2279,8 +2281,7 @@
   // is adopted and implemented by our C++ compiler(s). Fow now, we need to hide
   // the virtual function because the __attribute__((__pure__)) doesn't really
   // apply the strong requirement for virtual functions, preventing optimizations.
-  InstructionKind GetKind() const PURE;
-  virtual InstructionKind GetKindInternal() const = 0;
+  InstructionKind GetKind() const { return GetPackedField<InstructionKindField>(); }
 
   virtual size_t ComputeHashCode() const {
     size_t result = GetKind();
@@ -2332,9 +2333,16 @@
   // its users. Used by liveness analysis to compute use positions accordingly.
   static constexpr size_t kFlagEmittedAtUseSite = 0u;
   static constexpr size_t kFlagReferenceTypeIsExact = kFlagEmittedAtUseSite + 1;
-  static constexpr size_t kNumberOfGenericPackedBits = kFlagReferenceTypeIsExact + 1;
+  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 =
+      kFieldInstructionKind + kFieldInstructionKindSize;
   static constexpr size_t kMaxNumberOfPackedBits = sizeof(uint32_t) * kBitsPerByte;
 
+  static_assert(kNumberOfGenericPackedBits <= kMaxNumberOfPackedBits,
+                "Too many generic packed fields");
+
   const HUserRecord<HInstruction*> InputRecordAt(size_t i) const {
     return GetInputRecords()[i];
   }
@@ -2391,9 +2399,13 @@
         live_interval_(nullptr),
         lifetime_position_(kNoLifetime),
         side_effects_(other.side_effects_),
-        reference_type_handle_(other.reference_type_handle_) {}
+        reference_type_handle_(other.reference_type_handle_) {
+  }
 
  private:
+  using InstructionKindField =
+     BitField<InstructionKind, kFieldInstructionKind, kFieldInstructionKindSize>;
+
   void FixUpUserRecordsAfterUseInsertion(HUseList<HInstruction*>::iterator fixup_end) {
     auto before_use_node = uses_.before_begin();
     for (auto use_node = uses_.begin(); use_node != fixup_end; ++use_node) {
@@ -2569,12 +2581,13 @@
   void RemoveAllInputs();
 
  protected:
-  HVariableInputSizeInstruction(SideEffects side_effects,
+  HVariableInputSizeInstruction(InstructionKind inst_kind,
+                                SideEffects side_effects,
                                 uint32_t dex_pc,
                                 ArenaAllocator* allocator,
                                 size_t number_of_inputs,
                                 ArenaAllocKind kind)
-      : HInstruction(side_effects, dex_pc),
+      : HInstruction(inst_kind, side_effects, dex_pc),
         inputs_(number_of_inputs, allocator->Adapter(kind)) {}
 
   DEFAULT_COPY_CONSTRUCTOR(VariableInputSizeInstruction);
@@ -2585,8 +2598,8 @@
 template<size_t N>
 class HTemplateInstruction: public HInstruction {
  public:
-  HTemplateInstruction<N>(SideEffects side_effects, uint32_t dex_pc)
-      : HInstruction(side_effects, dex_pc), inputs_() {}
+  HTemplateInstruction<N>(InstructionKind kind, SideEffects side_effects, uint32_t dex_pc)
+      : HInstruction(kind, side_effects, dex_pc), inputs_() {}
   virtual ~HTemplateInstruction() {}
 
   using HInstruction::GetInputRecords;  // Keep the const version visible.
@@ -2607,8 +2620,8 @@
 template<>
 class HTemplateInstruction<0>: public HInstruction {
  public:
-  explicit HTemplateInstruction<0>(SideEffects side_effects, uint32_t dex_pc)
-      : HInstruction(side_effects, dex_pc) {}
+  explicit HTemplateInstruction<0>(InstructionKind kind, SideEffects side_effects, uint32_t dex_pc)
+      : HInstruction(kind, side_effects, dex_pc) {}
 
   virtual ~HTemplateInstruction() {}
 
@@ -2627,8 +2640,12 @@
 template<intptr_t N>
 class HExpression : public HTemplateInstruction<N> {
  public:
-  HExpression<N>(DataType::Type type, SideEffects side_effects, uint32_t dex_pc)
-      : HTemplateInstruction<N>(side_effects, dex_pc) {
+  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() {}
@@ -2653,7 +2670,8 @@
 class HReturnVoid FINAL : public HTemplateInstruction<0> {
  public:
   explicit HReturnVoid(uint32_t dex_pc = kNoDexPc)
-      : HTemplateInstruction(SideEffects::None(), dex_pc) {}
+      : HTemplateInstruction(kReturnVoid, SideEffects::None(), dex_pc) {
+  }
 
   bool IsControlFlow() const OVERRIDE { return true; }
 
@@ -2668,7 +2686,7 @@
 class HReturn FINAL : public HTemplateInstruction<1> {
  public:
   explicit HReturn(HInstruction* value, uint32_t dex_pc = kNoDexPc)
-      : HTemplateInstruction(SideEffects::None(), dex_pc) {
+      : HTemplateInstruction(kReturn, SideEffects::None(), dex_pc) {
     SetRawInputAt(0, value);
   }
 
@@ -2688,6 +2706,7 @@
        DataType::Type type,
        uint32_t dex_pc = kNoDexPc)
       : HVariableInputSizeInstruction(
+            kPhi,
             SideEffects::None(),
             dex_pc,
             allocator,
@@ -2788,7 +2807,9 @@
 // exit block.
 class HExit FINAL : public HTemplateInstruction<0> {
  public:
-  explicit HExit(uint32_t dex_pc = kNoDexPc) : HTemplateInstruction(SideEffects::None(), dex_pc) {}
+  explicit HExit(uint32_t dex_pc = kNoDexPc)
+      : HTemplateInstruction(kExit, SideEffects::None(), dex_pc) {
+  }
 
   bool IsControlFlow() const OVERRIDE { return true; }
 
@@ -2801,7 +2822,9 @@
 // Jumps from one block to another.
 class HGoto FINAL : public HTemplateInstruction<0> {
  public:
-  explicit HGoto(uint32_t dex_pc = kNoDexPc) : HTemplateInstruction(SideEffects::None(), dex_pc) {}
+  explicit HGoto(uint32_t dex_pc = kNoDexPc)
+      : HTemplateInstruction(kGoto, SideEffects::None(), dex_pc) {
+  }
 
   bool IsClonable() const OVERRIDE { return true; }
   bool IsControlFlow() const OVERRIDE { return true; }
@@ -2818,8 +2841,9 @@
 
 class HConstant : public HExpression<0> {
  public:
-  explicit HConstant(DataType::Type type, uint32_t dex_pc = kNoDexPc)
-      : HExpression(type, SideEffects::None(), dex_pc) {}
+  explicit HConstant(InstructionKind kind, DataType::Type type, uint32_t dex_pc = kNoDexPc)
+      : HExpression(kind, type, SideEffects::None(), dex_pc) {
+  }
 
   bool CanBeMoved() const OVERRIDE { return true; }
 
@@ -2860,7 +2884,8 @@
 
  private:
   explicit HNullConstant(uint32_t dex_pc = kNoDexPc)
-      : HConstant(DataType::Type::kReference, dex_pc) {}
+      : HConstant(kNullConstant, DataType::Type::kReference, dex_pc) {
+  }
 
   friend class HGraph;
 };
@@ -2899,9 +2924,12 @@
 
  private:
   explicit HIntConstant(int32_t value, uint32_t dex_pc = kNoDexPc)
-      : HConstant(DataType::Type::kInt32, dex_pc), value_(value) {}
+      : HConstant(kIntConstant, DataType::Type::kInt32, dex_pc), value_(value) {
+  }
   explicit HIntConstant(bool value, uint32_t dex_pc = kNoDexPc)
-      : HConstant(DataType::Type::kInt32, dex_pc), value_(value ? 1 : 0) {}
+      : HConstant(kIntConstant, DataType::Type::kInt32, dex_pc),
+        value_(value ? 1 : 0) {
+  }
 
   const int32_t value_;
 
@@ -2935,7 +2963,9 @@
 
  private:
   explicit HLongConstant(int64_t value, uint32_t dex_pc = kNoDexPc)
-      : HConstant(DataType::Type::kInt64, dex_pc), value_(value) {}
+      : HConstant(kLongConstant, DataType::Type::kInt64, dex_pc),
+        value_(value) {
+  }
 
   const int64_t value_;
 
@@ -2986,9 +3016,13 @@
 
  private:
   explicit HFloatConstant(float value, uint32_t dex_pc = kNoDexPc)
-      : HConstant(DataType::Type::kFloat32, dex_pc), value_(value) {}
+      : HConstant(kFloatConstant, DataType::Type::kFloat32, dex_pc),
+        value_(value) {
+  }
   explicit HFloatConstant(int32_t value, uint32_t dex_pc = kNoDexPc)
-      : HConstant(DataType::Type::kFloat32, dex_pc), value_(bit_cast<float, int32_t>(value)) {}
+      : HConstant(kFloatConstant, DataType::Type::kFloat32, dex_pc),
+        value_(bit_cast<float, int32_t>(value)) {
+  }
 
   const float value_;
 
@@ -3039,9 +3073,13 @@
 
  private:
   explicit HDoubleConstant(double value, uint32_t dex_pc = kNoDexPc)
-      : HConstant(DataType::Type::kFloat64, dex_pc), value_(value) {}
+      : HConstant(kDoubleConstant, DataType::Type::kFloat64, dex_pc),
+        value_(value) {
+  }
   explicit HDoubleConstant(int64_t value, uint32_t dex_pc = kNoDexPc)
-      : HConstant(DataType::Type::kFloat64, dex_pc), value_(bit_cast<double, int64_t>(value)) {}
+      : HConstant(kDoubleConstant, DataType::Type::kFloat64, dex_pc),
+        value_(bit_cast<double, int64_t>(value)) {
+  }
 
   const double value_;
 
@@ -3055,7 +3093,7 @@
 class HIf FINAL : public HTemplateInstruction<1> {
  public:
   explicit HIf(HInstruction* input, uint32_t dex_pc = kNoDexPc)
-      : HTemplateInstruction(SideEffects::None(), dex_pc) {
+      : HTemplateInstruction(kIf, SideEffects::None(), dex_pc) {
     SetRawInputAt(0, input);
   }
 
@@ -3091,7 +3129,7 @@
   };
 
   explicit HTryBoundary(BoundaryKind kind, uint32_t dex_pc = kNoDexPc)
-      : HTemplateInstruction(SideEffects::None(), dex_pc) {
+      : HTemplateInstruction(kTryBoundary, SideEffects::None(), dex_pc) {
     SetPackedField<BoundaryKindField>(kind);
   }
 
@@ -3150,6 +3188,7 @@
               DeoptimizationKind kind,
               uint32_t dex_pc)
       : HVariableInputSizeInstruction(
+            kDeoptimize,
             SideEffects::All(),
             dex_pc,
             allocator,
@@ -3173,6 +3212,7 @@
               DeoptimizationKind kind,
               uint32_t dex_pc)
       : HVariableInputSizeInstruction(
+            kDeoptimize,
             SideEffects::CanTriggerGC(),
             dex_pc,
             allocator,
@@ -3241,7 +3281,12 @@
   // CHA guards are only optimized in a separate pass and it has no side effects
   // with regard to other passes.
   HShouldDeoptimizeFlag(ArenaAllocator* allocator, uint32_t dex_pc)
-      : HVariableInputSizeInstruction(SideEffects::None(), dex_pc, allocator, 0, kArenaAllocCHA) {
+      : HVariableInputSizeInstruction(kShouldDeoptimizeFlag,
+                                      SideEffects::None(),
+                                      dex_pc,
+                                      allocator,
+                                      0,
+                                      kArenaAllocCHA) {
   }
 
   DataType::Type GetType() const OVERRIDE { return DataType::Type::kInt32; }
@@ -3264,7 +3309,8 @@
 class HCurrentMethod FINAL : public HExpression<0> {
  public:
   explicit HCurrentMethod(DataType::Type type, uint32_t dex_pc = kNoDexPc)
-      : HExpression(type, SideEffects::None(), dex_pc) {}
+      : HExpression(kCurrentMethod, type, SideEffects::None(), dex_pc) {
+  }
 
   DECLARE_INSTRUCTION(CurrentMethod);
 
@@ -3286,7 +3332,7 @@
                  TableKind kind,
                  size_t index,
                  uint32_t dex_pc)
-      : HExpression(type, SideEffects::None(), dex_pc),
+      : HExpression(kClassTableGet, type, SideEffects::None(), dex_pc),
         index_(index) {
     SetPackedField<TableKindField>(kind);
     SetRawInputAt(0, cls);
@@ -3329,7 +3375,7 @@
                 uint32_t num_entries,
                 HInstruction* input,
                 uint32_t dex_pc = kNoDexPc)
-    : HTemplateInstruction(SideEffects::None(), dex_pc),
+    : HTemplateInstruction(kPackedSwitch, SideEffects::None(), dex_pc),
       start_value_(start_value),
       num_entries_(num_entries) {
     SetRawInputAt(0, input);
@@ -3359,8 +3405,11 @@
 
 class HUnaryOperation : public HExpression<1> {
  public:
-  HUnaryOperation(DataType::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc)
-      : HExpression(result_type, SideEffects::None(), dex_pc) {
+  HUnaryOperation(InstructionKind kind,
+                  DataType::Type result_type,
+                  HInstruction* input,
+                  uint32_t dex_pc = kNoDexPc)
+      : HExpression(kind, result_type, SideEffects::None(), dex_pc) {
     SetRawInputAt(0, input);
   }
 
@@ -3394,12 +3443,13 @@
 
 class HBinaryOperation : public HExpression<2> {
  public:
-  HBinaryOperation(DataType::Type result_type,
+  HBinaryOperation(InstructionKind kind,
+                   DataType::Type result_type,
                    HInstruction* left,
                    HInstruction* right,
                    SideEffects side_effects = SideEffects::None(),
                    uint32_t dex_pc = kNoDexPc)
-      : HExpression(result_type, side_effects, dex_pc) {
+      : HExpression(kind, result_type, side_effects, dex_pc) {
     SetRawInputAt(0, left);
     SetRawInputAt(1, right);
   }
@@ -3498,8 +3548,16 @@
 
 class HCondition : public HBinaryOperation {
  public:
-  HCondition(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
-      : HBinaryOperation(DataType::Type::kBool, first, second, SideEffects::None(), dex_pc) {
+  HCondition(InstructionKind kind,
+             HInstruction* first,
+             HInstruction* second,
+             uint32_t dex_pc = kNoDexPc)
+      : HBinaryOperation(kind,
+                         DataType::Type::kBool,
+                         first,
+                         second,
+                         SideEffects::None(),
+                         dex_pc) {
     SetPackedField<ComparisonBiasField>(ComparisonBias::kNoBias);
   }
 
@@ -3579,7 +3637,8 @@
 class HEqual FINAL : public HCondition {
  public:
   HEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
-      : HCondition(first, second, dex_pc) {}
+      : HCondition(kEqual, first, second, dex_pc) {
+  }
 
   bool IsCommutative() const OVERRIDE { return true; }
 
@@ -3623,8 +3682,10 @@
 
 class HNotEqual FINAL : public HCondition {
  public:
-  HNotEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
-      : HCondition(first, second, dex_pc) {}
+  HNotEqual(HInstruction* first, HInstruction* second,
+            uint32_t dex_pc = kNoDexPc)
+      : HCondition(kNotEqual, first, second, dex_pc) {
+  }
 
   bool IsCommutative() const OVERRIDE { return true; }
 
@@ -3667,8 +3728,10 @@
 
 class HLessThan FINAL : public HCondition {
  public:
-  HLessThan(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
-      : HCondition(first, second, dex_pc) {}
+  HLessThan(HInstruction* first, HInstruction* second,
+            uint32_t dex_pc = kNoDexPc)
+      : HCondition(kLessThan, first, second, dex_pc) {
+  }
 
   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
@@ -3705,8 +3768,10 @@
 
 class HLessThanOrEqual FINAL : public HCondition {
  public:
-  HLessThanOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
-      : HCondition(first, second, dex_pc) {}
+  HLessThanOrEqual(HInstruction* first, HInstruction* second,
+                   uint32_t dex_pc = kNoDexPc)
+      : HCondition(kLessThanOrEqual, first, second, dex_pc) {
+  }
 
   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
@@ -3744,7 +3809,8 @@
 class HGreaterThan FINAL : public HCondition {
  public:
   HGreaterThan(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
-      : HCondition(first, second, dex_pc) {}
+      : HCondition(kGreaterThan, first, second, dex_pc) {
+  }
 
   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
@@ -3782,7 +3848,8 @@
 class HGreaterThanOrEqual FINAL : public HCondition {
  public:
   HGreaterThanOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
-      : HCondition(first, second, dex_pc) {}
+      : HCondition(kGreaterThanOrEqual, first, second, dex_pc) {
+  }
 
   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
@@ -3820,7 +3887,8 @@
 class HBelow FINAL : public HCondition {
  public:
   HBelow(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
-      : HCondition(first, second, dex_pc) {}
+      : HCondition(kBelow, first, second, dex_pc) {
+  }
 
   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
@@ -3861,7 +3929,8 @@
 class HBelowOrEqual FINAL : public HCondition {
  public:
   HBelowOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
-      : HCondition(first, second, dex_pc) {}
+      : HCondition(kBelowOrEqual, first, second, dex_pc) {
+  }
 
   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
@@ -3902,7 +3971,8 @@
 class HAbove FINAL : public HCondition {
  public:
   HAbove(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
-      : HCondition(first, second, dex_pc) {}
+      : HCondition(kAbove, first, second, dex_pc) {
+  }
 
   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
@@ -3943,7 +4013,8 @@
 class HAboveOrEqual FINAL : public HCondition {
  public:
   HAboveOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
-      : HCondition(first, second, dex_pc) {}
+      : HCondition(kAboveOrEqual, first, second, dex_pc) {
+  }
 
   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()), GetDexPc());
@@ -3993,7 +4064,8 @@
            HInstruction* second,
            ComparisonBias bias,
            uint32_t dex_pc)
-      : HBinaryOperation(DataType::Type::kInt32,
+      : HBinaryOperation(kCompare,
+                         DataType::Type::kInt32,
                          first,
                          second,
                          SideEffectsForArchRuntimeCalls(comparison_type),
@@ -4079,7 +4151,10 @@
                const DexFile& dex_file,
                bool finalizable,
                QuickEntrypointEnum entrypoint)
-      : HExpression(DataType::Type::kReference, SideEffects::CanTriggerGC(), dex_pc),
+      : HExpression(kNewInstance,
+                    DataType::Type::kReference,
+                    SideEffects::CanTriggerGC(),
+                    dex_pc),
         type_index_(type_index),
         dex_file_(dex_file),
         entrypoint_(entrypoint) {
@@ -4235,7 +4310,8 @@
   using InvokeTypeField = BitField<InvokeType, kFieldInvokeType, kFieldInvokeTypeSize>;
   using ReturnTypeField = BitField<DataType::Type, kFieldReturnType, kFieldReturnTypeSize>;
 
-  HInvoke(ArenaAllocator* allocator,
+  HInvoke(InstructionKind kind,
+          ArenaAllocator* allocator,
           uint32_t number_of_arguments,
           uint32_t number_of_other_inputs,
           DataType::Type return_type,
@@ -4244,6 +4320,7 @@
           ArtMethod* resolved_method,
           InvokeType invoke_type)
     : HVariableInputSizeInstruction(
+          kind,
           SideEffects::AllExceptGCDependency(),  // Assume write/read on all fields/arrays.
           dex_pc,
           allocator,
@@ -4278,7 +4355,8 @@
                     uint32_t dex_pc,
                     uint32_t dex_method_index,
                     InvokeType invoke_type)
-      : HInvoke(allocator,
+      : HInvoke(kInvokeUnresolved,
+                allocator,
                 number_of_arguments,
                 0u /* number_of_other_inputs */,
                 return_type,
@@ -4303,14 +4381,16 @@
                      DataType::Type return_type,
                      uint32_t dex_pc,
                      uint32_t dex_method_index)
-      : HInvoke(allocator,
+      : HInvoke(kInvokePolymorphic,
+                allocator,
                 number_of_arguments,
                 0u /* number_of_other_inputs */,
                 return_type,
                 dex_pc,
                 dex_method_index,
                 nullptr,
-                kVirtual) {}
+                kVirtual) {
+  }
 
   bool IsClonable() const OVERRIDE { return true; }
 
@@ -4387,7 +4467,8 @@
                         InvokeType invoke_type,
                         MethodReference target_method,
                         ClinitCheckRequirement clinit_check_requirement)
-      : HInvoke(allocator,
+      : HInvoke(kInvokeStaticOrDirect,
+                allocator,
                 number_of_arguments,
                 // There is potentially one extra argument for the HCurrentMethod node, and
                 // potentially one other if the clinit check is explicit, and potentially
@@ -4582,7 +4663,8 @@
                  uint32_t dex_method_index,
                  ArtMethod* resolved_method,
                  uint32_t vtable_index)
-      : HInvoke(allocator,
+      : HInvoke(kInvokeVirtual,
+                allocator,
                 number_of_arguments,
                 0u,
                 return_type,
@@ -4590,7 +4672,8 @@
                 dex_method_index,
                 resolved_method,
                 kVirtual),
-        vtable_index_(vtable_index) {}
+        vtable_index_(vtable_index) {
+  }
 
   bool IsClonable() const OVERRIDE { return true; }
 
@@ -4633,7 +4716,8 @@
                    uint32_t dex_method_index,
                    ArtMethod* resolved_method,
                    uint32_t imt_index)
-      : HInvoke(allocator,
+      : HInvoke(kInvokeInterface,
+                allocator,
                 number_of_arguments,
                 0u,
                 return_type,
@@ -4641,7 +4725,8 @@
                 dex_method_index,
                 resolved_method,
                 kInterface),
-        imt_index_(imt_index) {}
+        imt_index_(imt_index) {
+  }
 
   bool IsClonable() const OVERRIDE { return true; }
 
@@ -4670,7 +4755,7 @@
 class HNeg FINAL : public HUnaryOperation {
  public:
   HNeg(DataType::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc)
-      : HUnaryOperation(result_type, input, dex_pc) {
+      : HUnaryOperation(kNeg, result_type, input, dex_pc) {
     DCHECK_EQ(result_type, DataType::Kind(input->GetType()));
   }
 
@@ -4698,7 +4783,7 @@
 class HNewArray FINAL : public HExpression<2> {
  public:
   HNewArray(HInstruction* cls, HInstruction* length, uint32_t dex_pc)
-      : HExpression(DataType::Type::kReference, SideEffects::CanTriggerGC(), dex_pc) {
+      : HExpression(kNewArray, DataType::Type::kReference, SideEffects::CanTriggerGC(), dex_pc) {
     SetRawInputAt(0, cls);
     SetRawInputAt(1, length);
   }
@@ -4734,7 +4819,8 @@
        HInstruction* left,
        HInstruction* right,
        uint32_t dex_pc = kNoDexPc)
-      : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
+      : HBinaryOperation(kAdd, result_type, left, right, SideEffects::None(), dex_pc) {
+  }
 
   bool IsCommutative() const OVERRIDE { return true; }
 
@@ -4769,7 +4855,8 @@
        HInstruction* left,
        HInstruction* right,
        uint32_t dex_pc = kNoDexPc)
-      : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
+      : HBinaryOperation(kSub, result_type, left, right, SideEffects::None(), dex_pc) {
+  }
 
   template <typename T> static T Compute(T x, T y) { return x - y; }
 
@@ -4802,7 +4889,8 @@
        HInstruction* left,
        HInstruction* right,
        uint32_t dex_pc = kNoDexPc)
-      : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
+      : HBinaryOperation(kMul, result_type, left, right, SideEffects::None(), dex_pc) {
+  }
 
   bool IsCommutative() const OVERRIDE { return true; }
 
@@ -4837,7 +4925,8 @@
        HInstruction* left,
        HInstruction* right,
        uint32_t dex_pc)
-      : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
+      : HBinaryOperation(kDiv, result_type, left, right, SideEffects::None(), dex_pc) {
+  }
 
   template <typename T>
   T ComputeIntegral(T x, T y) const {
@@ -4884,7 +4973,8 @@
        HInstruction* left,
        HInstruction* right,
        uint32_t dex_pc)
-      : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
+      : HBinaryOperation(kRem, result_type, left, right, SideEffects::None(), dex_pc) {
+  }
 
   template <typename T>
   T ComputeIntegral(T x, T y) const {
@@ -4930,7 +5020,7 @@
   // `HDivZeroCheck` can trigger GC, as it may call the `ArithmeticException`
   // constructor.
   HDivZeroCheck(HInstruction* value, uint32_t dex_pc)
-      : HExpression(value->GetType(), SideEffects::CanTriggerGC(), dex_pc) {
+      : HExpression(kDivZeroCheck, value->GetType(), SideEffects::CanTriggerGC(), dex_pc) {
     SetRawInputAt(0, value);
   }
 
@@ -4957,7 +5047,7 @@
        HInstruction* value,
        HInstruction* distance,
        uint32_t dex_pc = kNoDexPc)
-      : HBinaryOperation(result_type, value, distance, SideEffects::None(), dex_pc) {
+      : HBinaryOperation(kShl, result_type, value, distance, SideEffects::None(), dex_pc) {
     DCHECK_EQ(result_type, DataType::Kind(value->GetType()));
     DCHECK_EQ(DataType::Type::kInt32, DataType::Kind(distance->GetType()));
   }
@@ -5003,7 +5093,7 @@
        HInstruction* value,
        HInstruction* distance,
        uint32_t dex_pc = kNoDexPc)
-      : HBinaryOperation(result_type, value, distance, SideEffects::None(), dex_pc) {
+      : HBinaryOperation(kShr, result_type, value, distance, SideEffects::None(), dex_pc) {
     DCHECK_EQ(result_type, DataType::Kind(value->GetType()));
     DCHECK_EQ(DataType::Type::kInt32, DataType::Kind(distance->GetType()));
   }
@@ -5049,7 +5139,7 @@
         HInstruction* value,
         HInstruction* distance,
         uint32_t dex_pc = kNoDexPc)
-      : HBinaryOperation(result_type, value, distance, SideEffects::None(), dex_pc) {
+      : HBinaryOperation(kUShr, result_type, value, distance, SideEffects::None(), dex_pc) {
     DCHECK_EQ(result_type, DataType::Kind(value->GetType()));
     DCHECK_EQ(DataType::Type::kInt32, DataType::Kind(distance->GetType()));
   }
@@ -5097,7 +5187,8 @@
        HInstruction* left,
        HInstruction* right,
        uint32_t dex_pc = kNoDexPc)
-      : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
+      : HBinaryOperation(kAnd, result_type, left, right, SideEffects::None(), dex_pc) {
+  }
 
   bool IsCommutative() const OVERRIDE { return true; }
 
@@ -5134,7 +5225,8 @@
       HInstruction* left,
       HInstruction* right,
       uint32_t dex_pc = kNoDexPc)
-      : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
+      : HBinaryOperation(kOr, result_type, left, right, SideEffects::None(), dex_pc) {
+  }
 
   bool IsCommutative() const OVERRIDE { return true; }
 
@@ -5171,7 +5263,8 @@
        HInstruction* left,
        HInstruction* right,
        uint32_t dex_pc = kNoDexPc)
-      : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
+      : HBinaryOperation(kXor, result_type, left, right, SideEffects::None(), dex_pc) {
+  }
 
   bool IsCommutative() const OVERRIDE { return true; }
 
@@ -5205,7 +5298,7 @@
 class HRor FINAL : public HBinaryOperation {
  public:
   HRor(DataType::Type result_type, HInstruction* value, HInstruction* distance)
-    : HBinaryOperation(result_type, value, distance) {
+      : HBinaryOperation(kRor, result_type, value, distance) {
     DCHECK_EQ(result_type, DataType::Kind(value->GetType()));
     DCHECK_EQ(DataType::Type::kInt32, DataType::Kind(distance->GetType()));
   }
@@ -5262,7 +5355,7 @@
                   uint8_t index,
                   DataType::Type parameter_type,
                   bool is_this = false)
-      : HExpression(parameter_type, SideEffects::None(), kNoDexPc),
+      : HExpression(kParameterValue, parameter_type, SideEffects::None(), kNoDexPc),
         dex_file_(dex_file),
         type_index_(type_index),
         index_(index) {
@@ -5301,7 +5394,8 @@
 class HNot FINAL : public HUnaryOperation {
  public:
   HNot(DataType::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc)
-      : HUnaryOperation(result_type, input, dex_pc) {}
+      : HUnaryOperation(kNot, result_type, input, dex_pc) {
+  }
 
   bool CanBeMoved() const OVERRIDE { return true; }
   bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
@@ -5334,7 +5428,8 @@
 class HBooleanNot FINAL : public HUnaryOperation {
  public:
   explicit HBooleanNot(HInstruction* input, uint32_t dex_pc = kNoDexPc)
-      : HUnaryOperation(DataType::Type::kBool, input, dex_pc) {}
+      : HUnaryOperation(kBooleanNot, DataType::Type::kBool, input, dex_pc) {
+  }
 
   bool CanBeMoved() const OVERRIDE { return true; }
   bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
@@ -5372,7 +5467,7 @@
  public:
   // Instantiate a type conversion of `input` to `result_type`.
   HTypeConversion(DataType::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc)
-      : HExpression(result_type, SideEffects::None(), dex_pc) {
+      : HExpression(kTypeConversion, result_type, SideEffects::None(), dex_pc) {
     SetRawInputAt(0, input);
     // Invariant: We should never generate a conversion to a Boolean value.
     DCHECK_NE(DataType::Type::kBool, result_type);
@@ -5404,7 +5499,7 @@
   // `HNullCheck` can trigger GC, as it may call the `NullPointerException`
   // constructor.
   HNullCheck(HInstruction* value, uint32_t dex_pc)
-      : HExpression(value->GetType(), SideEffects::CanTriggerGC(), dex_pc) {
+      : HExpression(kNullCheck, value->GetType(), SideEffects::CanTriggerGC(), dex_pc) {
     SetRawInputAt(0, value);
   }
 
@@ -5474,7 +5569,10 @@
                     uint16_t declaring_class_def_index,
                     const DexFile& dex_file,
                     uint32_t dex_pc)
-      : HExpression(field_type, SideEffects::FieldReadOfType(field_type, is_volatile), dex_pc),
+      : HExpression(kInstanceFieldGet,
+                    field_type,
+                    SideEffects::FieldReadOfType(field_type, is_volatile),
+                    dex_pc),
         field_info_(field,
                     field_offset,
                     field_type,
@@ -5534,7 +5632,9 @@
                     uint16_t declaring_class_def_index,
                     const DexFile& dex_file,
                     uint32_t dex_pc)
-      : HTemplateInstruction(SideEffects::FieldWriteOfType(field_type, is_volatile), dex_pc),
+      : HTemplateInstruction(kInstanceFieldSet,
+                             SideEffects::FieldWriteOfType(field_type, is_volatile),
+                             dex_pc),
         field_info_(field,
                     field_offset,
                     field_type,
@@ -5586,7 +5686,8 @@
                  type,
                  SideEffects::ArrayReadOfType(type),
                  dex_pc,
-                 /* is_string_char_at */ false) {}
+                 /* is_string_char_at */ false) {
+  }
 
   HArrayGet(HInstruction* array,
             HInstruction* index,
@@ -5594,7 +5695,7 @@
             SideEffects side_effects,
             uint32_t dex_pc,
             bool is_string_char_at)
-      : HExpression(type, side_effects, dex_pc) {
+      : HExpression(kArrayGet, type, side_effects, dex_pc) {
     SetPackedFlag<kFlagIsStringCharAt>(is_string_char_at);
     SetRawInputAt(0, array);
     SetRawInputAt(1, index);
@@ -5678,7 +5779,8 @@
                   expected_component_type,
                   // Make a best guess for side effects now, may be refined during SSA building.
                   ComputeSideEffects(GetComponentType(value->GetType(), expected_component_type)),
-                  dex_pc) {}
+                  dex_pc) {
+  }
 
   HArraySet(HInstruction* array,
             HInstruction* index,
@@ -5686,7 +5788,7 @@
             DataType::Type expected_component_type,
             SideEffects side_effects,
             uint32_t dex_pc)
-      : HTemplateInstruction(side_effects, dex_pc) {
+      : HTemplateInstruction(kArraySet, side_effects, dex_pc) {
     SetPackedField<ExpectedComponentTypeField>(expected_component_type);
     SetPackedFlag<kFlagNeedsTypeCheck>(value->GetType() == DataType::Type::kReference);
     SetPackedFlag<kFlagValueCanBeNull>(true);
@@ -5786,7 +5888,7 @@
 class HArrayLength FINAL : public HExpression<1> {
  public:
   HArrayLength(HInstruction* array, uint32_t dex_pc, bool is_string_length = false)
-      : HExpression(DataType::Type::kInt32, SideEffects::None(), dex_pc) {
+      : HExpression(kArrayLength, DataType::Type::kInt32, SideEffects::None(), dex_pc) {
     SetPackedFlag<kFlagIsStringLength>(is_string_length);
     // Note that arrays do not change length, so the instruction does not
     // depend on any write.
@@ -5829,7 +5931,7 @@
                HInstruction* length,
                uint32_t dex_pc,
                bool is_string_char_at = false)
-      : HExpression(index->GetType(), SideEffects::CanTriggerGC(), dex_pc) {
+      : HExpression(kBoundsCheck, index->GetType(), SideEffects::CanTriggerGC(), dex_pc) {
     DCHECK_EQ(DataType::Type::kInt32, DataType::Kind(index->GetType()));
     SetPackedFlag<kFlagIsStringCharAt>(is_string_char_at);
     SetRawInputAt(0, index);
@@ -5862,7 +5964,9 @@
 class HSuspendCheck FINAL : public HTemplateInstruction<0> {
  public:
   explicit HSuspendCheck(uint32_t dex_pc = kNoDexPc)
-      : HTemplateInstruction(SideEffects::CanTriggerGC(), dex_pc), slow_path_(nullptr) {}
+      : HTemplateInstruction(kSuspendCheck, SideEffects::CanTriggerGC(), dex_pc),
+        slow_path_(nullptr) {
+  }
 
   bool IsClonable() const OVERRIDE { return true; }
 
@@ -5889,7 +5993,8 @@
 class HNativeDebugInfo : public HTemplateInstruction<0> {
  public:
   explicit HNativeDebugInfo(uint32_t dex_pc)
-      : HTemplateInstruction<0>(SideEffects::None(), dex_pc) {}
+      : HTemplateInstruction<0>(kNativeDebugInfo, SideEffects::None(), dex_pc) {
+  }
 
   bool NeedsEnvironment() const OVERRIDE {
     return true;
@@ -5947,7 +6052,7 @@
              bool is_referrers_class,
              uint32_t dex_pc,
              bool needs_access_check)
-      : HInstruction(SideEffectsForArchRuntimeCalls(), dex_pc),
+      : HInstruction(kLoadClass, SideEffectsForArchRuntimeCalls(), dex_pc),
         special_input_(HUserRecord<HInstruction*>(current_method)),
         type_index_(type_index),
         dex_file_(dex_file),
@@ -6163,7 +6268,7 @@
               dex::StringIndex string_index,
               const DexFile& dex_file,
               uint32_t dex_pc)
-      : HInstruction(SideEffectsForArchRuntimeCalls(), dex_pc),
+      : HInstruction(kLoadString, SideEffectsForArchRuntimeCalls(), dex_pc),
         special_input_(HUserRecord<HInstruction*>(current_method)),
         string_index_(string_index),
         dex_file_(dex_file) {
@@ -6300,6 +6405,7 @@
  public:
   HClinitCheck(HLoadClass* constant, uint32_t dex_pc)
       : HExpression(
+            kClinitCheck,
             DataType::Type::kReference,
             SideEffects::AllExceptGCDependency(),  // Assume write/read on all fields/arrays.
             dex_pc) {
@@ -6342,7 +6448,10 @@
                   uint16_t declaring_class_def_index,
                   const DexFile& dex_file,
                   uint32_t dex_pc)
-      : HExpression(field_type, SideEffects::FieldReadOfType(field_type, is_volatile), dex_pc),
+      : HExpression(kStaticFieldGet,
+                    field_type,
+                    SideEffects::FieldReadOfType(field_type, is_volatile),
+                    dex_pc),
         field_info_(field,
                     field_offset,
                     field_type,
@@ -6399,7 +6508,9 @@
                   uint16_t declaring_class_def_index,
                   const DexFile& dex_file,
                   uint32_t dex_pc)
-      : HTemplateInstruction(SideEffects::FieldWriteOfType(field_type, is_volatile), dex_pc),
+      : HTemplateInstruction(kStaticFieldSet,
+                             SideEffects::FieldWriteOfType(field_type, is_volatile),
+                             dex_pc),
         field_info_(field,
                     field_offset,
                     field_type,
@@ -6442,7 +6553,10 @@
                               DataType::Type field_type,
                               uint32_t field_index,
                               uint32_t dex_pc)
-      : HExpression(field_type, SideEffects::AllExceptGCDependency(), dex_pc),
+      : HExpression(kUnresolvedInstanceFieldGet,
+                    field_type,
+                    SideEffects::AllExceptGCDependency(),
+                    dex_pc),
         field_index_(field_index) {
     SetRawInputAt(0, obj);
   }
@@ -6470,7 +6584,9 @@
                               DataType::Type field_type,
                               uint32_t field_index,
                               uint32_t dex_pc)
-      : HTemplateInstruction(SideEffects::AllExceptGCDependency(), dex_pc),
+      : HTemplateInstruction(kUnresolvedInstanceFieldSet,
+                             SideEffects::AllExceptGCDependency(),
+                             dex_pc),
         field_index_(field_index) {
     SetPackedField<FieldTypeField>(field_type);
     DCHECK_EQ(DataType::Kind(field_type), DataType::Kind(value->GetType()));
@@ -6508,7 +6624,10 @@
   HUnresolvedStaticFieldGet(DataType::Type field_type,
                             uint32_t field_index,
                             uint32_t dex_pc)
-      : HExpression(field_type, SideEffects::AllExceptGCDependency(), dex_pc),
+      : HExpression(kUnresolvedStaticFieldGet,
+                    field_type,
+                    SideEffects::AllExceptGCDependency(),
+                    dex_pc),
         field_index_(field_index) {
   }
 
@@ -6534,7 +6653,9 @@
                             DataType::Type field_type,
                             uint32_t field_index,
                             uint32_t dex_pc)
-      : HTemplateInstruction(SideEffects::AllExceptGCDependency(), dex_pc),
+      : HTemplateInstruction(kUnresolvedStaticFieldSet,
+                             SideEffects::AllExceptGCDependency(),
+                             dex_pc),
         field_index_(field_index) {
     SetPackedField<FieldTypeField>(field_type);
     DCHECK_EQ(DataType::Kind(field_type), DataType::Kind(value->GetType()));
@@ -6570,7 +6691,8 @@
 class HLoadException FINAL : public HExpression<0> {
  public:
   explicit HLoadException(uint32_t dex_pc = kNoDexPc)
-      : HExpression(DataType::Type::kReference, SideEffects::None(), dex_pc) {}
+      : HExpression(kLoadException, DataType::Type::kReference, SideEffects::None(), dex_pc) {
+  }
 
   bool CanBeNull() const OVERRIDE { return false; }
 
@@ -6585,7 +6707,8 @@
 class HClearException FINAL : public HTemplateInstruction<0> {
  public:
   explicit HClearException(uint32_t dex_pc = kNoDexPc)
-      : HTemplateInstruction(SideEffects::AllWrites(), dex_pc) {}
+      : HTemplateInstruction(kClearException, SideEffects::AllWrites(), dex_pc) {
+  }
 
   DECLARE_INSTRUCTION(ClearException);
 
@@ -6596,7 +6719,7 @@
 class HThrow FINAL : public HTemplateInstruction<1> {
  public:
   HThrow(HInstruction* exception, uint32_t dex_pc)
-      : HTemplateInstruction(SideEffects::CanTriggerGC(), dex_pc) {
+      : HTemplateInstruction(kThrow, SideEffects::CanTriggerGC(), dex_pc) {
     SetRawInputAt(0, exception);
   }
 
@@ -6637,7 +6760,8 @@
               HLoadClass* target_class,
               TypeCheckKind check_kind,
               uint32_t dex_pc)
-      : HExpression(DataType::Type::kBool,
+      : HExpression(kInstanceOf,
+                    DataType::Type::kBool,
                     SideEffectsForArchRuntimeCalls(check_kind),
                     dex_pc) {
     SetPackedField<TypeCheckKindField>(check_kind);
@@ -6696,7 +6820,7 @@
 class HBoundType FINAL : public HExpression<1> {
  public:
   explicit HBoundType(HInstruction* input, uint32_t dex_pc = kNoDexPc)
-      : HExpression(DataType::Type::kReference, SideEffects::None(), dex_pc),
+      : HExpression(kBoundType, DataType::Type::kReference, SideEffects::None(), dex_pc),
         upper_bound_(ReferenceTypeInfo::CreateInvalid()) {
     SetPackedFlag<kFlagUpperCanBeNull>(true);
     SetPackedFlag<kFlagCanBeNull>(true);
@@ -6746,7 +6870,7 @@
              HLoadClass* target_class,
              TypeCheckKind check_kind,
              uint32_t dex_pc)
-      : HTemplateInstruction(SideEffects::CanTriggerGC(), dex_pc) {
+      : HTemplateInstruction(kCheckCast, SideEffects::CanTriggerGC(), dex_pc) {
     SetPackedField<TypeCheckKindField>(check_kind);
     SetPackedFlag<kFlagMustDoNullCheck>(true);
     SetRawInputAt(0, object);
@@ -6823,7 +6947,9 @@
  public:
   explicit HMemoryBarrier(MemBarrierKind barrier_kind, uint32_t dex_pc = kNoDexPc)
       : HTemplateInstruction(
-            SideEffects::AllWritesAndReads(), dex_pc) {  // Assume write/read on all fields/arrays.
+            kMemoryBarrier,
+            SideEffects::AllWritesAndReads(),  // Assume write/read on all fields/arrays.
+            dex_pc) {
     SetPackedField<BarrierKindField>(barrier_kind);
   }
 
@@ -6942,7 +7068,8 @@
     //
     // If in a later phase we discover that there are no writes to reference final fields,
     // we can refine the side effect to a smaller set of type reads (see above constraints).
-      : HVariableInputSizeInstruction(SideEffects::AllReads(),
+      : HVariableInputSizeInstruction(kConstructorFence,
+                                      SideEffects::AllReads(),
                                       dex_pc,
                                       allocator,
                                       /* number_of_inputs */ 1,
@@ -7009,6 +7136,7 @@
 
   HMonitorOperation(HInstruction* object, OperationKind kind, uint32_t dex_pc)
     : HTemplateInstruction(
+          kMonitorOperation,
           SideEffects::AllExceptGCDependency(),  // Assume write/read on all fields/arrays.
           dex_pc) {
     SetPackedField<OperationKindField>(kind);
@@ -7050,7 +7178,7 @@
           HInstruction* true_value,
           HInstruction* false_value,
           uint32_t dex_pc)
-      : HExpression(HPhi::ToPhiType(true_value->GetType()), SideEffects::None(), dex_pc) {
+      : HExpression(kSelect, HPhi::ToPhiType(true_value->GetType()), SideEffects::None(), dex_pc) {
     DCHECK_EQ(HPhi::ToPhiType(true_value->GetType()), HPhi::ToPhiType(false_value->GetType()));
 
     // First input must be `true_value` or `false_value` to allow codegens to
@@ -7163,7 +7291,7 @@
 class HParallelMove FINAL : public HTemplateInstruction<0> {
  public:
   explicit HParallelMove(ArenaAllocator* allocator, uint32_t dex_pc = kNoDexPc)
-      : HTemplateInstruction(SideEffects::None(), dex_pc),
+      : HTemplateInstruction(kParallelMove, SideEffects::None(), dex_pc),
         moves_(allocator->Adapter(kArenaAllocMoveOperands)) {
     moves_.reserve(kDefaultNumberOfMoves);
   }
@@ -7225,7 +7353,10 @@
 class HIntermediateAddress FINAL : public HExpression<2> {
  public:
   HIntermediateAddress(HInstruction* base_address, HInstruction* offset, uint32_t dex_pc)
-      : HExpression(DataType::Type::kInt32, SideEffects::DependsOnGC(), dex_pc) {
+      : HExpression(kIntermediateAddress,
+                    DataType::Type::kInt32,
+                    SideEffects::DependsOnGC(),
+                    dex_pc) {
         DCHECK_EQ(DataType::Size(DataType::Type::kInt32),
                   DataType::Size(DataType::Type::kReference))
             << "kPrimInt and kPrimNot have different sizes.";