Set hint for liveinterval related to checkcast

- Into the IR, checkcast instruction defines a new value, try to allocate
input and output to the same register by setting a hint. It allows to save
around 9ko of the dex file for GMSCore v10 in release mode. Debug mode is
unchanged.

Change-Id: I9f4a44d25c61d33fe70210a31e9b1b45bc9e67b0
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
index 5783ad4..55ecb45 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
@@ -11,6 +11,7 @@
 import com.android.tools.r8.ir.code.And;
 import com.android.tools.r8.ir.code.ArithmeticBinop;
 import com.android.tools.r8.ir.code.BasicBlock;
+import com.android.tools.r8.ir.code.CheckCast;
 import com.android.tools.r8.ir.code.DebugLocalsChange;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.code.Instruction;
@@ -751,6 +752,7 @@
     while (!unhandled.isEmpty()) {
       LiveIntervals unhandledInterval = unhandled.poll();
 
+      setHintForDestRegOfCheckCast(unhandledInterval);
       setHintToPromote2AddrInstruction(unhandledInterval);
 
       // If this interval value is the src of an argument move. Fix the registers for the
@@ -804,6 +806,20 @@
     return true;
   }
 
+  private void setHintForDestRegOfCheckCast(LiveIntervals unhandledInterval) {
+    if (unhandledInterval.getHint() == null &&
+        unhandledInterval.getValue().definition instanceof CheckCast) {
+      CheckCast checkcast = unhandledInterval.getValue().definition.asCheckCast();
+      Value checkcastInput = checkcast.inValues().get(0);
+      assert checkcastInput != null;
+      if (checkcastInput.getLiveIntervals() != null &&
+          !checkcastInput.getLiveIntervals().overlaps(unhandledInterval) &&
+          checkcastInput.getLocalInfo() == unhandledInterval.getValue().definition.getLocalInfo()) {
+        unhandledInterval.setHint(checkcastInput.getLiveIntervals());
+      }
+    }
+  }
+
   /*
    * This method tries to promote arithmetic binary instruction to use the 2Addr form.
    * To achieve this goal the output interval of the binary instruction is set with an hint
diff --git a/src/test/java/com/android/tools/r8/smali/IfSimplificationTest.java b/src/test/java/com/android/tools/r8/smali/IfSimplificationTest.java
index 5dc1e75..162db06 100644
--- a/src/test/java/com/android/tools/r8/smali/IfSimplificationTest.java
+++ b/src/test/java/com/android/tools/r8/smali/IfSimplificationTest.java
@@ -444,6 +444,6 @@
     // TODO(sgjesse): Maybe this test is too fragile, as it leaves quite a lot of code, so the
     // expectation might need changing with other optimizations.
     // TODO(zerny): Consider optimizing the fallthrough branch of conditionals to not be return.
-    assertEquals(27, code.instructions.length);
+    assertEquals(26, code.instructions.length);
   }
 }