Introduce various constraints for simple inlining
This introduces a constraint that is always true, and constraints that are true if a specific argument is guaranteed to be either true, false, null, or non-null.
Bug: 132600418
Change-Id: I0db575dfded14ba71ff3c40c16e697bd2f25fca8
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index d51e21c..6bedacf 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -13,6 +13,7 @@
import com.android.tools.r8.graph.classmerging.StaticallyMergedClasses;
import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
import com.android.tools.r8.horizontalclassmerging.HorizontallyMergedClasses;
+import com.android.tools.r8.ir.analysis.inlining.SimpleInliningConstraintFactory;
import com.android.tools.r8.ir.analysis.proto.EnumLiteProtoShrinker;
import com.android.tools.r8.ir.analysis.proto.GeneratedExtensionRegistryShrinker;
import com.android.tools.r8.ir.analysis.proto.GeneratedMessageLiteBuilderShrinker;
@@ -67,6 +68,8 @@
private final InstanceFieldInitializationInfoFactory instanceFieldInitializationInfoFactory =
new InstanceFieldInitializationInfoFactory();
private final MethodProcessingId.Factory methodProcessingIdFactory;
+ private final SimpleInliningConstraintFactory simpleInliningConstraintFactory =
+ new SimpleInliningConstraintFactory();
// Desugaring.
public final PrefixRewritingMapper rewritePrefix;
@@ -187,6 +190,10 @@
return methodProcessingIdFactory;
}
+ public SimpleInliningConstraintFactory simpleInliningConstraintFactory() {
+ return simpleInliningConstraintFactory;
+ }
+
public T appInfo() {
assert !appInfo.hasClassHierarchy() || enableWholeProgramOptimizations();
return appInfo;
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/inlining/AlwaysSimpleInliningConstraint.java b/src/main/java/com/android/tools/r8/ir/analysis/inlining/AlwaysSimpleInliningConstraint.java
new file mode 100644
index 0000000..d92af89
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/analysis/inlining/AlwaysSimpleInliningConstraint.java
@@ -0,0 +1,30 @@
+// 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;
+
+/** Constraint that is always satisfied. */
+public class AlwaysSimpleInliningConstraint extends SimpleInliningConstraint {
+
+ public static final AlwaysSimpleInliningConstraint INSTANCE =
+ new AlwaysSimpleInliningConstraint();
+
+ private AlwaysSimpleInliningConstraint() {}
+
+ public static AlwaysSimpleInliningConstraint getInstance() {
+ return INSTANCE;
+ }
+
+ @Override
+ public boolean isAlways() {
+ return true;
+ }
+
+ @Override
+ public boolean isSatisfied(InvokeMethod invoke) {
+ return false;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/inlining/BooleanFalseSimpleInliningConstraint.java b/src/main/java/com/android/tools/r8/ir/analysis/inlining/BooleanFalseSimpleInliningConstraint.java
new file mode 100644
index 0000000..a568f38
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/analysis/inlining/BooleanFalseSimpleInliningConstraint.java
@@ -0,0 +1,34 @@
+// 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.android.tools.r8.ir.code.Value;
+
+/** Constraint that is satisfied if a specific argument is always false. */
+public class BooleanFalseSimpleInliningConstraint extends SimpleInliningArgumentConstraint {
+
+ private BooleanFalseSimpleInliningConstraint(int argumentIndex) {
+ super(argumentIndex);
+ }
+
+ static BooleanFalseSimpleInliningConstraint create(
+ int argumentIndex, SimpleInliningConstraintFactory witness) {
+ assert witness != null;
+ return new BooleanFalseSimpleInliningConstraint(argumentIndex);
+ }
+
+ @Override
+ public boolean isBooleanFalse() {
+ return true;
+ }
+
+ @Override
+ public boolean isSatisfied(InvokeMethod invoke) {
+ Value argument = getArgument(invoke);
+ assert argument.getType().isInt();
+ return argument.isConstBoolean(false);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/inlining/BooleanTrueSimpleInliningConstraint.java b/src/main/java/com/android/tools/r8/ir/analysis/inlining/BooleanTrueSimpleInliningConstraint.java
new file mode 100644
index 0000000..37b61d7
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/analysis/inlining/BooleanTrueSimpleInliningConstraint.java
@@ -0,0 +1,34 @@
+// 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.android.tools.r8.ir.code.Value;
+
+/** Constraint that is satisfied if a specific argument is always true. */
+public class BooleanTrueSimpleInliningConstraint extends SimpleInliningArgumentConstraint {
+
+ private BooleanTrueSimpleInliningConstraint(int argumentIndex) {
+ super(argumentIndex);
+ }
+
+ static BooleanTrueSimpleInliningConstraint create(
+ int argumentIndex, SimpleInliningConstraintFactory witness) {
+ assert witness != null;
+ return new BooleanTrueSimpleInliningConstraint(argumentIndex);
+ }
+
+ @Override
+ public boolean isBooleanTrue() {
+ return true;
+ }
+
+ @Override
+ public boolean isSatisfied(InvokeMethod invoke) {
+ Value argument = getArgument(invoke);
+ assert argument.getType().isInt();
+ return argument.isConstBoolean(true);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/inlining/NeverSimpleInliningConstraint.java b/src/main/java/com/android/tools/r8/ir/analysis/inlining/NeverSimpleInliningConstraint.java
index 295f0c5..d3c0fca 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/inlining/NeverSimpleInliningConstraint.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/inlining/NeverSimpleInliningConstraint.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.ir.code.InvokeMethod;
+/** Constraint that is never satisfied. */
public class NeverSimpleInliningConstraint extends SimpleInliningConstraint {
public static final NeverSimpleInliningConstraint INSTANCE = new NeverSimpleInliningConstraint();
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/inlining/NotNullSimpleInliningConstraint.java b/src/main/java/com/android/tools/r8/ir/analysis/inlining/NotNullSimpleInliningConstraint.java
new file mode 100644
index 0000000..6ccf6ca
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/analysis/inlining/NotNullSimpleInliningConstraint.java
@@ -0,0 +1,34 @@
+// 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.android.tools.r8.ir.code.Value;
+
+/** Constraint that is satisfied if a specific argument is always non-null. */
+public class NotNullSimpleInliningConstraint extends SimpleInliningArgumentConstraint {
+
+ private NotNullSimpleInliningConstraint(int argumentIndex) {
+ super(argumentIndex);
+ }
+
+ static NotNullSimpleInliningConstraint create(
+ int argumentIndex, SimpleInliningConstraintFactory witness) {
+ assert witness != null;
+ return new NotNullSimpleInliningConstraint(argumentIndex);
+ }
+
+ @Override
+ public boolean isNotNull() {
+ return true;
+ }
+
+ @Override
+ public boolean isSatisfied(InvokeMethod invoke) {
+ Value argument = getArgument(invoke);
+ assert argument.getType().isReferenceType() : invoke;
+ return argument.isNeverNull();
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/inlining/NullSimpleInliningConstraint.java b/src/main/java/com/android/tools/r8/ir/analysis/inlining/NullSimpleInliningConstraint.java
new file mode 100644
index 0000000..39cae4b
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/analysis/inlining/NullSimpleInliningConstraint.java
@@ -0,0 +1,34 @@
+// 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.android.tools.r8.ir.code.Value;
+
+/** Constraint that is satisfied if a specific argument is always null. */
+public class NullSimpleInliningConstraint extends SimpleInliningArgumentConstraint {
+
+ private NullSimpleInliningConstraint(int argumentIndex) {
+ super(argumentIndex);
+ }
+
+ static NullSimpleInliningConstraint create(
+ int argumentIndex, SimpleInliningConstraintFactory witness) {
+ assert witness != null;
+ return new NullSimpleInliningConstraint(argumentIndex);
+ }
+
+ @Override
+ public boolean isNull() {
+ return true;
+ }
+
+ @Override
+ public boolean isSatisfied(InvokeMethod invoke) {
+ Value argument = getArgument(invoke);
+ assert argument.getType().isReferenceType();
+ return argument.getType().isDefinitelyNull();
+ }
+}
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
new file mode 100644
index 0000000..d05b97e
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningArgumentConstraint.java
@@ -0,0 +1,25 @@
+// 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.android.tools.r8.ir.code.Value;
+
+public abstract class SimpleInliningArgumentConstraint extends SimpleInliningConstraint {
+
+ private final int argumentIndex;
+
+ SimpleInliningArgumentConstraint(int argumentIndex) {
+ this.argumentIndex = argumentIndex;
+ }
+
+ Value getArgument(InvokeMethod invoke) {
+ return invoke.getArgument(argumentIndex);
+ }
+
+ int getArgumentIndex() {
+ return argumentIndex;
+ }
+}
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 73bca62..1420223 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
@@ -8,9 +8,29 @@
public abstract class SimpleInliningConstraint {
+ public boolean isAlways() {
+ return false;
+ }
+
+ public boolean isBooleanFalse() {
+ return false;
+ }
+
+ public boolean isBooleanTrue() {
+ return false;
+ }
+
public boolean isNever() {
return false;
}
+ public boolean isNotNull() {
+ return false;
+ }
+
+ public boolean isNull() {
+ return false;
+ }
+
public abstract boolean isSatisfied(InvokeMethod invoke);
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraintFactory.java b/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraintFactory.java
new file mode 100644
index 0000000..1e3651a
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraintFactory.java
@@ -0,0 +1,40 @@
+// 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 java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class SimpleInliningConstraintFactory {
+
+ private final Map<Integer, BooleanFalseSimpleInliningConstraint> booleanFalseConstraints =
+ new ConcurrentHashMap<>();
+ private final Map<Integer, BooleanTrueSimpleInliningConstraint> booleanTrueConstraints =
+ new ConcurrentHashMap<>();
+ private final Map<Integer, NotNullSimpleInliningConstraint> notNullConstraints =
+ new ConcurrentHashMap<>();
+ private final Map<Integer, NullSimpleInliningConstraint> nullConstraints =
+ new ConcurrentHashMap<>();
+
+ public BooleanFalseSimpleInliningConstraint createBooleanFalseConstraint(int argumentIndex) {
+ return booleanFalseConstraints.computeIfAbsent(
+ argumentIndex, key -> BooleanFalseSimpleInliningConstraint.create(key, this));
+ }
+
+ public BooleanTrueSimpleInliningConstraint createBooleanTrueConstraint(int argumentIndex) {
+ return booleanTrueConstraints.computeIfAbsent(
+ argumentIndex, key -> BooleanTrueSimpleInliningConstraint.create(key, this));
+ }
+
+ public NotNullSimpleInliningConstraint createNotNullConstraint(int argumentIndex) {
+ return notNullConstraints.computeIfAbsent(
+ argumentIndex, key -> NotNullSimpleInliningConstraint.create(key, this));
+ }
+
+ public NullSimpleInliningConstraint createNullConstraint(int argumentIndex) {
+ return nullConstraints.computeIfAbsent(
+ argumentIndex, key -> NullSimpleInliningConstraint.create(key, this));
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Value.java b/src/main/java/com/android/tools/r8/ir/code/Value.java
index b842c63..0f0d6e9 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Value.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Value.java
@@ -30,6 +30,7 @@
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.position.MethodPosition;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.LongInterval;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.SetUtils;
@@ -778,6 +779,11 @@
return isConstant() && getConstInstruction().isConstNumber();
}
+ public boolean isConstBoolean(boolean value) {
+ return isConstNumber()
+ && definition.asConstNumber().getRawValue() == BooleanUtils.longValue(value);
+ }
+
public boolean isConstZero() {
return isConstNumber() && definition.asConstNumber().isZero();
}