Allow devirtualized method to be intrinsified.

For a invocation that's devirtualized to a different method, try
to give intrinsics matching an opportunity before trying to inline it.

Test: run-test on host. 638-checker-inline-cache-intrinsic.
Change-Id: I51f70835db4c07575c58872a64a603a38dbcb89c
diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc
index 7719924..6928b70 100644
--- a/compiler/optimizing/intrinsics.cc
+++ b/compiler/optimizing/intrinsics.cc
@@ -137,7 +137,7 @@
 
     case kVirtual:
       // Call might be devirtualized.
-      return (invoke_type == kVirtual || invoke_type == kDirect);
+      return (invoke_type == kVirtual || invoke_type == kDirect || invoke_type == kInterface);
 
     case kSuper:
     case kInterface:
@@ -148,8 +148,12 @@
   UNREACHABLE();
 }
 
-bool IntrinsicsRecognizer::Recognize(HInvoke* invoke, /*out*/ bool* wrong_invoke_type) {
-  ArtMethod* art_method = invoke->GetResolvedMethod();
+bool IntrinsicsRecognizer::Recognize(HInvoke* invoke,
+                                     ArtMethod* art_method,
+                                     /*out*/ bool* wrong_invoke_type) {
+  if (art_method == nullptr) {
+    art_method = invoke->GetResolvedMethod();
+  }
   *wrong_invoke_type = false;
   if (art_method == nullptr || !art_method->IsIntrinsic()) {
     return false;
@@ -182,7 +186,7 @@
       HInstruction* inst = inst_it.Current();
       if (inst->IsInvoke()) {
         bool wrong_invoke_type = false;
-        if (Recognize(inst->AsInvoke(), &wrong_invoke_type)) {
+        if (Recognize(inst->AsInvoke(), /* art_method */ nullptr, &wrong_invoke_type)) {
           MaybeRecordStat(stats_, MethodCompilationStat::kIntrinsicRecognized);
         } else if (wrong_invoke_type) {
           LOG(WARNING)