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.