Revert "Revert "Do not update the type of something we already know.""

This reverts commit 63107a804ce17db9789051e1fe310d99d1dae1cb.

bug:22116987
Change-Id: I49a376a5bd2073a69babe122ec0d26e5d2f82461
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc
index d7e6bd8..9679d0a 100644
--- a/compiler/optimizing/graph_checker.cc
+++ b/compiler/optimizing/graph_checker.cc
@@ -257,6 +257,7 @@
 }
 
 void GraphChecker::VisitReturn(HReturn* ret) {
+  VisitInstruction(ret);
   if (!ret->GetBlock()->GetSingleSuccessor()->IsExitBlock()) {
     AddError(StringPrintf("%s:%d does not jump to the exit block.",
                           ret->DebugName(),
@@ -265,6 +266,7 @@
 }
 
 void GraphChecker::VisitReturnVoid(HReturnVoid* ret) {
+  VisitInstruction(ret);
   if (!ret->GetBlock()->GetSingleSuccessor()->IsExitBlock()) {
     AddError(StringPrintf("%s:%d does not jump to the exit block.",
                           ret->DebugName(),
@@ -272,6 +274,30 @@
   }
 }
 
+void GraphChecker::VisitCheckCast(HCheckCast* check) {
+  VisitInstruction(check);
+  HInstruction* input = check->InputAt(1);
+  if (!input->IsLoadClass()) {
+    AddError(StringPrintf("%s:%d expects a HLoadClass as second input, not %s:%d.",
+                          check->DebugName(),
+                          check->GetId(),
+                          input->DebugName(),
+                          input->GetId()));
+  }
+}
+
+void GraphChecker::VisitInstanceOf(HInstanceOf* instruction) {
+  VisitInstruction(instruction);
+  HInstruction* input = instruction->InputAt(1);
+  if (!input->IsLoadClass()) {
+    AddError(StringPrintf("%s:%d expects a HLoadClass as second input, not %s:%d.",
+                          instruction->DebugName(),
+                          instruction->GetId(),
+                          input->DebugName(),
+                          input->GetId()));
+  }
+}
+
 void SSAChecker::VisitBasicBlock(HBasicBlock* block) {
   super_type::VisitBasicBlock(block);
 
diff --git a/compiler/optimizing/graph_checker.h b/compiler/optimizing/graph_checker.h
index bafa69d..7c72e23 100644
--- a/compiler/optimizing/graph_checker.h
+++ b/compiler/optimizing/graph_checker.h
@@ -48,6 +48,10 @@
   // Check that the HasBoundsChecks() flag is set for bounds checks.
   void VisitBoundsCheck(HBoundsCheck* check) OVERRIDE;
 
+  // Check that HCheckCast and HInstanceOf have HLoadClass as second input.
+  void VisitCheckCast(HCheckCast* check) OVERRIDE;
+  void VisitInstanceOf(HInstanceOf* check) OVERRIDE;
+
   // Check that the Return and ReturnVoid jump to the exit block.
   void VisitReturn(HReturn* ret) OVERRIDE;
   void VisitReturnVoid(HReturnVoid* ret) OVERRIDE;
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index 30d61ef..c41574c 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -462,7 +462,7 @@
           ReferenceTypeInfo info = instruction->AsLoadClass()->GetLoadedClassRTI();
           ScopedObjectAccess soa(Thread::Current());
           if (info.GetTypeHandle().GetReference() != nullptr) {
-            StartAttributeStream("klass") << info.GetTypeHandle().Get();
+            StartAttributeStream("klass") << PrettyClass(info.GetTypeHandle().Get());
           } else {
             StartAttributeStream("klass") << "unresolved";
           }
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index 6784098..3d6606b 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -151,6 +151,15 @@
   HBoundType* bound_type = nullptr;
 
   HInstruction* obj = instanceOf->InputAt(0);
+  if (obj->GetReferenceTypeInfo().IsExact() && !obj->IsPhi()) {
+    // This method is being called while doing a fixed-point calculation
+    // over phis. Non-phis instruction whose type is already known do
+    // not need to be bound to another type.
+    // Not that this also prevents replacing `HLoadClass` with a `HBoundType`.
+    // `HCheckCast` and `HInstanceOf` expect a `HLoadClass` as a second
+    // input.
+    return;
+  }
   for (HUseIterator<HInstruction*> it(obj->GetUses()); !it.Done(); it.Advance()) {
     HInstruction* user = it.Current()->GetUser();
     if (instanceOfTrueBlock->Dominates(user->GetBlock())) {