Version 1.4.31

Cherry pick: Also consider targeted methods for if-rule evaluation
CL: https://r8-review.googlesource.com/c/r8/+/33489

Bug: 122940365
Change-Id: I9b6db08b1852dd730e7f334f642251deadd0d074
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index 115fe4a..cf756ef 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
 
   // This field is accessed from release scripts using simple pattern matching.
   // Therefore, changing this field could break our release scripts.
-  public static final String LABEL = "1.4.30";
+  public static final String LABEL = "1.4.31";
 
   private Version() {
   }
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 86a4a8d..0761a71 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -1460,7 +1460,10 @@
               new RootSetBuilder(appView, rootSet.ifRules, options);
           IfRuleEvaluator ifRuleEvaluator =
               consequentSetBuilder.getIfRuleEvaluator(
-                  liveMethods.getItems(), liveFields.getItems(), executorService);
+                  liveFields.getItems(),
+                  liveMethods.getItems(),
+                  targetedMethods.getItems(),
+                  executorService);
           ConsequentRootSet consequentRootSet = ifRuleEvaluator.run(liveTypes);
           enqueueRootItems(consequentRootSet.noShrinking);
           rootSet.neverInline.addAll(consequentRootSet.neverInline);
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
index a0da9e7..2a8ce8f 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -277,26 +277,31 @@
   }
 
   IfRuleEvaluator getIfRuleEvaluator(
-      Set<DexEncodedMethod> liveMethods,
       Set<DexEncodedField> liveFields,
+      Set<DexEncodedMethod> liveMethods,
+      Set<DexEncodedMethod> targetedMethods,
       ExecutorService executorService) {
-    return new IfRuleEvaluator(liveMethods, liveFields, executorService);
+    return new IfRuleEvaluator(liveFields, liveMethods, targetedMethods, executorService);
   }
 
   class IfRuleEvaluator {
 
-    private final Set<DexEncodedMethod> liveMethods;
     private final Set<DexEncodedField> liveFields;
+    private final Set<DexEncodedMethod> liveMethods;
+    private final Set<DexEncodedMethod> targetedMethods;
+
     private final ExecutorService executorService;
 
     private final List<Future<?>> futures = new ArrayList<>();
 
     public IfRuleEvaluator(
-        Set<DexEncodedMethod> liveMethods,
         Set<DexEncodedField> liveFields,
+        Set<DexEncodedMethod> liveMethods,
+        Set<DexEncodedMethod> targetedMethods,
         ExecutorService executorService) {
-      this.liveMethods = liveMethods;
       this.liveFields = liveFields;
+      this.liveMethods = liveMethods;
+      this.targetedMethods = targetedMethods;
       this.executorService = executorService;
     }
 
@@ -391,7 +396,7 @@
           filteredMembers,
           targetClass.methods(
               m ->
-                  liveMethods.contains(m)
+                  (liveMethods.contains(m) || targetedMethods.contains(m))
                       && appView.graphLense().getOriginalMethodSignature(m.method).getHolder()
                           == sourceClass.type));
 
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/IfOnTargetedMethodTest.java b/src/test/java/com/android/tools/r8/shaking/ifrule/IfOnTargetedMethodTest.java
new file mode 100644
index 0000000..edf2b89
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/ifrule/IfOnTargetedMethodTest.java
@@ -0,0 +1,68 @@
+// 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.shaking.ifrule;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed;
+import static org.junit.Assert.assertThat;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import java.lang.reflect.Proxy;
+import org.junit.Test;
+
+public class IfOnTargetedMethodTest extends TestBase {
+
+  @Test
+  public void test() throws Exception {
+    String expectedOutput = StringUtils.lines("Hello world!");
+
+    testForJvm().addTestClasspath().run(TestClass.class).assertSuccessWithOutput(expectedOutput);
+
+    CodeInspector inspector =
+        testForR8(Backend.DEX)
+            .addInnerClasses(IfOnTargetedMethodTest.class)
+            .addKeepMainRule(TestClass.class)
+            .addKeepRules(
+                "-if interface * { @" + MyAnnotation.class.getTypeName() + " <methods>; }",
+                "-keep,allowobfuscation interface <1>")
+            .run(TestClass.class)
+            .assertSuccessWithOutput(expectedOutput)
+            .inspector();
+
+    ClassSubject interfaceSubject = inspector.clazz(Interface.class);
+    assertThat(interfaceSubject, isPresent());
+    assertThat(interfaceSubject, isRenamed());
+  }
+
+  static class TestClass {
+
+    public static void main(String[] args) {
+      Interface obj = getInstance();
+      obj.method();
+    }
+
+    static Interface getInstance() {
+      return (Interface)
+          Proxy.newProxyInstance(
+              Interface.class.getClassLoader(),
+              new Class[] {Interface.class},
+              (o, method, objects) -> {
+                System.out.println("Hello world!");
+                return null;
+              });
+    }
+  }
+
+  interface Interface {
+
+    @MyAnnotation
+    void method();
+  }
+
+  @interface MyAnnotation {}
+}