Implement known boolean tracking for phis.

A phi is known to be a boolean if the only values that the phi can
ever represent are the integers 0 or 1.

Bug: b/65363934
Change-Id: Ieb3a7add29c140fd9f2cd5b39917faae51c1904e
diff --git a/src/main/java/com/android/tools/r8/ir/code/Phi.java b/src/main/java/com/android/tools/r8/ir/code/Phi.java
index 65995ff..28a4d74 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Phi.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Phi.java
@@ -278,6 +278,40 @@
         && value.isZero();
   }
 
+  /**
+   * Determine if the only possible values for the phi are the integers 0 or 1.
+   */
+  public boolean knownToBeBoolean() {
+    return knownToBeBoolean(new HashSet<>());
+  }
+
+  private boolean knownToBeBoolean(HashSet<Phi> active) {
+    active.add(this);
+
+    for (Value operand : operands) {
+      if (!operand.isPhi()) {
+        if (operand.isConstNumber()) {
+          ConstNumber number = operand.getConstInstruction().asConstNumber();
+          if (!number.isIntegerOne() && !number.isIntegerZero()) {
+            return false;
+          }
+        } else {
+          return false;
+        }
+      }
+    }
+
+    for (Value operand : operands) {
+      if (operand.isPhi() && !active.contains(operand.asPhi())) {
+        if (!operand.asPhi().knownToBeBoolean(active)) {
+          return false;
+        }
+      }
+    }
+
+    return true;
+  }
+
   private MoveType computeOutType(Set<Phi> active) {
     if (outType != null) {
       return outType;
@@ -293,7 +327,7 @@
     }
     // We did not find a non-phi operand that dictates the type. Recurse on phi arguments.
     for (Value operand : operands) {
-      if (operand.isPhi() && !active.contains(operand)) {
+      if (operand.isPhi() && !active.contains(operand.asPhi())) {
         MoveType phiType = operand.asPhi().computeOutType(active);
         // TODO(zerny): If we had a CONST_ZERO type element, we could often avoid going through
         // all phis. We would only have to recurse until we got a non CONST_ZERO out type.