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