Add basic tests about propagating dynamic types from call sites.
Bug: 139246447
Change-Id: I020b282cf51fc9e9d119249faf2335315f2209f0
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeDirectNegativeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeDirectNegativeTest.java
new file mode 100644
index 0000000..7b8b8aa
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeDirectNegativeTest.java
@@ -0,0 +1,90 @@
+// Copyright (c) 2019, 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.optimize.callsites.dynamictype;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class InvokeDirectNegativeTest extends TestBase {
+ private static final Class<?> MAIN = Main.class;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().build();
+ }
+
+ private final TestParameters parameters;
+
+ public InvokeDirectNegativeTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(InvokeDirectNegativeTest.class)
+ .addKeepMainRule(MAIN)
+ .enableClassInliningAnnotations()
+ .enableInliningAnnotations()
+ .setMinApi(parameters.getRuntime())
+ .run(parameters.getRuntime(), MAIN)
+ .assertSuccessWithOutputLines("Sub1", "Sub2")
+ .inspect(this::inspect);
+ }
+
+ private void inspect(CodeInspector inspector) {
+ ClassSubject main = inspector.clazz(MAIN);
+ assertThat(main, isPresent());
+
+ MethodSubject test = main.uniqueMethodWithName("test");
+ assertThat(test, isPresent());
+ // Should not optimize branches since the type of `arg` is unsure.
+ assertTrue(test.streamInstructions().anyMatch(InstructionSubject::isIf));
+
+ // Should not optimize away Sub1, since it's still referred/instantiated.
+ ClassSubject sub1 = inspector.clazz(Sub1.class);
+ assertThat(sub1, isPresent());
+
+ // Should not optimize away Sub2, since it's still referred/instantiated.
+ ClassSubject sub2 = inspector.clazz(Sub2.class);
+ assertThat(sub2, isPresent());
+ }
+
+ static class Base {}
+ static class Sub1 extends Base {}
+ static class Sub2 extends Base {}
+
+ @NeverClassInline
+ static class Main {
+ public static void main(String... args) {
+ Main obj = new Main();
+ obj.test(new Sub1()); // calls test with Sub1.
+ obj.test(new Sub2()); // calls test with Sub2.
+ }
+
+ @NeverInline
+ private void test(Base arg) {
+ if (arg instanceof Sub1) {
+ System.out.println("Sub1");
+ } else if (arg instanceof Sub2) {
+ System.out.println("Sub2");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeDirectPositiveTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeDirectPositiveTest.java
new file mode 100644
index 0000000..d56d3df
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeDirectPositiveTest.java
@@ -0,0 +1,84 @@
+// Copyright (c) 2019, 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.optimize.callsites.dynamictype;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NeverMerge;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class InvokeDirectPositiveTest extends TestBase {
+ private static final Class<?> MAIN = Main.class;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().build();
+ }
+
+ private final TestParameters parameters;
+
+ public InvokeDirectPositiveTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(InvokeDirectPositiveTest.class)
+ .addKeepMainRule(MAIN)
+ .enableMergeAnnotations()
+ .enableClassInliningAnnotations()
+ .enableInliningAnnotations()
+ .setMinApi(parameters.getRuntime())
+ .run(parameters.getRuntime(), MAIN)
+ .assertSuccessWithOutputLines("Sub1")
+ .inspect(this::inspect);
+ }
+
+ private void inspect(CodeInspector inspector) {
+ ClassSubject main = inspector.clazz(MAIN);
+ assertThat(main, isPresent());
+
+ MethodSubject test = main.uniqueMethodWithName("test");
+ assertThat(test, isPresent());
+ // TODO(b/139246447): Can optimize branches since the type of `arg` is Sub1.
+ assertTrue(test.streamInstructions().anyMatch(InstructionSubject::isIf));
+ }
+
+ @NeverMerge
+ static class Base {}
+ static class Sub1 extends Base {}
+ static class Sub2 extends Base {}
+
+ @NeverClassInline
+ static class Main {
+ public static void main(String... args) {
+ Main obj = new Main();
+ obj.test(new Sub1()); // calls test with Sub1.
+ }
+
+ @NeverInline
+ private void test(Base arg) {
+ if (arg instanceof Sub1) {
+ System.out.println("Sub1");
+ } else if (arg instanceof Sub2) {
+ System.out.println("Sub2");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeInterfaceNegativeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeInterfaceNegativeTest.java
new file mode 100644
index 0000000..4db0012
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeInterfaceNegativeTest.java
@@ -0,0 +1,107 @@
+// Copyright (c) 2019, 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.optimize.callsites.dynamictype;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NeverMerge;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class InvokeInterfaceNegativeTest extends TestBase {
+ private static final Class<?> MAIN = Main.class;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().build();
+ }
+
+ private final TestParameters parameters;
+
+ public InvokeInterfaceNegativeTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(InvokeInterfaceNegativeTest.class)
+ .addKeepMainRule(MAIN)
+ .enableMergeAnnotations()
+ .enableClassInliningAnnotations()
+ .enableInliningAnnotations()
+ .addOptionsModification(o -> {
+ // To prevent invoke-interface from being rewritten to invoke-virtual w/ a single target.
+ o.enableDevirtualization = false;
+ })
+ .setMinApi(parameters.getRuntime())
+ .run(parameters.getRuntime(), MAIN)
+ .assertSuccessWithOutputLines("Sub1", "Sub2")
+ .inspect(this::inspect);
+ }
+
+ private void inspect(CodeInspector inspector) {
+ ClassSubject i = inspector.clazz(I.class);
+ assertThat(i, isPresent());
+
+ ClassSubject a = inspector.clazz(A.class);
+ assertThat(a, isPresent());
+
+ MethodSubject a_m = a.uniqueMethodWithName("m");
+ assertThat(a_m, isPresent());
+ // Should not optimize branches since the type of `arg` is unsure.
+ assertTrue(a_m.streamInstructions().anyMatch(InstructionSubject::isIf));
+
+ // Should not optimize away Sub1, since it's still referred/instantiated.
+ ClassSubject sub1 = inspector.clazz(Sub1.class);
+ assertThat(sub1, isPresent());
+
+ // Should not optimize away Sub2, since it's still referred/instantiated.
+ ClassSubject sub2 = inspector.clazz(Sub2.class);
+ assertThat(sub2, isPresent());
+ }
+
+ static class Base {}
+ static class Sub1 extends Base {}
+ static class Sub2 extends Base {}
+
+ @NeverMerge
+ interface I {
+ void m(Base arg);
+ }
+
+ @NeverClassInline
+ static class A implements I {
+ @NeverInline
+ @Override
+ public void m(Base arg) {
+ if (arg instanceof Sub1) {
+ System.out.println("Sub1");
+ } else if (arg instanceof Sub2) {
+ System.out.println("Sub2");
+ }
+ }
+ }
+
+ static class Main {
+ public static void main(String... args) {
+ I i = new A();
+ i.m(new Sub1()); // calls A.m() with Sub1.
+ i.m(new Sub2()); // calls A.m() with Sub2.
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeInterfacePositiveTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeInterfacePositiveTest.java
new file mode 100644
index 0000000..254b019
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeInterfacePositiveTest.java
@@ -0,0 +1,120 @@
+// Copyright (c) 2019, 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.optimize.callsites.dynamictype;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NeverMerge;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class InvokeInterfacePositiveTest extends TestBase {
+ private static final Class<?> MAIN = Main.class;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().build();
+ }
+
+ private final TestParameters parameters;
+
+ public InvokeInterfacePositiveTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(InvokeInterfacePositiveTest.class)
+ .addKeepMainRule(MAIN)
+ .enableMergeAnnotations()
+ .enableClassInliningAnnotations()
+ .enableInliningAnnotations()
+ .addOptionsModification(o -> {
+ // To prevent invoke-interface from being rewritten to invoke-virtual w/ a single target.
+ o.enableDevirtualization = false;
+ })
+ .setMinApi(parameters.getRuntime())
+ .run(parameters.getRuntime(), MAIN)
+ .assertSuccessWithOutputLines("A:Sub1", "B:Sub2")
+ .inspect(this::inspect);
+ }
+
+ private void inspect(CodeInspector inspector) {
+ ClassSubject i = inspector.clazz(I.class);
+ assertThat(i, isPresent());
+
+ ClassSubject a = inspector.clazz(A.class);
+ assertThat(a, isPresent());
+
+ MethodSubject a_m = a.uniqueMethodWithName("m");
+ assertThat(a_m, isPresent());
+ // TODO(b/139246447): Can optimize branches since the type of `arg` is Sub1.
+ assertTrue(a_m.streamInstructions().anyMatch(InstructionSubject::isIf));
+
+ ClassSubject b = inspector.clazz(B.class);
+ assertThat(b, isPresent());
+
+ MethodSubject b_m = b.uniqueMethodWithName("m");
+ assertThat(b_m, isPresent());
+ // Should not optimize branches since the type of `arg` is unsure.
+ assertTrue(b_m.streamInstructions().anyMatch(InstructionSubject::isIf));
+ }
+
+ @NeverMerge
+ static class Base {}
+ static class Sub1 extends Base {}
+ static class Sub2 extends Base {}
+
+ interface I {
+ void m(Base arg);
+ }
+
+ @NeverClassInline
+ static class A implements I {
+ @NeverInline
+ @Override
+ public void m(Base arg) {
+ if (arg instanceof Sub1) {
+ System.out.println("A:Sub1");
+ } else if (arg instanceof Sub2) {
+ System.out.println("A:Sub2");
+ }
+ }
+ }
+
+ @NeverClassInline
+ static class B implements I {
+ @NeverInline
+ @Override
+ public void m(Base arg) {
+ if (arg instanceof Sub1) {
+ System.out.println("B:Sub1");
+ } else if (arg instanceof Sub2) {
+ System.out.println("B:Sub2");
+ }
+ }
+ }
+
+ static class Main {
+ public static void main(String... args) {
+ I i = System.currentTimeMillis() > 0 ? new A() : new B();
+ i.m(new Sub1()); // calls A.m() with Sub1.
+ new B().m(new Sub2()); // calls B.m() with Sub2.
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeStaticNegativeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeStaticNegativeTest.java
new file mode 100644
index 0000000..1579439
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeStaticNegativeTest.java
@@ -0,0 +1,87 @@
+// Copyright (c) 2019, 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.optimize.callsites.dynamictype;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class InvokeStaticNegativeTest extends TestBase {
+ private static final Class<?> MAIN = Main.class;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().build();
+ }
+
+ private final TestParameters parameters;
+
+ public InvokeStaticNegativeTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(InvokeStaticNegativeTest.class)
+ .addKeepMainRule(MAIN)
+ .enableInliningAnnotations()
+ .setMinApi(parameters.getRuntime())
+ .run(parameters.getRuntime(), MAIN)
+ .assertSuccessWithOutputLines("Sub1", "Sub2")
+ .inspect(this::inspect);
+ }
+
+ private void inspect(CodeInspector inspector) {
+ ClassSubject main = inspector.clazz(MAIN);
+ assertThat(main, isPresent());
+
+ MethodSubject test = main.uniqueMethodWithName("test");
+ assertThat(test, isPresent());
+
+ // Should not optimize branches since the type of `arg` is unsure.
+ assertTrue(test.streamInstructions().anyMatch(InstructionSubject::isIf));
+
+ // Should not optimize away Sub1, since it's still referred/instantiated.
+ ClassSubject sub1 = inspector.clazz(Sub1.class);
+ assertThat(sub1, isPresent());
+
+ // Should not optimize away Sub2, since it's still referred/instantiated.
+ ClassSubject sub2 = inspector.clazz(Sub2.class);
+ assertThat(sub2, isPresent());
+ }
+
+ static class Base {}
+ static class Sub1 extends Base {}
+ static class Sub2 extends Base {}
+
+ static class Main {
+ public static void main(String... args) {
+ test(new Sub1()); // calls test with Sub1.
+ test(new Sub2()); // calls test with Sub2.
+ }
+
+ @NeverInline
+ static void test(Base arg) {
+ if (arg instanceof Sub1) {
+ System.out.println("Sub1");
+ } else if (arg instanceof Sub2) {
+ System.out.println("Sub2");
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeStaticPositiveTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeStaticPositiveTest.java
new file mode 100644
index 0000000..e160788
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeStaticPositiveTest.java
@@ -0,0 +1,81 @@
+// Copyright (c) 2019, 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.optimize.callsites.dynamictype;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NeverMerge;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class InvokeStaticPositiveTest extends TestBase {
+ private static final Class<?> MAIN = Main.class;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().build();
+ }
+
+ private final TestParameters parameters;
+
+ public InvokeStaticPositiveTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(InvokeStaticPositiveTest.class)
+ .addKeepMainRule(MAIN)
+ .enableMergeAnnotations()
+ .enableInliningAnnotations()
+ .setMinApi(parameters.getRuntime())
+ .run(parameters.getRuntime(), MAIN)
+ .assertSuccessWithOutputLines("Sub1")
+ .inspect(this::inspect);
+ }
+
+ private void inspect(CodeInspector inspector) {
+ ClassSubject main = inspector.clazz(MAIN);
+ assertThat(main, isPresent());
+
+ MethodSubject test = main.uniqueMethodWithName("test");
+ assertThat(test, isPresent());
+
+ // TODO(b/139246447): Can optimize branches since the type of `arg` is Sub1.
+ assertTrue(test.streamInstructions().anyMatch(InstructionSubject::isIf));
+ }
+
+ @NeverMerge
+ static class Base {}
+ static class Sub1 extends Base {}
+ static class Sub2 extends Base {}
+
+ static class Main {
+ public static void main(String... args) {
+ test(new Sub1()); // calls test with Sub1.
+ }
+
+ @NeverInline
+ static void test(Base arg) {
+ if (arg instanceof Sub1) {
+ System.out.println("Sub1");
+ } else if (arg instanceof Sub2) {
+ System.out.println("Sub2");
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeVirtualNegativeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeVirtualNegativeTest.java
new file mode 100644
index 0000000..b32e117
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeVirtualNegativeTest.java
@@ -0,0 +1,127 @@
+// Copyright (c) 2019, 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.optimize.callsites.dynamictype;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NeverMerge;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class InvokeVirtualNegativeTest extends TestBase {
+ private static final Class<?> MAIN = Main.class;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().build();
+ }
+
+ private final TestParameters parameters;
+
+ public InvokeVirtualNegativeTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(InvokeVirtualNegativeTest.class)
+ .addKeepMainRule(MAIN)
+ .enableMergeAnnotations()
+ .enableClassInliningAnnotations()
+ .enableInliningAnnotations()
+ .setMinApi(parameters.getRuntime())
+ .run(parameters.getRuntime(), MAIN)
+ .assertSuccessWithOutputLines("A:Sub1", "A:Sub2", "B:Sub1", "B:Sub2")
+ .inspect(this::inspect);
+ }
+
+ private void inspect(CodeInspector inspector) {
+ ClassSubject a = inspector.clazz(A.class);
+ assertThat(a, isPresent());
+
+ MethodSubject a_m = a.uniqueMethodWithName("m");
+ assertThat(a_m, isPresent());
+ // Should not optimize branches since the type of `arg` is unsure.
+ assertTrue(a_m.streamInstructions().anyMatch(InstructionSubject::isIf));
+
+ ClassSubject b = inspector.clazz(B.class);
+ assertThat(b, isPresent());
+
+ MethodSubject b_m = b.uniqueMethodWithName("m");
+ assertThat(b_m, isPresent());
+ // Should not optimize branches since the type of `arg` is unsure.
+ assertTrue(b_m.streamInstructions().anyMatch(InstructionSubject::isIf));
+
+ // Should not optimize away Sub1, since it's still referred/instantiated.
+ ClassSubject sub1 = inspector.clazz(Sub1.class);
+ assertThat(sub1, isPresent());
+
+ // Should not optimize away Sub2, since it's still referred/instantiated.
+ ClassSubject sub2 = inspector.clazz(Sub2.class);
+ assertThat(sub2, isPresent());
+ }
+
+ static class Base {}
+ static class Sub1 extends Base {}
+ static class Sub2 extends Base {}
+
+ @NeverMerge
+ @NeverClassInline
+ static class A {
+ @NeverInline
+ void m(Base arg) {
+ if (arg instanceof Sub1) {
+ System.out.println("A:Sub1");
+ } else if (arg instanceof Sub2) {
+ System.out.println("A:Sub2");
+ }
+ }
+ }
+
+ @NeverClassInline
+ static class B extends A {
+ @NeverInline
+ @Override
+ void m(Base arg) {
+ if (arg instanceof Sub1) {
+ System.out.println("B:Sub1");
+ } else if (arg instanceof Sub2) {
+ System.out.println("B:Sub2");
+ }
+ }
+ }
+
+ static class Main {
+ public static void main(String... args) {
+ Sub2 s2 = new Sub2();
+
+ A a = new A();
+ test(a); // calls A.m() with Sub1.
+ a.m(s2); // calls A.m() with Sub2.
+
+ B b = new B();
+ test(b); // calls B.m() with Sub1.
+ b.m(s2); // calls B.m() with Sub2.
+ }
+
+ @NeverInline
+ static void test(A arg) {
+ arg.m(new Sub1());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeVirtualPositiveTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeVirtualPositiveTest.java
new file mode 100644
index 0000000..95b091b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamictype/InvokeVirtualPositiveTest.java
@@ -0,0 +1,113 @@
+// Copyright (c) 2019, 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.optimize.callsites.dynamictype;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NeverMerge;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class InvokeVirtualPositiveTest extends TestBase {
+ private static final Class<?> MAIN = Main.class;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().build();
+ }
+
+ private final TestParameters parameters;
+
+ public InvokeVirtualPositiveTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(InvokeVirtualPositiveTest.class)
+ .addKeepMainRule(MAIN)
+ .enableMergeAnnotations()
+ .enableClassInliningAnnotations()
+ .enableInliningAnnotations()
+ .setMinApi(parameters.getRuntime())
+ .run(parameters.getRuntime(), MAIN)
+ .assertSuccessWithOutputLines("A:Sub1", "B:Sub1")
+ .inspect(this::inspect);
+ }
+
+ private void inspect(CodeInspector inspector) {
+ ClassSubject a = inspector.clazz(A.class);
+ assertThat(a, isPresent());
+
+ MethodSubject a_m = a.uniqueMethodWithName("m");
+ assertThat(a_m, isPresent());
+ // TODO(b/139246447): Can optimize branches since the type of `arg` is Sub1.
+ assertTrue(a_m.streamInstructions().anyMatch(InstructionSubject::isIf));
+
+ ClassSubject b = inspector.clazz(B.class);
+ assertThat(b, isPresent());
+
+ MethodSubject b_m = b.uniqueMethodWithName("m");
+ assertThat(b_m, isPresent());
+ // TODO(b/139246447): Can optimize branches since the type of `arg` is Sub1.
+ assertTrue(b_m.streamInstructions().anyMatch(InstructionSubject::isIf));
+ }
+
+ @NeverMerge
+ static class Base {}
+ static class Sub1 extends Base {}
+ static class Sub2 extends Base {}
+
+ @NeverMerge
+ @NeverClassInline
+ static class A {
+ @NeverInline
+ void m(Base arg) {
+ if (arg instanceof Sub1) {
+ System.out.println("A:Sub1");
+ } else if (arg instanceof Sub2) {
+ System.out.println("A:Sub2");
+ }
+ }
+ }
+
+ @NeverClassInline
+ static class B extends A {
+ @NeverInline
+ @Override
+ void m(Base arg) {
+ if (arg instanceof Sub1) {
+ System.out.println("B:Sub1");
+ } else if (arg instanceof Sub2) {
+ System.out.println("B:Sub2");
+ }
+ }
+ }
+
+ static class Main {
+ public static void main(String... args) {
+ Sub1 s1 = new Sub1();
+
+ A a = System.currentTimeMillis() > 0 ? new A() : new B();
+ a.m(s1); // calls A.m() with Sub1.
+
+ B b = new B();
+ b.m(s1); // calls B.m() with Sub1.
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeDirectNegativeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeDirectNegativeTest.java
index b2be29c..859365b 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeDirectNegativeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeDirectNegativeTest.java
@@ -5,7 +5,7 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
@@ -55,7 +55,7 @@
MethodSubject test = main.uniqueMethodWithName("test");
assertThat(test, isPresent());
// Should not optimize branches since the nullability of `arg` is unsure.
- assertNotEquals(0, test.streamInstructions().filter(InstructionSubject::isIf).count());
+ assertTrue(test.streamInstructions().anyMatch(InstructionSubject::isIf));
}
@NeverClassInline
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeDirectPositiveTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeDirectPositiveTest.java
index 0ebf6b9..9eef5ac 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeDirectPositiveTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeDirectPositiveTest.java
@@ -5,7 +5,7 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
@@ -57,7 +57,7 @@
MethodSubject test = main.uniqueMethodWithName("test");
assertThat(test, isPresent());
// Can optimize branches since `arg` is definitely not null.
- assertEquals(0, test.streamInstructions().filter(InstructionSubject::isIf).count());
+ assertTrue(test.streamInstructions().noneMatch(InstructionSubject::isIf));
}
@NeverClassInline
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeInterfaceNegativeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeInterfaceNegativeTest.java
index ca42813..9d4e509 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeInterfaceNegativeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeInterfaceNegativeTest.java
@@ -5,7 +5,7 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
@@ -64,7 +64,7 @@
MethodSubject a_m = a.uniqueMethodWithName("m");
assertThat(a_m, isPresent());
// Should not optimize branches since the nullability of `arg` is unsure.
- assertNotEquals(0, a_m.streamInstructions().filter(InstructionSubject::isIf).count());
+ assertTrue(a_m.streamInstructions().anyMatch(InstructionSubject::isIf));
}
@NeverMerge
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeInterfacePositiveTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeInterfacePositiveTest.java
index 797bde4..ae8ef12 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeInterfacePositiveTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeInterfacePositiveTest.java
@@ -5,7 +5,7 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
@@ -64,7 +64,7 @@
MethodSubject a_m = a.uniqueMethodWithName("m");
assertThat(a_m, isPresent());
// Can optimize branches since `arg` is definitely not null.
- assertEquals(0, a_m.streamInstructions().filter(InstructionSubject::isIf).count());
+ assertTrue(a_m.streamInstructions().noneMatch(InstructionSubject::isIf));
ClassSubject b = inspector.clazz(B.class);
assertThat(b, isPresent());
@@ -72,7 +72,7 @@
MethodSubject b_m = b.uniqueMethodWithName("m");
assertThat(b_m, isPresent());
// Can optimize branches since `arg` is definitely not null.
- assertEquals(0, b_m.streamInstructions().filter(InstructionSubject::isIf).count());
+ assertTrue(b_m.streamInstructions().noneMatch(InstructionSubject::isIf));
}
interface I {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeStaticNegativeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeStaticNegativeTest.java
index 8ffb330..5d10e42 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeStaticNegativeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeStaticNegativeTest.java
@@ -5,7 +5,7 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
@@ -53,7 +53,7 @@
MethodSubject test = main.uniqueMethodWithName("test");
assertThat(test, isPresent());
// Should not optimize branches since the nullability of `arg` is unsure.
- assertNotEquals(0, test.streamInstructions().filter(InstructionSubject::isIf).count());
+ assertTrue(test.streamInstructions().anyMatch(InstructionSubject::isIf));
}
static class Main {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeStaticPositiveTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeStaticPositiveTest.java
index c37e990..53c9f8f 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeStaticPositiveTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeStaticPositiveTest.java
@@ -5,7 +5,7 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
@@ -55,7 +55,7 @@
MethodSubject test = main.uniqueMethodWithName("test");
assertThat(test, isPresent());
// Can optimize branches since `arg` is definitely not null.
- assertEquals(0, test.streamInstructions().filter(InstructionSubject::isIf).count());
+ assertTrue(test.streamInstructions().noneMatch(InstructionSubject::isIf));
}
static class Main {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualCascadeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualCascadeTest.java
index 11ff032..d313c03 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualCascadeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualCascadeTest.java
@@ -5,7 +5,7 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
@@ -57,7 +57,7 @@
MethodSubject a_m = a.uniqueMethodWithName("m");
assertThat(a_m, isPresent());
// TODO(b/139246447): Can optimize branches since `arg` is definitely not null.
- assertNotEquals(0, a_m.streamInstructions().filter(InstructionSubject::isIf).count());
+ assertTrue(a_m.streamInstructions().anyMatch(InstructionSubject::isIf));
ClassSubject b = inspector.clazz(B.class);
assertThat(b, isPresent());
@@ -65,7 +65,7 @@
MethodSubject b_m = b.uniqueMethodWithName("m");
assertThat(b_m, isPresent());
// TODO(b/139246447): Can optimize branches since `arg` is definitely not null.
- assertNotEquals(0, b_m.streamInstructions().filter(InstructionSubject::isIf).count());
+ assertTrue(b_m.streamInstructions().anyMatch(InstructionSubject::isIf));
}
@NeverMerge
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualNegativeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualNegativeTest.java
index f45a2d3..45976a0 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualNegativeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualNegativeTest.java
@@ -5,7 +5,7 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
@@ -57,7 +57,7 @@
MethodSubject a_m = a.uniqueMethodWithName("m");
assertThat(a_m, isPresent());
// Should not optimize branches since the nullability of `arg` is unsure.
- assertNotEquals(0, a_m.streamInstructions().filter(InstructionSubject::isIf).count());
+ assertTrue(a_m.streamInstructions().anyMatch(InstructionSubject::isIf));
ClassSubject b = inspector.clazz(B.class);
assertThat(b, isPresent());
@@ -65,7 +65,7 @@
MethodSubject b_m = b.uniqueMethodWithName("m");
assertThat(b_m, isPresent());
// Should not optimize branches since the nullability of `arg` is unsure.
- assertNotEquals(0, b_m.streamInstructions().filter(InstructionSubject::isIf).count());
+ assertTrue(a_m.streamInstructions().anyMatch(InstructionSubject::isIf));
}
@NeverMerge
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualPositiveTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualPositiveTest.java
index deb3204..bc4d0a7 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualPositiveTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualPositiveTest.java
@@ -5,7 +5,7 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
@@ -59,7 +59,7 @@
MethodSubject a_m = a.uniqueMethodWithName("m");
assertThat(a_m, isPresent());
// Can optimize branches since `arg` is definitely not null.
- assertEquals(0, a_m.streamInstructions().filter(InstructionSubject::isIf).count());
+ assertTrue(a_m.streamInstructions().noneMatch(InstructionSubject::isIf));
ClassSubject b = inspector.clazz(B.class);
assertThat(b, isPresent());
@@ -67,7 +67,7 @@
MethodSubject b_m = b.uniqueMethodWithName("m");
assertThat(b_m, isPresent());
// Can optimize branches since `arg` is definitely not null.
- assertEquals(0, b_m.streamInstructions().filter(InstructionSubject::isIf).count());
+ assertTrue(b_m.streamInstructions().noneMatch(InstructionSubject::isIf));
}
@NeverMerge
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/KeptMethodTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/KeptMethodTest.java
index 6e647a9..d77c180 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/KeptMethodTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/KeptMethodTest.java
@@ -5,7 +5,7 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
@@ -57,7 +57,7 @@
MethodSubject m = a.uniqueMethodWithName("m");
assertThat(m, isPresent());
// Should not optimize branches since the method is kept, accessed via reflection.
- assertNotEquals(0, m.streamInstructions().filter(InstructionSubject::isIf).count());
+ assertTrue(m.streamInstructions().anyMatch(InstructionSubject::isIf));
}
@NeverClassInline
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/WithStaticizerTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/WithStaticizerTest.java
index 48eaa92..79ea92e 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/WithStaticizerTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/WithStaticizerTest.java
@@ -6,7 +6,7 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
@@ -62,7 +62,7 @@
MethodSubject foo = host.uniqueMethodWithName("foo");
assertThat(foo, isPresent());
// TODO(b/139246447): Can optimize branches since `arg` is definitely not null.
- assertNotEquals(0, foo.streamInstructions().filter(InstructionSubject::isIf).count());
+ assertTrue(foo.streamInstructions().anyMatch(InstructionSubject::isIf));
}
@NeverClassInline