Introduce constraints to compose first-order simple inlining constraints
Change-Id: I85ba12382c8d0b54121c0b9ebcc15cd134d8afbf
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningArgumentConstraint.java b/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningArgumentConstraint.java
index d05b97e..749d6f4 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningArgumentConstraint.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningArgumentConstraint.java
@@ -22,4 +22,9 @@
int getArgumentIndex() {
return argumentIndex;
}
+
+ @Override
+ public boolean isArgumentConstraint() {
+ return true;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraint.java b/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraint.java
index 1420223..db78fd2 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraint.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraint.java
@@ -5,6 +5,8 @@
package com.android.tools.r8.ir.analysis.inlining;
import com.android.tools.r8.ir.code.InvokeMethod;
+import com.google.common.collect.ImmutableList;
+import java.util.function.Supplier;
public abstract class SimpleInliningConstraint {
@@ -12,6 +14,10 @@
return false;
}
+ public boolean isArgumentConstraint() {
+ return false;
+ }
+
public boolean isBooleanFalse() {
return false;
}
@@ -20,6 +26,22 @@
return false;
}
+ public boolean isConjunction() {
+ return false;
+ }
+
+ public SimpleInliningConstraintConjunction asConjunction() {
+ return null;
+ }
+
+ public boolean isDisjunction() {
+ return false;
+ }
+
+ public SimpleInliningConstraintDisjunction asDisjunction() {
+ return null;
+ }
+
public boolean isNever() {
return false;
}
@@ -33,4 +55,53 @@
}
public abstract boolean isSatisfied(InvokeMethod invoke);
+
+ public final SimpleInliningConstraint meet(SimpleInliningConstraint other) {
+ if (isAlways()) {
+ return other;
+ }
+ if (other.isAlways()) {
+ return this;
+ }
+ if (isNever() || other.isNever()) {
+ return NeverSimpleInliningConstraint.getInstance();
+ }
+ if (isConjunction()) {
+ return asConjunction().add(other);
+ }
+ if (other.isConjunction()) {
+ return other.asConjunction().add(this);
+ }
+ assert isArgumentConstraint() || isDisjunction();
+ assert other.isArgumentConstraint() || other.isDisjunction();
+ return new SimpleInliningConstraintConjunction(ImmutableList.of(this, other));
+ }
+
+ public final SimpleInliningConstraint lazyMeet(Supplier<SimpleInliningConstraint> supplier) {
+ if (isNever()) {
+ return NeverSimpleInliningConstraint.getInstance();
+ }
+ return meet(supplier.get());
+ }
+
+ public final SimpleInliningConstraint join(SimpleInliningConstraint other) {
+ if (isAlways() || other.isAlways()) {
+ return AlwaysSimpleInliningConstraint.getInstance();
+ }
+ if (isNever()) {
+ return other;
+ }
+ if (other.isNever()) {
+ return this;
+ }
+ if (isDisjunction()) {
+ return asDisjunction().add(other);
+ }
+ if (other.isDisjunction()) {
+ return other.asDisjunction().add(this);
+ }
+ assert isArgumentConstraint() || isConjunction();
+ assert other.isArgumentConstraint() || other.isConjunction();
+ return new SimpleInliningConstraintDisjunction(ImmutableList.of(this, other));
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraintConjunction.java b/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraintConjunction.java
new file mode 100644
index 0000000..ccc7400
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraintConjunction.java
@@ -0,0 +1,65 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.analysis.inlining;
+
+import com.android.tools.r8.ir.code.InvokeMethod;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+
+public class SimpleInliningConstraintConjunction extends SimpleInliningConstraint {
+
+ private final List<SimpleInliningConstraint> constraints;
+
+ public SimpleInliningConstraintConjunction(List<SimpleInliningConstraint> constraints) {
+ assert constraints.size() > 1;
+ assert constraints.stream().noneMatch(SimpleInliningConstraint::isAlways);
+ assert constraints.stream().noneMatch(SimpleInliningConstraint::isConjunction);
+ assert constraints.stream().noneMatch(SimpleInliningConstraint::isNever);
+ this.constraints = constraints;
+ }
+
+ SimpleInliningConstraint add(SimpleInliningConstraint constraint) {
+ assert !constraint.isAlways();
+ assert !constraint.isNever();
+ if (constraint.isConjunction()) {
+ return addAll(constraint.asConjunction());
+ }
+ assert constraint.isArgumentConstraint() || constraint.isDisjunction();
+ return new SimpleInliningConstraintConjunction(
+ ImmutableList.<SimpleInliningConstraint>builder()
+ .addAll(constraints)
+ .add(constraint)
+ .build());
+ }
+
+ public SimpleInliningConstraintConjunction addAll(
+ SimpleInliningConstraintConjunction conjunction) {
+ return new SimpleInliningConstraintConjunction(
+ ImmutableList.<SimpleInliningConstraint>builder()
+ .addAll(constraints)
+ .addAll(conjunction.constraints)
+ .build());
+ }
+
+ @Override
+ public boolean isConjunction() {
+ return true;
+ }
+
+ @Override
+ public SimpleInliningConstraintConjunction asConjunction() {
+ return this;
+ }
+
+ @Override
+ public boolean isSatisfied(InvokeMethod invoke) {
+ for (SimpleInliningConstraint constraint : constraints) {
+ if (!constraint.isSatisfied(invoke)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraintDisjunction.java b/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraintDisjunction.java
new file mode 100644
index 0000000..f84e5cd
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraintDisjunction.java
@@ -0,0 +1,65 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.analysis.inlining;
+
+import com.android.tools.r8.ir.code.InvokeMethod;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+
+public class SimpleInliningConstraintDisjunction extends SimpleInliningConstraint {
+
+ private final List<SimpleInliningConstraint> constraints;
+
+ public SimpleInliningConstraintDisjunction(List<SimpleInliningConstraint> constraints) {
+ assert constraints.size() > 1;
+ assert constraints.stream().noneMatch(SimpleInliningConstraint::isAlways);
+ assert constraints.stream().noneMatch(SimpleInliningConstraint::isDisjunction);
+ assert constraints.stream().noneMatch(SimpleInliningConstraint::isNever);
+ this.constraints = constraints;
+ }
+
+ SimpleInliningConstraint add(SimpleInliningConstraint constraint) {
+ assert !constraint.isAlways();
+ assert !constraint.isNever();
+ if (constraint.isDisjunction()) {
+ return addAll(constraint.asDisjunction());
+ }
+ assert constraint.isArgumentConstraint() || constraint.isConjunction();
+ return new SimpleInliningConstraintDisjunction(
+ ImmutableList.<SimpleInliningConstraint>builder()
+ .addAll(constraints)
+ .add(constraint)
+ .build());
+ }
+
+ public SimpleInliningConstraintDisjunction addAll(
+ SimpleInliningConstraintDisjunction disjunction) {
+ return new SimpleInliningConstraintDisjunction(
+ ImmutableList.<SimpleInliningConstraint>builder()
+ .addAll(constraints)
+ .addAll(disjunction.constraints)
+ .build());
+ }
+
+ @Override
+ public boolean isDisjunction() {
+ return true;
+ }
+
+ @Override
+ public SimpleInliningConstraintDisjunction asDisjunction() {
+ return this;
+ }
+
+ @Override
+ public boolean isSatisfied(InvokeMethod invoke) {
+ for (SimpleInliningConstraint constraint : constraints) {
+ if (constraint.isSatisfied(invoke)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}