Fix bug in virtual method merging of preoptimized methods

Bug: 163311975
Change-Id: I83aa9108aacd45e29c5788849e73fea596dbaf95
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java
index 0f9fdc1..b26d2ea 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/VirtualMethodMerger.java
@@ -154,12 +154,12 @@
     }
 
     // Use the first of the original methods as the original method for the merged constructor.
+    DexMethod templateReference = methods.iterator().next().getReference();
     DexMethod originalMethodReference =
-        appView.graphLens().getOriginalMethodSignature(methods.iterator().next().getReference());
+        appView.graphLens().getOriginalMethodSignature(templateReference);
 
     DexMethod newMethodReference =
-        dexItemFactory.createMethod(
-            target.type, originalMethodReference.proto, originalMethodReference.name);
+        dexItemFactory.createMethod(target.type, templateReference.proto, templateReference.name);
     AbstractSynthesizedCode synthesizedCode =
         new VirtualMethodEntryPointSynthesizedCode(
             classIdToMethodMap,
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/VerticalMergingPreoptimizedTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/VerticalMergingPreoptimizedTest.java
new file mode 100644
index 0000000..7731d5e
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/VerticalMergingPreoptimizedTest.java
@@ -0,0 +1,99 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.classmerging.horizontal;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsNot.not;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NoHorizontalClassMerging;
+import com.android.tools.r8.TestParameters;
+import org.junit.Test;
+
+public class VerticalMergingPreoptimizedTest extends HorizontalClassMergingTestBase {
+
+  public VerticalMergingPreoptimizedTest(
+      TestParameters parameters, boolean enableHorizontalClassMerging) {
+    super(parameters, enableHorizontalClassMerging);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addInnerClasses(getClass())
+        .addKeepMainRule(Main.class)
+        .addOptionsModification(
+            options -> options.enableHorizontalClassMerging = enableHorizontalClassMerging)
+        .enableInliningAnnotations()
+        .enableNeverClassInliningAnnotations()
+        .enableNoHorizontalClassMergingAnnotations()
+        .setMinApi(parameters.getApiLevel())
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(
+            "changed", "print a", "foo", "print b", "foo", "unused argument")
+        .inspect(
+            codeInspector -> {
+              assertThat(codeInspector.clazz(Parent.class), not(isPresent()));
+              assertThat(codeInspector.clazz(Changed.class), isPresent());
+              assertThat(codeInspector.clazz(A.class), isPresent());
+              assertThat(
+                  codeInspector.clazz(B.class), notIf(isPresent(), enableHorizontalClassMerging));
+            });
+  }
+
+  @NeverClassInline
+  @NoHorizontalClassMerging
+  public static class Parent {
+    @NeverInline
+    public void foo() {
+      System.out.println("foo");
+    }
+  }
+
+  @NeverClassInline
+  @NoHorizontalClassMerging
+  public static class Changed extends Parent {
+    public Changed() {
+      System.out.println("changed");
+    }
+  }
+
+  @NeverClassInline
+  public static class A {
+    @NeverInline
+    public void print(Parent p) {
+      System.out.println("print a");
+      p.foo();
+    }
+  }
+
+  @NeverClassInline
+  public static class B {
+    @NeverInline
+    public void print(Parent p) {
+      System.out.println("print b");
+      p.foo();
+    }
+
+    @NeverInline
+    public void unusedArgument(Parent p) {
+      System.out.println("unused argument");
+    }
+  }
+
+  public static class Main {
+    public static void main(String[] args) {
+      Parent p = new Changed();
+      A a = new A();
+      B b = new B();
+      a.print(p);
+      b.print(p);
+      b.unusedArgument(p);
+    }
+  }
+}