Create list of intrinsics with specialized HIR.

Split the intrinsics list to differentiate intrinsics with
and without HIR. Eliminate unreachable intrinsic functions
for intrinsics with HIR.

Test: m test-art-host-gtest
Test: restrunner.py --host --optimizing
Bug: 319045458
Change-Id: I6144ef6b6ec547c30f2911c41125a1f07f6f6d50
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc
index e8c94dd..8f2f253 100644
--- a/compiler/optimizing/graph_checker.cc
+++ b/compiler/optimizing/graph_checker.cc
@@ -27,6 +27,7 @@
 #include "base/scoped_arena_containers.h"
 #include "code_generator.h"
 #include "handle.h"
+#include "intrinsics.h"
 #include "mirror/class.h"
 #include "nodes.h"
 #include "obj_ptr-inl.h"
@@ -738,50 +739,21 @@
 
   // Check for intrinsics which should have been replaced by intermediate representation in the
   // instruction builder.
-  switch (invoke->GetIntrinsic()) {
-    case Intrinsics::kIntegerRotateRight:
-    case Intrinsics::kLongRotateRight:
-    case Intrinsics::kIntegerRotateLeft:
-    case Intrinsics::kLongRotateLeft:
-    case Intrinsics::kIntegerCompare:
-    case Intrinsics::kLongCompare:
-    case Intrinsics::kIntegerSignum:
-    case Intrinsics::kLongSignum:
-    case Intrinsics::kFloatIsNaN:
-    case Intrinsics::kDoubleIsNaN:
-    case Intrinsics::kStringIsEmpty:
-    case Intrinsics::kUnsafeLoadFence:
-    case Intrinsics::kUnsafeStoreFence:
-    case Intrinsics::kUnsafeFullFence:
-    case Intrinsics::kJdkUnsafeLoadFence:
-    case Intrinsics::kJdkUnsafeStoreFence:
-    case Intrinsics::kJdkUnsafeFullFence:
-    case Intrinsics::kVarHandleFullFence:
-    case Intrinsics::kVarHandleAcquireFence:
-    case Intrinsics::kVarHandleReleaseFence:
-    case Intrinsics::kVarHandleLoadLoadFence:
-    case Intrinsics::kVarHandleStoreStoreFence:
-    case Intrinsics::kMathMinIntInt:
-    case Intrinsics::kMathMinLongLong:
-    case Intrinsics::kMathMinFloatFloat:
-    case Intrinsics::kMathMinDoubleDouble:
-    case Intrinsics::kMathMaxIntInt:
-    case Intrinsics::kMathMaxLongLong:
-    case Intrinsics::kMathMaxFloatFloat:
-    case Intrinsics::kMathMaxDoubleDouble:
-    case Intrinsics::kMathAbsInt:
-    case Intrinsics::kMathAbsLong:
-    case Intrinsics::kMathAbsFloat:
-    case Intrinsics::kMathAbsDouble:
-      AddError(
-          StringPrintf("The graph contains an instrinsic which should have been replaced in the "
-                       "instruction builder: %s:%d in block %d.",
-                       invoke->DebugName(),
-                       invoke->GetId(),
-                       invoke->GetBlock()->GetBlockId()));
-      break;
-    default:
-      break;
+  if (IsIntrinsicWithSpecializedHir(invoke->GetIntrinsic()) &&
+      // FIXME: The inliner can currently create graphs with any of the intrinsics with HIR.
+      // However, we are able to compensate for `StringCharAt` and `StringLength` in the
+      // `HInstructionSimplifier`, so we're allowing these two intrinsics for now, preserving
+      // the old behavior. Besides fixing the bug, we should also clean up the simplifier
+      // and remove `SimplifyStringCharAt` and `SimplifyStringLength`. Bug: 319045458
+      invoke->GetIntrinsic() != Intrinsics::kStringCharAt &&
+      invoke->GetIntrinsic() != Intrinsics::kStringLength) {
+    AddError(
+        StringPrintf("The graph contains the instrinsic %d which should have been replaced in the "
+                     "instruction builder: %s:%d in block %d.",
+                     enum_cast<int>(invoke->GetIntrinsic()),
+                     invoke->DebugName(),
+                     invoke->GetId(),
+                     invoke->GetBlock()->GetBlockId()));
   }
 }
 
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 23d47c3..ca0a8e8 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -2009,6 +2009,7 @@
       break;
     default:
       // We do not have intermediate representation for other intrinsics.
