Further refinements to checkcast/instanceof.

- Use setcc when possible.
- Do an exact check in the Object[] case before checking the
  component type.

Change-Id: Ic11c60643af9b41fe4ef2beb59dfe7769bef388f
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 32a1db5..b78b017 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -4766,10 +4766,16 @@
         DCHECK(cls.IsStackSlot()) << cls;
         __ cmpl(out, Address(CpuRegister(RSP), cls.GetStackIndex()));
       }
-      // Classes must be equal for the instanceof to succeed.
-      __ j(kNotEqual, &zero);
-      __ movl(out, Immediate(1));
-      __ jmp(&done);
+      if (zero.IsLinked()) {
+        // Classes must be equal for the instanceof to succeed.
+        __ j(kNotEqual, &zero);
+        __ movl(out, Immediate(1));
+        __ jmp(&done);
+      } else {
+        __ setcc(kEqual, out);
+        // setcc only sets the low byte.
+        __ andl(out, Immediate(1));
+      }
       break;
     }
     case TypeCheckKind::kAbstractClassCheck: {
@@ -4820,7 +4826,16 @@
       break;
     }
     case TypeCheckKind::kArrayObjectCheck: {
-      // Just need to check that the object's class is a non primitive array.
+      // Do an exact check.
+      NearLabel exact_check;
+      if (cls.IsRegister()) {
+        __ cmpl(out, cls.AsRegister<CpuRegister>());
+      } else {
+        DCHECK(cls.IsStackSlot()) << cls;
+        __ cmpl(out, Address(CpuRegister(RSP), cls.GetStackIndex()));
+      }
+      __ j(kEqual, &exact_check);
+      // Otherwise, we need to check that the object's class is a non primitive array.
       __ movl(out, Address(out, component_offset));
       __ MaybeUnpoisonHeapReference(out);
       __ testl(out, out);
@@ -4828,6 +4843,7 @@
       __ j(kEqual, &done);
       __ cmpw(Address(out, primitive_offset), Immediate(Primitive::kPrimNot));
       __ j(kNotEqual, &zero);
+      __ Bind(&exact_check);
       __ movl(out, Immediate(1));
       __ jmp(&done);
       break;
@@ -4983,7 +4999,7 @@
     }
     case TypeCheckKind::kClassHierarchyCheck: {
       // Walk over the class hierarchy to find a match.
-      NearLabel loop, success;
+      NearLabel loop;
       __ Bind(&loop);
       if (cls.IsRegister()) {
         __ cmpl(temp, cls.AsRegister<CpuRegister>());
@@ -4991,18 +5007,25 @@
         DCHECK(cls.IsStackSlot()) << cls;
         __ cmpl(temp, Address(CpuRegister(RSP), cls.GetStackIndex()));
       }
-      __ j(kEqual, &success);
+      __ j(kEqual, &done);
       __ movl(temp, Address(temp, super_offset));
       __ MaybeUnpoisonHeapReference(temp);
       __ testl(temp, temp);
       __ j(kNotEqual, &loop);
       // Jump to the slow path to throw the exception.
       __ jmp(slow_path->GetEntryLabel());
-      __ Bind(&success);
       break;
     }
     case TypeCheckKind::kArrayObjectCheck: {
-      // Just need to check that the object's class is a non primitive array.
+      // Do an exact check.
+      if (cls.IsRegister()) {
+        __ cmpl(temp, cls.AsRegister<CpuRegister>());
+      } else {
+        DCHECK(cls.IsStackSlot()) << cls;
+        __ cmpl(temp, Address(CpuRegister(RSP), cls.GetStackIndex()));
+      }
+      __ j(kEqual, &done);
+      // Otherwise, we need to check that the object's class is a non primitive array.
       __ movl(temp, Address(temp, component_offset));
       __ MaybeUnpoisonHeapReference(temp);
       __ testl(temp, temp);