Revert constant splitting heuristics change as it breaks gmscore builds.

R=sgjesse@google.com

Change-Id: I5efdacc973749c28b0d2210032119b70d0f6b65b
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 23b6b70..6f94b1e 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -459,7 +459,7 @@
     codeRewriter.commonSubexpressionElimination(code);
     codeRewriter.simplifyArrayConstruction(code);
     codeRewriter.rewriteMoveResult(code);
-    codeRewriter.splitRangeInvokeConstants(code);
+    codeRewriter.splitConstants(code);
     codeRewriter.foldConstants(code);
     codeRewriter.rewriteSwitch(code);
     codeRewriter.simplifyIf(code);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index 408ebc7..e1c0ccb 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -63,6 +63,7 @@
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.IdentityHashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
@@ -651,35 +652,68 @@
     assert code.isConsistentSSA();
   }
 
-  // Split constants that flow into ranged invokes. This gives the register allocator more
-  // freedom in assigning register to ranged invokes which can greatly reduce the number
-  // of register needed (and thereby code size as well).
-  public void splitRangeInvokeConstants(IRCode code) {
+  // Constants are canonicalized in the entry block. We split some of them when it is likely
+  // that having them canonicalized in the entry block will lead to poor code quality.
+  public void splitConstants(IRCode code) {
     for (BasicBlock block : code.blocks) {
-      InstructionListIterator it = block.listIterator();
-      while (it.hasNext()) {
-        Instruction current = it.next();
-        if (current.isInvoke() && current.asInvoke().requiredArgumentRegisters() > 5) {
-          Invoke invoke = current.asInvoke();
-          it.previous();
-          Map<ConstNumber, ConstNumber> oldToNew = new HashMap<>();
-          for (int i = 0; i < invoke.inValues().size(); i++) {
-            Value value = invoke.inValues().get(i);
-            if (value.isConstNumber() && value.numberOfUsers() > 1) {
-              ConstNumber definition = value.getConstInstruction().asConstNumber();
-              Value originalValue = definition.outValue();
-              ConstNumber newNumber = oldToNew.get(definition);
-              if (newNumber == null) {
-                newNumber = ConstNumber.copyOf(code, definition);
-                it.add(newNumber);
-                oldToNew.put(definition, newNumber);
-              }
-              invoke.inValues().set(i, newNumber.outValue());
-              originalValue.removeUser(invoke);
-              newNumber.outValue().addUser(invoke);
+      // Split constants that flow into phis. It is likely that these constants will have moves
+      // generated for them anyway and we might as well insert a const instruction in the right
+      // predecessor block.
+      splitPhiConstants(code, block);
+      // Split constants that flow into ranged invokes. This gives the register allocator more
+      // freedom in assigning register to ranged invokes which can greatly reduce the number
+      // of register needed (and thereby code size as well).
+      splitRangedInvokeConstants(code, block);
+    }
+  }
+
+  private void splitRangedInvokeConstants(IRCode code, BasicBlock block) {
+    InstructionListIterator it = block.listIterator();
+    while (it.hasNext()) {
+      Instruction current = it.next();
+      if (current.isInvoke() && current.asInvoke().requiredArgumentRegisters() > 5) {
+        Invoke invoke = current.asInvoke();
+        it.previous();
+        Map<ConstNumber, ConstNumber> oldToNew = new HashMap<>();
+        for (int i = 0; i < invoke.inValues().size(); i++) {
+          Value value = invoke.inValues().get(i);
+          if (value.isConstNumber() && value.numberOfUsers() > 1) {
+            ConstNumber definition = value.getConstInstruction().asConstNumber();
+            Value originalValue = definition.outValue();
+            ConstNumber newNumber = oldToNew.get(definition);
+            if (newNumber == null) {
+              newNumber = ConstNumber.copyOf(code, definition);
+              it.add(newNumber);
+              oldToNew.put(definition, newNumber);
             }
+            invoke.inValues().set(i, newNumber.outValue());
+            originalValue.removeUser(invoke);
+            newNumber.outValue().addUser(invoke);
           }
-          it.next();
+        }
+        it.next();
+      }
+    }
+  }
+
+  private void splitPhiConstants(IRCode code, BasicBlock block) {
+    for (int i = 0; i < block.getPredecessors().size(); i++) {
+      Map<ConstNumber, ConstNumber> oldToNew = new IdentityHashMap<>();
+      BasicBlock predecessor = block.getPredecessors().get(i);
+      for (Phi phi : block.getPhis()) {
+        Value operand = phi.getOperand(i);
+        if (!operand.isPhi() && operand.isConstNumber()) {
+          ConstNumber definition = operand.getConstInstruction().asConstNumber();
+          ConstNumber newNumber = oldToNew.get(definition);
+          Value originalValue = definition.outValue();
+          if (newNumber == null) {
+            newNumber = ConstNumber.copyOf(code, definition);
+            oldToNew.put(definition, newNumber);
+            insertConstantInBlock(newNumber, predecessor);
+          }
+          phi.getOperands().set(i, newNumber.outValue());
+          originalValue.removePhiUser(phi);
+          newNumber.outValue().addPhiUser(phi);
         }
       }
     }
@@ -696,7 +730,7 @@
     List<Instruction> toInsertInThisBlock = new ArrayList<>();
     while (it.hasNext()) {
       Instruction instruction = it.next();
-      if (instruction.isConstNumber() && instruction.outValue().numberOfAllUsers() > 0) {
+      if (instruction.isConstNumber()) {
         // Collect the blocks for all users of the constant.
         List<BasicBlock> userBlocks = new LinkedList<>();
         for (Instruction user : instruction.outValue().uniqueUsers()) {
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 919f569..6b4a431 100644
--- a/src/test/java/com/android/tools/r8/smali/IfSimplificationTest.java
+++ b/src/test/java/com/android/tools/r8/smali/IfSimplificationTest.java
@@ -180,8 +180,8 @@
         ":return",
         "  return v0");
     DexCode code = method.getCode().asDexCode();
-    assertEquals(10, code.instructions.length);
-    assertTrue(code.instructions[9] instanceof Return);
+    assertEquals(12, code.instructions.length);
+    assertTrue(code.instructions[11] instanceof Return);
   }
 
   @Test
@@ -443,6 +443,6 @@
     DexCode code = method.getCode().asDexCode();
     // 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.
-    assertEquals(27, code.instructions.length);
+    assertEquals(29, code.instructions.length);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/smali/SwitchRewritingTest.java b/src/test/java/com/android/tools/r8/smali/SwitchRewritingTest.java
index e6bfbd0..f10add0 100644
--- a/src/test/java/com/android/tools/r8/smali/SwitchRewritingTest.java
+++ b/src/test/java/com/android/tools/r8/smali/SwitchRewritingTest.java
@@ -7,6 +7,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import com.android.tools.r8.R8;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.code.Const;
 import com.android.tools.r8.code.Const4;
@@ -291,11 +292,12 @@
     DexCode code = method.getCode().asDexCode();
     if (key == 0) {
       assertEquals(5, code.instructions.length);
-      assertTrue(code.instructions[2] instanceof IfEqz);
+      assertTrue(code.instructions[0] instanceof IfEqz);
     } else {
       assertEquals(6, code.instructions.length);
-      assertTrue(some16BitConst(code.instructions[2]));
-      assertTrue(code.instructions[3] instanceof IfEq);
+      assertTrue(some16BitConst(code.instructions[0]));
+      assertTrue(code.instructions[1] instanceof IfEq);
+      assertTrue(code.instructions[2] instanceof Const4);
     }
   }
 
@@ -349,9 +351,9 @@
     DexEncodedMethod method = getMethod(app, signature);
     DexCode code = method.getCode().asDexCode();
     if (twoCaseWillUsePackedSwitch(key1, key2)) {
-      assertTrue(code.instructions[3] instanceof PackedSwitch);
+      assertTrue(code.instructions[0] instanceof PackedSwitch);
     } else {
-      assertTrue(code.instructions[3] instanceof SparseSwitch);
+      assertTrue(code.instructions[0] instanceof SparseSwitch);
     }
   }
 
@@ -421,23 +423,10 @@
     MethodSignature signature = new MethodSignature("Test", "test", "int", ImmutableList.of("int"));
     DexEncodedMethod method = getMethod(app, signature);
     DexCode code = method.getCode().asDexCode();
-    int packedSwithsCount = 0;
-    int sparseSwithsCount = 0;
-    for (Instruction instruction : code.instructions) {
-      if (instruction instanceof PackedSwitch) {
-        packedSwithsCount++;
-      }
-      if (instruction instanceof SparseSwitch) {
-        sparseSwithsCount++;
-      }
-    }
-
     if (keyStep <= 2) {
-      assert packedSwithsCount == 1;
-      assert sparseSwithsCount == 0;
+      assertTrue(code.instructions[0] instanceof PackedSwitch);
     } else {
-      assert packedSwithsCount == 0;
-      assert sparseSwithsCount == 1;
+      assertTrue(code.instructions[0] instanceof SparseSwitch);
     }
   }