+      DCHECK(!IsIntrinsicWithSpecializedHir(intrinsic));
       return false;
   }
   DCHECK(instruction != nullptr);
diff --git a/compiler/optimizing/intrinsics.h b/compiler/optimizing/intrinsics.h
index d74d5d2..d14d264 100644
--- a/compiler/optimizing/intrinsics.h
+++ b/compiler/optimizing/intrinsics.h
@@ -45,11 +45,23 @@
     switch (invoke->GetIntrinsic()) {
       case Intrinsics::kNone:
         return;
+
+#define OPTIMIZING_INTRINSICS_WITH_SPECIALIZED_HIR(Name, ...) \
+      case Intrinsics::k ## Name:
+        ART_INTRINSICS_WITH_SPECIALIZED_HIR_LIST(OPTIMIZING_INTRINSICS_WITH_SPECIALIZED_HIR)
+#undef OPTIMIZING_INTRINSICS_WITH_SPECIALIZED_HIR
+        // Note: clang++ can optimize this `switch` to a range check and a virtual dispatch
+        // with indexed load from the vtable using an adjusted `invoke->GetIntrinsic()`
+        // as the index. However, a non-empty `case` causes clang++ to produce much worse
+        // code, so we want to limit this check to debug builds only.
+        DCHECK(false) << "Unexpected intrinsic with HIR: " << invoke->GetIntrinsic();
+        return;
+
 #define OPTIMIZING_INTRINSICS(Name, ...) \
       case Intrinsics::k ## Name: \
         Visit ## Name(invoke);    \
         return;
-        ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
+        ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS)
 #undef OPTIMIZING_INTRINSICS
 
       // Do not put a default case. That way the compiler will complain if we missed a case.
@@ -58,10 +70,10 @@
 
   // Define visitor methods.
 
-#define OPTIMIZING_INTRINSICS(Name, ...) \
-  virtual void Visit##Name([[maybe_unused]] HInvoke* invoke) {}
-  ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
-#undef OPTIMIZING_INTRINSICS
+#define DECLARE_VISIT_INTRINSIC(Name, ...) \
+  virtual void Visit##Name([[maybe_unused]] HInvoke* invoke) = 0;
+  ART_INTRINSICS_WITH_HINVOKE_LIST(DECLARE_VISIT_INTRINSIC)
+#undef DECLARE_VISIT_INTRINSIC
 
   static void MoveArguments(HInvoke* invoke,
                             CodeGenerator* codegen,
@@ -153,6 +165,18 @@
   DISALLOW_COPY_AND_ASSIGN(IntrinsicVisitor);
 };
 
+static inline bool IsIntrinsicWithSpecializedHir(Intrinsics intrinsic) {
+  switch (intrinsic) {
+#define OPTIMIZING_INTRINSICS_WITH_SPECIALIZED_HIR(Name, ...) \
+    case Intrinsics::k ## Name:
+      ART_INTRINSICS_WITH_SPECIALIZED_HIR_LIST(OPTIMIZING_INTRINSICS_WITH_SPECIALIZED_HIR)
+#undef OPTIMIZING_INTRINSICS_WITH_SPECIALIZED_HIR
+      return true;
+    default:
+      return false;
+  }
+}
+
 #define GENERIC_OPTIMIZATION(name, bit)                \
 public:                                                \
 void Set##name() { SetBit(k##name); }                  \
@@ -278,44 +302,8 @@
              << " should have been converted to HIR";                    \
 }
 #define UNREACHABLE_INTRINSICS(Arch)                            \
-UNREACHABLE_INTRINSIC(Arch, MathMinIntInt)                      \
-UNREACHABLE_INTRINSIC(Arch, MathMinLongLong)                    \
-UNREACHABLE_INTRINSIC(Arch, MathMinFloatFloat)                  \
-UNREACHABLE_INTRINSIC(Arch, MathMinDoubleDouble)                \
-UNREACHABLE_INTRINSIC(Arch, MathMaxIntInt)                      \
-UNREACHABLE_INTRINSIC(Arch, MathMaxLongLong)                    \
-UNREACHABLE_INTRINSIC(Arch, MathMaxFloatFloat)                  \
-UNREACHABLE_INTRINSIC(Arch, MathMaxDoubleDouble)                \
-UNREACHABLE_INTRINSIC(Arch, MathAbsInt)                         \
-UNREACHABLE_INTRINSIC(Arch, MathAbsLong)                        \
-UNREACHABLE_INTRINSIC(Arch, MathAbsFloat)                       \
-UNREACHABLE_INTRINSIC(Arch, MathAbsDouble)                      \
 UNREACHABLE_INTRINSIC(Arch, FloatFloatToIntBits)                \
