Recognize getClass() in RTP.

Also always keep around the resolved field
in related HInstructions to avoid resolving it again
and again.

Test: test-art-host, 631-checker-get-class

Change-Id: I3bc6be11f3eb175c635e746006f39865947e0669
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index 439e3b6..1d3c5bf 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -1118,7 +1118,66 @@
   VisitCondition(condition);
 }
 
+// Recognize the following pattern:
+// obj.getClass() ==/!= Foo.class
+// And replace it with a constant value if the type of `obj` is statically known.
+static bool RecognizeAndSimplifyClassCheck(HCondition* condition) {
+  HInstruction* input_one = condition->InputAt(0);
+  HInstruction* input_two = condition->InputAt(1);
+  HLoadClass* load_class = input_one->IsLoadClass()
+      ? input_one->AsLoadClass()
+      : input_two->AsLoadClass();
+  if (load_class == nullptr) {
+    return false;
+  }
+
+  ReferenceTypeInfo class_rti = load_class->GetLoadedClassRTI();
+  if (!class_rti.IsValid()) {
+    // Unresolved class.
+    return false;
+  }
+
+  HInstanceFieldGet* field_get = (load_class == input_one)
+      ? input_two->AsInstanceFieldGet()
+      : input_one->AsInstanceFieldGet();
+  if (field_get == nullptr) {
+    return false;
+  }
+
+  HInstruction* receiver = field_get->InputAt(0);
+  ReferenceTypeInfo receiver_type = receiver->GetReferenceTypeInfo();
+  if (!receiver_type.IsExact()) {
+    return false;
+  }
+
+  {
+    ScopedObjectAccess soa(Thread::Current());
+    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+    ArtField* field = class_linker->GetClassRoot(ClassLinker::kJavaLangObject)->GetInstanceField(0);
+    DCHECK_EQ(std::string(field->GetName()), "shadow$_klass_");
+    if (field_get->GetFieldInfo().GetField() != field) {
+      return false;
+    }
+
+    // We can replace the compare.
+    int value = 0;
+    if (receiver_type.IsEqual(class_rti)) {
+      value = condition->IsEqual() ? 1 : 0;
+    } else {
+      value = condition->IsNotEqual() ? 1 : 0;
+    }
+    condition->ReplaceWith(condition->GetBlock()->GetGraph()->GetIntConstant(value));
+    return true;
+  }
+}
+
 void InstructionSimplifierVisitor::VisitCondition(HCondition* condition) {
+  if (condition->IsEqual() || condition->IsNotEqual()) {
+    if (RecognizeAndSimplifyClassCheck(condition)) {
+      return;
+    }
+  }
+
   // Reverse condition if left is constant. Our code generators prefer constant
   // on the right hand side.
   if (condition->GetLeft()->IsConstant() && !condition->GetRight()->IsConstant()) {