Add test for type constraints on trivial phis
Bug: 119401913
Change-Id: I2f7a70489dbe6cd411cceb628a50630cb74523fe
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/type/ArrayTypeTest.java b/src/test/java/com/android/tools/r8/ir/analysis/type/ArrayTypeTest.java
index 1d21381..f508934 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/type/ArrayTypeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/type/ArrayTypeTest.java
@@ -7,7 +7,6 @@
import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.FLOAT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.ir.code.ArrayGet;
@@ -17,7 +16,6 @@
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.Value;
import java.util.function.Consumer;
-import java.util.function.Predicate;
import org.junit.Ignore;
import org.junit.Test;
@@ -99,24 +97,6 @@
};
}
- private static <T extends Instruction> T getMatchingInstruction(
- IRCode code, Predicate<Instruction> predicate) {
- Instruction result = null;
- Iterable<Instruction> instructions = code::instructionIterator;
- for (Instruction instruction : instructions) {
- if (predicate.test(instruction)) {
- if (result != null) {
- fail();
- }
- result = instruction;
- }
- }
- if (result == null) {
- fail();
- }
- return (T) result;
- }
-
static class TestClass {
public static void arrayTest() {
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/type/TypeAnalysisTestBase.java b/src/test/java/com/android/tools/r8/ir/analysis/type/TypeAnalysisTestBase.java
index 98c4954..3987e03 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/type/TypeAnalysisTestBase.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/type/TypeAnalysisTestBase.java
@@ -4,11 +4,14 @@
package com.android.tools.r8.ir.analysis.type;
+import static org.junit.Assert.fail;
+
import com.android.tools.r8.TestBase;
import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
@@ -16,6 +19,7 @@
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.util.function.Consumer;
+import java.util.function.Predicate;
import org.junit.Before;
public class TypeAnalysisTestBase extends TestBase {
@@ -52,4 +56,22 @@
.buildIR(appInfo, GraphLense.getIdentityLense(), options, Origin.unknown());
irInspector.accept(code);
}
+
+ public static <T extends Instruction> T getMatchingInstruction(
+ IRCode code, Predicate<Instruction> predicate) {
+ Instruction result = null;
+ Iterable<Instruction> instructions = code::instructionIterator;
+ for (Instruction instruction : instructions) {
+ if (predicate.test(instruction)) {
+ if (result != null) {
+ fail();
+ }
+ result = instruction;
+ }
+ }
+ if (result == null) {
+ fail();
+ }
+ return (T) result;
+ }
}
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/type/TypeConstraintOnTrivialPhiTest.java b/src/test/java/com/android/tools/r8/ir/analysis/type/TypeConstraintOnTrivialPhiTest.java
new file mode 100644
index 0000000..da32262
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/analysis/type/TypeConstraintOnTrivialPhiTest.java
@@ -0,0 +1,113 @@
+// Copyright (c) 2018, 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.type;
+
+import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.DOUBLE;
+import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.FLOAT;
+import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.INT;
+import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.LONG;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.ir.code.ConstNumber;
+import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.smali.SmaliBuilder;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.function.Consumer;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class TypeConstraintOnTrivialPhiTest extends TypeAnalysisTestBase {
+
+ private enum Config {
+ INT,
+ FLOAT,
+ LONG,
+ DOUBLE;
+
+ public boolean isSingle() {
+ return this == INT || this == FLOAT;
+ }
+
+ public String getTestName() {
+ return toString().toLowerCase() + "ConstraintOnTrivialPhiTest";
+ }
+
+ public String getConstInstruction() {
+ return isSingle() ? "const/4 v0, 0x0" : "const-wide v0, 0x0";
+ }
+
+ public String getMoveInstruction() {
+ return isSingle() ? "move v1, v0" : "move-wide v2, v0";
+ }
+
+ public String getInvokeStaticInstruction() {
+ switch (this) {
+ case INT:
+ return "invoke-static {v1}, Ljava/lang/Integer;->toString(I)Ljava/lang/String;";
+ case FLOAT:
+ return "invoke-static {v1}, Ljava/lang/Float;->toString(F)Ljava/lang/String;";
+ case LONG:
+ return "invoke-static {v2, v3}, Ljava/lang/Long;->toString(J)Ljava/lang/String;";
+ case DOUBLE:
+ return "invoke-static {v2, v3}, Ljava/lang/Double;->toString(D)Ljava/lang/String;";
+ }
+ throw new Unreachable();
+ }
+ }
+
+ public TypeConstraintOnTrivialPhiTest() throws Exception {
+ super(buildApp(), "TestClass");
+ }
+
+ public static AndroidApp buildApp() throws Exception {
+ SmaliBuilder smaliBuilder = new SmaliBuilder("TestClass");
+ for (Config config : Config.values()) {
+ String code =
+ StringUtils.lines(
+ config.getConstInstruction(),
+ ":label_1",
+ "if-eqz p0, :label_2",
+ config.getMoveInstruction(),
+ config.getInvokeStaticInstruction(),
+ ":label_2",
+ "goto :label_1");
+ smaliBuilder.addStaticMethod("void", config.getTestName(), ImmutableList.of("int"), 4, code);
+ }
+ return smaliBuilder.build();
+ }
+
+ @Test
+ public void testIntConstraintOnTrivialPhi() throws Exception {
+ buildAndCheckIR("intConstraintOnTrivialPhiTest", testInspector(INT));
+ }
+
+ @Test
+ @Ignore("b/119401913")
+ public void testFloatConstraintOnTrivialPhi() throws Exception {
+ buildAndCheckIR("floatConstraintOnTrivialPhiTest", testInspector(FLOAT));
+ }
+
+ @Test
+ public void testLongConstraintOnTrivialPhi() throws Exception {
+ buildAndCheckIR("longConstraintOnTrivialPhiTest", testInspector(LONG));
+ }
+
+ @Test
+ @Ignore("b/119401913")
+ public void testDoubleConstraintOnTrivialPhi() throws Exception {
+ buildAndCheckIR("doubleConstraintOnTrivialPhiTest", testInspector(DOUBLE));
+ }
+
+ private static Consumer<IRCode> testInspector(TypeLatticeElement expectedType) {
+ return code -> {
+ ConstNumber constNumberInstruction = getMatchingInstruction(code, Instruction::isConstNumber);
+ assertEquals(expectedType, constNumberInstruction.outValue().getTypeLattice());
+ };
+ }
+}