-UNREACHABLE_INTRINSIC(Arch, DoubleDoubleToLongBits)             \
-UNREACHABLE_INTRINSIC(Arch, FloatIsNaN)                         \
-UNREACHABLE_INTRINSIC(Arch, DoubleIsNaN)                        \
-UNREACHABLE_INTRINSIC(Arch, IntegerRotateLeft)                  \
-UNREACHABLE_INTRINSIC(Arch, LongRotateLeft)                     \
-UNREACHABLE_INTRINSIC(Arch, IntegerRotateRight)                 \
-UNREACHABLE_INTRINSIC(Arch, LongRotateRight)                    \
-UNREACHABLE_INTRINSIC(Arch, IntegerCompare)                     \
-UNREACHABLE_INTRINSIC(Arch, LongCompare)                        \
-UNREACHABLE_INTRINSIC(Arch, IntegerSignum)                      \
-UNREACHABLE_INTRINSIC(Arch, LongSignum)                         \
-UNREACHABLE_INTRINSIC(Arch, StringCharAt)                       \
-UNREACHABLE_INTRINSIC(Arch, StringIsEmpty)                      \
-UNREACHABLE_INTRINSIC(Arch, StringLength)                       \
-UNREACHABLE_INTRINSIC(Arch, UnsafeLoadFence)                    \
-UNREACHABLE_INTRINSIC(Arch, UnsafeStoreFence)                   \
-UNREACHABLE_INTRINSIC(Arch, UnsafeFullFence)                    \
-UNREACHABLE_INTRINSIC(Arch, JdkUnsafeLoadFence)                 \
-UNREACHABLE_INTRINSIC(Arch, JdkUnsafeStoreFence)                \
-UNREACHABLE_INTRINSIC(Arch, JdkUnsafeFullFence)                 \
-UNREACHABLE_INTRINSIC(Arch, VarHandleFullFence)                 \
-UNREACHABLE_INTRINSIC(Arch, VarHandleAcquireFence)              \
-UNREACHABLE_INTRINSIC(Arch, VarHandleReleaseFence)              \
-UNREACHABLE_INTRINSIC(Arch, VarHandleLoadLoadFence)             \
-UNREACHABLE_INTRINSIC(Arch, VarHandleStoreStoreFence)
+UNREACHABLE_INTRINSIC(Arch, DoubleDoubleToLongBits)
 
 template <typename IntrinsicLocationsBuilder, typename Codegenerator>
 bool IsCallFreeIntrinsic(HInvoke* invoke, Codegenerator* codegen) {
diff --git a/compiler/optimizing/intrinsics_arm64.h b/compiler/optimizing/intrinsics_arm64.h
index 50e2e43..d103caf 100644
--- a/compiler/optimizing/intrinsics_arm64.h
+++ b/compiler/optimizing/intrinsics_arm64.h
@@ -48,7 +48,7 @@
 
 #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
   void Visit ## Name(HInvoke* invoke) override;
-  ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
+  ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS)
 #undef OPTIMIZING_INTRINSICS
 
   // Check whether an invoke is an intrinsic, and if so, create a location summary. Returns whether
@@ -71,7 +71,7 @@
 
 #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
   void Visit ## Name(HInvoke* invoke) override;
-  ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
+  ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS)
 #undef OPTIMIZING_INTRINSICS
 
  private:
diff --git a/compiler/optimizing/intrinsics_arm_vixl.h b/compiler/optimizing/intrinsics_arm_vixl.h
index fd86866..7dcb524 100644
--- a/compiler/optimizing/intrinsics_arm_vixl.h
+++ b/compiler/optimizing/intrinsics_arm_vixl.h
@@ -37,7 +37,7 @@
 
 #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
   void Visit ## Name(HInvoke* invoke) override;
-  ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
+  ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS)
 #undef OPTIMIZING_INTRINSICS
 
   // Check whether an invoke is an intrinsic, and if so, create a location summary. Returns whether
@@ -62,7 +62,7 @@
 
 #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
   void Visit ## Name(HInvoke* invoke) override;
