Quick: Eliminate check-cast guaranteed by instance-of.

Eliminate check-cast if the result of an instance-of with
the very same type on the same value is used to branch to
the check-cast's block or a dominator of it.

Note that there already exists a verifier-based elimination
of check-cast but it excludes check-cast on interfaces. This
new optimization works for interface types and, since it's
GVN-based, it can better recognize when the same reference
is used for instance-of and check-cast.

Change-Id: Ib315199805099d1cb0534bb4a90dc51baa409685
diff --git a/compiler/dex/gvn_dead_code_elimination.cc b/compiler/dex/gvn_dead_code_elimination.cc
index 2e7f032..2d4c18f 100644
--- a/compiler/dex/gvn_dead_code_elimination.cc
+++ b/compiler/dex/gvn_dead_code_elimination.cc
@@ -1058,7 +1058,6 @@
     case Instruction::INVOKE_INTERFACE_RANGE:
     case Instruction::INVOKE_STATIC:
     case Instruction::INVOKE_STATIC_RANGE:
-    case Instruction::CHECK_CAST:
     case Instruction::THROW:
     case Instruction::FILLED_NEW_ARRAY:
     case Instruction::FILLED_NEW_ARRAY_RANGE:
@@ -1073,6 +1072,12 @@
       uses_all_vregs = true;
       break;
 
+    case Instruction::CHECK_CAST:
+      DCHECK_EQ(mir->ssa_rep->num_uses, 1);
+      must_keep = true;  // Keep for type information even if MIR_IGNORE_CHECK_CAST.
+      uses_all_vregs = (mir->optimization_flags & MIR_IGNORE_CHECK_CAST) == 0;
+      break;
+
     case kMirOpNullCheck:
       DCHECK_EQ(mir->ssa_rep->num_uses, 1);
       if ((mir->optimization_flags & MIR_IGNORE_NULL_CHECK) != 0) {