Version 2.0.74

Cherry-pick: Don't replace local writes by phi introduced locals.
CL: https://r8-review.googlesource.com/48222

Bug: 148661132
Bug: 156142802
Change-Id: Iab815abe01e6db2c7b9bdf86b2e0715d7a5a2a4f
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index 98ff11a..f031f30 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 = "2.0.73";
+  public static final String LABEL = "2.0.74";
 
   private Version() {
   }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index d157111..6c04583 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -2180,15 +2180,6 @@
 
   public void simplifyDebugLocals(IRCode code) {
     for (BasicBlock block : code.blocks) {
-      for (Phi phi : block.getPhis()) {
-        if (!phi.hasLocalInfo() && phi.numberOfUsers() == 1 && phi.numberOfAllUsers() == 1) {
-          Instruction instruction = phi.singleUniqueUser();
-          if (instruction.isDebugLocalWrite()) {
-            removeDebugWriteOfPhi(code, phi, instruction.asDebugLocalWrite());
-          }
-        }
-      }
-
       InstructionListIterator iterator = block.listIterator(code);
       while (iterator.hasNext()) {
         Instruction prevInstruction = iterator.peekPrevious();
@@ -2222,29 +2213,6 @@
     }
   }
 
-  private void removeDebugWriteOfPhi(IRCode code, Phi phi, DebugLocalWrite write) {
-    assert write.src() == phi;
-    InstructionListIterator iterator = phi.getBlock().listIterator(code);
-    while (iterator.hasNext()) {
-      Instruction next = iterator.next();
-      if (!next.isDebugLocalWrite()) {
-        // If the debug write is not in the block header bail out.
-        return;
-      }
-      if (next == write) {
-        // Associate the phi with the local.
-        phi.setLocalInfo(write.getLocalInfo());
-        // Replace uses of the write with the phi.
-        write.outValue().replaceUsers(phi);
-        // Safely remove the write.
-        // TODO(zerny): Once phis become instructions, move debug values there instead of a nop.
-        iterator.removeOrReplaceByDebugLocalRead();
-        return;
-      }
-      assert next.getLocalInfo().name != write.getLocalInfo().name;
-    }
-  }
-
   private static class CSEExpressionEquivalence extends Equivalence<Instruction> {
 
     private final InternalOptions options;
diff --git a/src/test/java/com/android/tools/r8/debug/Regress148661132Test.java b/src/test/java/com/android/tools/r8/debug/Regress148661132Test.java
new file mode 100644
index 0000000..ae64de7
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/debug/Regress148661132Test.java
@@ -0,0 +1,100 @@
+// 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.debug;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+@RunWith(Parameterized.class)
+public class Regress148661132Test extends TestBase {
+
+  private final TestParameters parameters;
+
+  @Parameterized.Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withNoneRuntime().build();
+  }
+
+  public Regress148661132Test(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  @Test
+  public void test() throws Exception {
+    testForD8().setMinApi(AndroidApiLevel.B).addProgramClassFileData(FlafKtDump.dump()).compile();
+  }
+
+  static class FlafKtDump implements Opcodes {
+
+    public static byte[] dump() {
+
+      ClassWriter cw = new ClassWriter(0);
+      cw.visit(V1_6, ACC_PUBLIC | ACC_FINAL | ACC_SUPER, "FlafKt", null, "java/lang/Object", null);
+      cw.visitSource("Flaf.kt", null);
+      cw.visitInnerClass("FlafKt$inlineFun$1", null, null, ACC_PUBLIC | ACC_FINAL | ACC_STATIC);
+
+      MethodVisitor mv =
+          cw.visitMethod(
+              ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC,
+              "inlineFun$default",
+              "(LA;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)LA;",
+              null,
+              null);
+      mv.visitCode();
+      mv.visitVarInsn(ILOAD, 2);
+      mv.visitInsn(ICONST_2);
+      mv.visitInsn(IAND);
+      Label label0 = new Label();
+      mv.visitJumpInsn(IFEQ, label0);
+      mv.visitTypeInsn(NEW, "FlafKt$inlineFun$1");
+      mv.visitInsn(DUP);
+      mv.visitVarInsn(ALOAD, 0);
+      mv.visitMethodInsn(INVOKESPECIAL, "FlafKt$inlineFun$1", "<init>", "(LA;)V", false);
+      mv.visitTypeInsn(CHECKCAST, "kotlin/jvm/functions/Function0");
+      mv.visitVarInsn(ASTORE, 1);
+      mv.visitLabel(label0);
+      mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
+      mv.visitVarInsn(ALOAD, 1);
+      mv.visitVarInsn(ASTORE, 4);
+      Label label1 = new Label();
+      // The delayed introduction of the local variable causes a write after the phi.
+      // That write should not be replaced as it invalidates the assumption of local info
+      // associated with phis.
+      mv.visitLabel(label1);
+      mv.visitInsn(ICONST_0);
+      mv.visitVarInsn(ISTORE, 5);
+      Label label2 = new Label();
+      mv.visitLabel(label2);
+      mv.visitLineNumber(13, label2);
+      mv.visitVarInsn(ALOAD, 4);
+      mv.visitMethodInsn(
+          INVOKEINTERFACE,
+          "kotlin/jvm/functions/Function0",
+          "invoke",
+          "()Ljava/lang/Object;",
+          true);
+      mv.visitTypeInsn(CHECKCAST, "A");
+      Label label3 = new Label();
+      mv.visitLabel(label3);
+      mv.visitInsn(ARETURN);
+      mv.visitLocalVariable("$i$f$inlineFun", "I", null, label2, label3, 5);
+      mv.visitLocalVariable(
+          "lambda$iv", "Lkotlin/jvm/functions/Function0;", null, label1, label3, 4);
+      mv.visitMaxs(3, 6);
+      mv.visitEnd();
+
+      cw.visitEnd();
+      return cw.toByteArray();
+    }
+  }
+}