-  ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
+  ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS)
 #undef OPTIMIZING_INTRINSICS
 
  private:
diff --git a/compiler/optimizing/intrinsics_riscv64.h b/compiler/optimizing/intrinsics_riscv64.h
index 8160c05..43068c0 100644
--- a/compiler/optimizing/intrinsics_riscv64.h
+++ b/compiler/optimizing/intrinsics_riscv64.h
@@ -42,7 +42,7 @@
 
 #define OPTIMIZING_INTRINSICS(Name, ...) \
   void Visit##Name(HInvoke* invoke) override;
-  ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
+  ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS)
 #undef OPTIMIZING_INTRINSICS
 
   // Check whether an invoke is an intrinsic, and if so, create a location summary. Returns whether
@@ -65,7 +65,7 @@
 
 #define OPTIMIZING_INTRINSICS(Name, ...) \
   void Visit##Name(HInvoke* invoke);
-  ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
+  ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS)
 #undef OPTIMIZING_INTRINSICS
 
  private:
diff --git a/compiler/optimizing/intrinsics_x86.h b/compiler/optimizing/intrinsics_x86.h
index 289a3c3..565a92a 100644
--- a/compiler/optimizing/intrinsics_x86.h
+++ b/compiler/optimizing/intrinsics_x86.h
@@ -40,7 +40,7 @@
 
 #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
   void Visit ## Name(HInvoke* invoke) override;
-  ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
+  ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS)
 #undef OPTIMIZING_INTRINSICS
 
   // Check whether an invoke is an intrinsic, and if so, create a location summary. Returns whether
@@ -63,7 +63,7 @@
 
 #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
   void Visit ## Name(HInvoke* invoke) override;
-  ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
+  ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS)
 #undef OPTIMIZING_INTRINSICS
 
  private:
diff --git a/compiler/optimizing/intrinsics_x86_64.h b/compiler/optimizing/intrinsics_x86_64.h
index 4a76c5c..704fa9b 100644
--- a/compiler/optimizing/intrinsics_x86_64.h
+++ b/compiler/optimizing/intrinsics_x86_64.h
@@ -40,7 +40,7 @@
 
 #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
   void Visit ## Name(HInvoke* invoke) override;
-  ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
+  ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS)
 #undef OPTIMIZING_INTRINSICS
 
   // Check whether an invoke is an intrinsic, and if so, create a location summary. Returns whether
@@ -63,7 +63,7 @@
 
 #define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironmentOrCache, SideEffects, Exceptions, ...) \
   void Visit ## Name(HInvoke* invoke) override;
-  ART_INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
+  ART_INTRINSICS_WITH_HINVOKE_LIST(OPTIMIZING_INTRINSICS)
 #undef OPTIMIZING_INTRINSICS
 
  private:
diff --git a/runtime/intrinsics_list.h b/runtime/intrinsics_list.h
index d931c26..d6fa39f 100644
--- a/runtime/intrinsics_list.h
+++ b/runtime/intrinsics_list.h
@@ -83,49 +83,23 @@
   V(VarHandleWeakCompareAndSetPlain, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "weakCompareAndSetPlain", "([Ljava/lang/Object;)Z") \
   V(VarHandleWeakCompareAndSetRelease, kPolymorphic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/invoke/VarHandle;", "weakCompareAndSetRelease", "([Ljava/lang/Object;)Z")
 
-// The complete list of intrinsics.
-#define ART_INTRINSICS_LIST(V) \
-  V(DoubleDoubleToRawLongBits, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "doubleToRawLongBits", "(D)J") \
-  V(DoubleDoubleToLongBits, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "doubleToLongBits", "(D)J") \
-  V(DoubleIsInfinite, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "isInfinite", "(D)Z") \
+// Intrinics that have specialized intermediate representation in the compiler
+// and therefore should never be recorded in a generic `HInvoke`.
+#define ART_INTRINSICS_WITH_SPECIALIZED_HIR_LIST(V) \
   V(DoubleIsNaN, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "isNaN", "(D)Z") \
-  V(DoubleLongBitsToDouble, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "longBitsToDouble", "(J)D") \
-  V(FloatFloatToRawIntBits, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "floatToRawIntBits", "(F)I") \
-  V(FloatFloatToIntBits, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "floatToIntBits", "(F)I") \
-  V(FloatIsInfinite, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "isInfinite", "(F)Z") \
   V(FloatIsNaN, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "isNaN", "(F)Z") \
-  V(FloatIntBitsToFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "intBitsToFloat", "(I)F") \
-  V(IntegerReverse, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "reverse", "(I)I") \
-  V(IntegerReverseBytes, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "reverseBytes", "(I)I") \
-  V(IntegerBitCount, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "bitCount", "(I)I") \
   V(IntegerCompare, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "compare", "(II)I") \
-  V(IntegerDivideUnsigned, kStatic, kNeedsEnvironment, kNoSideEffects, kCanThrow, "Ljava/lang/Integer;", "divideUnsigned", "(II)I") \
-  V(IntegerHighestOneBit, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "highestOneBit", "(I)I") \
-  V(IntegerLowestOneBit, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "lowestOneBit", "(I)I") \
-  V(IntegerNumberOfLeadingZeros, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "numberOfLeadingZeros", "(I)I") \
-  V(IntegerNumberOfTrailingZeros, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "numberOfTrailingZeros", "(I)I") \
   V(IntegerRotateRight, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "rotateRight", "(II)I") \
   V(IntegerRotateLeft, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "rotateLeft", "(II)I") \
   V(IntegerSignum, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "signum", "(I)I") \
-  V(LongReverse, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "reverse", "(J)J") \
-  V(LongReverseBytes, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "reverseBytes", "(J)J") \
-  V(LongBitCount, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "bitCount", "(J)I") \
   V(LongCompare, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "compare", "(JJ)I") \
-  V(LongDivideUnsigned, kStatic, kNeedsEnvironment, kNoSideEffects, kCanThrow, "Ljava/lang/Long;", "divideUnsigned", "(JJ)J") \
-  V(LongHighestOneBit, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "highestOneBit", "(J)J") \
-  V(LongLowestOneBit, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "lowestOneBit", "(J)J") \
-  V(LongNumberOfLeadingZeros, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "numberOfLeadingZeros", "(J)I") \
-  V(LongNumberOfTrailingZeros, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "numberOfTrailingZeros", "(J)I") \
   V(LongRotateRight, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "rotateRight", "(JI)J") \
   V(LongRotateLeft, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "rotateLeft", "(JI)J") \
   V(LongSignum, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "signum", "(J)I") \
-  V(ShortReverseBytes, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Short;", "reverseBytes", "(S)S") \
   V(MathAbsDouble, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(D)D") \
   V(MathAbsFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(F)F") \
   V(MathAbsLong, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(J)J") \
   V(MathAbsInt, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "abs", "(I)I") \
-  V(MathFmaDouble, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "fma", "(DDD)D") \
-  V(MathFmaFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "fma", "(FFF)F") \
   V(MathMinDoubleDouble, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(DD)D") \
   V(MathMinFloatFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(FF)F") \
   V(MathMinLongLong, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "min", "(JJ)J") \
@@ -134,6 +108,50 @@
   V(MathMaxFloatFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(FF)F") \
   V(MathMaxLongLong, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(JJ)J") \
   V(MathMaxIntInt, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "max", "(II)I") \
+  V(StringCharAt, kVirtual, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "charAt", "(I)C") \
+  V(StringIsEmpty, kVirtual, kNeedsEnvironment, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "isEmpty", "()Z") \
+  V(StringLength, kVirtual, kNeedsEnvironment, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "length", "()I") \
+  V(UnsafeLoadFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "loadFence", "()V") \
+  V(UnsafeStoreFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "storeFence", "()V") \
+  V(UnsafeFullFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "fullFence", "()V") \
+  V(JdkUnsafeLoadFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "loadFence", "()V") \
+  V(JdkUnsafeStoreFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "storeFence", "()V") \
+  V(JdkUnsafeFullFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "fullFence", "()V") \
+  V(VarHandleFullFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "fullFence", "()V") \
+  V(VarHandleAcquireFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "acquireFence", "()V") \
+  V(VarHandleReleaseFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "releaseFence", "()V") \
+  V(VarHandleLoadLoadFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "loadLoadFence", "()V") \
+  V(VarHandleStoreStoreFence, kStatic, kNeedsEnvironment, kReadSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "storeStoreFence", "()V")
+
+// Intrinics without specialized intermediate representation in the compiler, using `HInvoke`.
+#define ART_INTRINSICS_WITH_HINVOKE_LIST(V) \
+  V(DoubleDoubleToRawLongBits, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "doubleToRawLongBits", "(D)J") \
+  V(DoubleDoubleToLongBits, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "doubleToLongBits", "(D)J") \
+  V(DoubleIsInfinite, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "isInfinite", "(D)Z") \
+  V(DoubleLongBitsToDouble, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Double;", "longBitsToDouble", "(J)D") \
+  V(FloatFloatToRawIntBits, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "floatToRawIntBits", "(F)I") \
+  V(FloatFloatToIntBits, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "floatToIntBits", "(F)I") \
+  V(FloatIsInfinite, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "isInfinite", "(F)Z") \
+  V(FloatIntBitsToFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Float;", "intBitsToFloat", "(I)F") \
+  V(IntegerReverse, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "reverse", "(I)I") \
+  V(IntegerReverseBytes, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "reverseBytes", "(I)I") \
+  V(IntegerBitCount, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "bitCount", "(I)I") \
+  V(IntegerDivideUnsigned, kStatic, kNeedsEnvironment, kNoSideEffects, kCanThrow, "Ljava/lang/Integer;", "divideUnsigned", "(II)I") \
+  V(IntegerHighestOneBit, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "highestOneBit", "(I)I") \
+  V(IntegerLowestOneBit, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "lowestOneBit", "(I)I") \
+  V(IntegerNumberOfLeadingZeros, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "numberOfLeadingZeros", "(I)I") \
+  V(IntegerNumberOfTrailingZeros, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "numberOfTrailingZeros", "(I)I") \
+  V(LongReverse, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "reverse", "(J)J") \
+  V(LongReverseBytes, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "reverseBytes", "(J)J") \
+  V(LongBitCount, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "bitCount", "(J)I") \
+  V(LongDivideUnsigned, kStatic, kNeedsEnvironment, kNoSideEffects, kCanThrow, "Ljava/lang/Long;", "divideUnsigned", "(JJ)J") \
+  V(LongHighestOneBit, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "highestOneBit", "(J)J") \
+  V(LongLowestOneBit, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "lowestOneBit", "(J)J") \
+  V(LongNumberOfLeadingZeros, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "numberOfLeadingZeros", "(J)I") \
+  V(LongNumberOfTrailingZeros, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Long;", "numberOfTrailingZeros", "(J)I") \
+  V(ShortReverseBytes, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Short;", "reverseBytes", "(S)S") \
+  V(MathFmaDouble, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "fma", "(DDD)D") \
+  V(MathFmaFloat, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "fma", "(FFF)F") \
   V(MathCos, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "cos", "(D)D") \
   V(MathSin, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "sin", "(D)D") \
   V(MathAcos, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Math;", "acos", "(D)D") \
@@ -184,7 +202,6 @@
   V(FP16LessEquals, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "lessEquals", "(SS)Z") \
   V(FP16Min, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "min", "(SS)S") \
   V(FP16Max, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Llibcore/util/FP16;", "max", "(SS)S") \
-  V(StringCharAt, kVirtual, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "charAt", "(I)C") \
   V(StringCompareTo, kVirtual, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "compareTo", "(Ljava/lang/String;)I") \
   V(StringEquals, kVirtual, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "equals", "(Ljava/lang/Object;)Z") \
   V(StringGetCharsNoCheck, kVirtual, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "getCharsNoCheck", "(II[CI)V") \
@@ -192,8 +209,6 @@
   V(StringIndexOfAfter, kVirtual, kNeedsEnvironment, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "indexOf", "(II)I") \
   V(StringStringIndexOf, kVirtual, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "indexOf", "(Ljava/lang/String;)I") \
   V(StringStringIndexOfAfter, kVirtual, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/lang/String;", "indexOf", "(Ljava/lang/String;I)I") \
-  V(StringIsEmpty, kVirtual, kNeedsEnvironment, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "isEmpty", "()Z") \
-  V(StringLength, kVirtual, kNeedsEnvironment, kReadSideEffects, kNoThrow, "Ljava/lang/String;", "length", "()I") \
   V(StringNewStringFromBytes, kStatic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringFactory;", "newStringFromBytes", "([BIII)Ljava/lang/String;") \
   V(StringNewStringFromChars, kStatic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringFactory;", "newStringFromChars", "(II[C)Ljava/lang/String;") \
   V(StringNewStringFromString, kStatic, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/StringFactory;", "newStringFromString", "(Ljava/lang/String;)Ljava/lang/String;") \
@@ -237,9 +252,6 @@
   V(UnsafeGetAndSetInt, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndSetInt", "(Ljava/lang/Object;JI)I") \
   V(UnsafeGetAndSetLong, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndSetLong", "(Ljava/lang/Object;JJ)J") \
   V(UnsafeGetAndSetObject, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "getAndSetObject", "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;") \
-  V(UnsafeLoadFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "loadFence", "()V") \
-  V(UnsafeStoreFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "storeFence", "()V") \
-  V(UnsafeFullFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Lsun/misc/Unsafe;", "fullFence", "()V") \
   V(JdkUnsafeCASInt, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "compareAndSwapInt", "(Ljava/lang/Object;JII)Z") \
   V(JdkUnsafeCASLong, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z") \
   V(JdkUnsafeCASObject, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "compareAndSwapObject", "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \
@@ -274,17 +286,9 @@
   V(JdkUnsafeGetAndSetInt, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "getAndSetInt", "(Ljava/lang/Object;JI)I") \
   V(JdkUnsafeGetAndSetLong, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "getAndSetLong", "(Ljava/lang/Object;JJ)J") \
   V(JdkUnsafeGetAndSetReference, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "getAndSetReference", "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;") \
-  V(JdkUnsafeLoadFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "loadFence", "()V") \
-  V(JdkUnsafeStoreFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "storeFence", "()V") \
-  V(JdkUnsafeFullFence, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljdk/internal/misc/Unsafe;", "fullFence", "()V") \
   V(ReferenceGetReferent, kDirect, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/ref/Reference;", "getReferent", "()Ljava/lang/Object;") \
   V(ReferenceRefersTo, kVirtual, kNeedsEnvironment, kAllSideEffects, kCanThrow, "Ljava/lang/ref/Reference;", "refersTo", "(Ljava/lang/Object;)Z") \
   V(ThreadInterrupted, kStatic, kNeedsEnvironment, kAllSideEffects, kNoThrow, "Ljava/lang/Thread;", "interrupted", "()Z") \
-  V(VarHandleFullFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "fullFence", "()V") \
-  V(VarHandleAcquireFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "acquireFence", "()V") \
-  V(VarHandleReleaseFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "releaseFence", "()V") \
-  V(VarHandleLoadLoadFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "loadLoadFence", "()V") \
-  V(VarHandleStoreStoreFence, kStatic, kNeedsEnvironment, kReadSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "storeStoreFence", "()V") \
   V(ReachabilityFence, kStatic, kNeedsEnvironment, kWriteSideEffects, kNoThrow, "Ljava/lang/ref/Reference;", "reachabilityFence", "(Ljava/lang/Object;)V") \
   V(CRC32Update, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/util/zip/CRC32;", "update", "(II)I") \
   V(CRC32UpdateBytes, kStatic, kNeedsEnvironment, kReadSideEffects, kCanThrow, "Ljava/util/zip/CRC32;", "updateBytes", "(I[BII)I") \
@@ -295,4 +299,9 @@
   V(IntegerValueOf, kStatic, kNeedsEnvironment, kNoSideEffects, kNoThrow, "Ljava/lang/Integer;", "valueOf", "(I)Ljava/lang/Integer;") \
   ART_SIGNATURE_POLYMORPHIC_INTRINSICS_LIST(V)
 
+// The complete list of intrinsics.
+#define ART_INTRINSICS_LIST(V) \
+  ART_INTRINSICS_WITH_SPECIALIZED_HIR_LIST(V) \
+  ART_INTRINSICS_WITH_HINVOKE_LIST(V)
+
 #endif  // ART_RUNTIME_INTRINSICS_LIST_H_
diff --git a/runtime/oat/image.cc b/runtime/oat/image.cc
index ae602ec..b005cd0 100644
--- a/runtime/oat/image.cc
+++ b/runtime/oat/image.cc
@@ -34,8 +34,8 @@
 namespace art {
 
 const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-// Last change: Add DexCacheSection.
-const uint8_t ImageHeader::kImageVersion[] = { '1', '0', '8', '\0' };
+// Last change: Split intrinsics list - with and without HIR.
+const uint8_t ImageHeader::kImageVersion[] = { '1', '0', '9', '\0' };
 
 ImageHeader::ImageHeader(uint32_t image_reservation_size,
                          uint32_t component_count,