Reland: Remove DebugLocalWrite when it is possible

- It allows to D8 to generate smaller code in debug mode. It save about
12k on framework and 46k on GMSCore v10.

Bug: 66161160
Change-Id: I5c9c3e6abdc817aba3f469a395bdde9b72d76b6d
diff --git a/src/test/debugTestResources/Locals.java b/src/test/debugTestResources/Locals.java
index 205ae64..71f2a66 100644
--- a/src/test/debugTestResources/Locals.java
+++ b/src/test/debugTestResources/Locals.java
@@ -346,6 +346,13 @@
     return c + d;
   }
 
+  public static int intAddition(int a, int b, int c) {
+    a += b;
+    b += c;
+    c = a + b;
+    return c;
+  }
+
   public static void main(String[] args) {
     noLocals();
     unusedLocals();
@@ -369,5 +376,6 @@
     System.out.println(localConstant(true));
     System.out.println(localConstantBis(true));
     System.out.println(localTriggeringCSE());
+    System.out.println(intAddition(1, 2, 6));
   }
 }
diff --git a/src/test/java/com/android/tools/r8/debug/LocalsTest.java b/src/test/java/com/android/tools/r8/debug/LocalsTest.java
index 177efbe..c86581f 100644
--- a/src/test/java/com/android/tools/r8/debug/LocalsTest.java
+++ b/src/test/java/com/android/tools/r8/debug/LocalsTest.java
@@ -648,4 +648,37 @@
         checkLocal("d", Value.createInt(5)),
         run());
   }
+
+  /**
+   * Companion test with dex inspection
+   * {@link com.android.tools.r8.debuginfo.CodeGeneratorTestRunner#test2AddrInstruction}
+   */
+  @Test
+  public void testLocalUsedBy2AddrInstruction() throws Throwable {
+    final String className = "Locals";
+    final String methodName = "intAddition";
+    runDebugTest(className,
+        breakpoint(className, methodName),
+        run(),
+        checkLine(SOURCE_FILE, 350),
+        checkLocal("a", Value.createInt(1)),
+        checkLocal("b", Value.createInt(2)),
+        checkLocal("c", Value.createInt(6)),
+        stepOver(),
+        checkLine(SOURCE_FILE, 351),
+        checkLocal("a", Value.createInt(3)),
+        checkLocal("b", Value.createInt(2)),
+        checkLocal("c", Value.createInt(6)),
+        stepOver(),
+        checkLine(SOURCE_FILE, 352),
+        checkLocal("a", Value.createInt(3)),
+        checkLocal("b", Value.createInt(8)),
+        checkLocal("c", Value.createInt(6)),
+        stepOver(),
+        checkLine(SOURCE_FILE, 353),
+        checkLocal("a", Value.createInt(3)),
+        checkLocal("b", Value.createInt(8)),
+        checkLocal("c", Value.createInt(11)),
+        run());
+  }
 }
diff --git a/src/test/java/com/android/tools/r8/debuginfo/CodeGeneratorTest.java b/src/test/java/com/android/tools/r8/debuginfo/CodeGeneratorTest.java
new file mode 100644
index 0000000..a586502
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/debuginfo/CodeGeneratorTest.java
@@ -0,0 +1,18 @@
+// Copyright (c) 2017, 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.debuginfo;
+
+public class CodeGeneratorTest {
+
+  public static int intAddition(int a, int b, int c) {
+    a += b;
+    b += c;
+    c = a + b;
+    return c;
+  }
+
+  public static void main(String[] args) {
+    System.out.print(intAddition(1, 2, 6));
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/debuginfo/CodeGeneratorTestRunner.java b/src/test/java/com/android/tools/r8/debuginfo/CodeGeneratorTestRunner.java
new file mode 100644
index 0000000..062a4d3
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/debuginfo/CodeGeneratorTestRunner.java
@@ -0,0 +1,43 @@
+// Copyright (c) 2017, 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.debuginfo;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.code.AddInt;
+import com.android.tools.r8.code.AddInt2Addr;
+import com.android.tools.r8.code.Instruction;
+import com.android.tools.r8.code.Return;
+import com.android.tools.r8.utils.AndroidApp;
+import org.junit.Test;
+
+public class CodeGeneratorTestRunner extends DebugInfoTestBase {
+
+  /**
+   * Companion test checking the behavior when attached to a debugger
+   * {@link com.android.tools.r8.debug.LocalsTest#testLocalUsedBy2AddrInstruction}
+   */
+  @Test
+  public void test2AddrInstruction() throws Exception {
+    Class clazz = CodeGeneratorTest.class;
+
+    AndroidApp d8App = compileWithD8(clazz);
+    AndroidApp dxApp = getDxCompiledSources();
+
+    String expected = "11";
+    assertEquals(expected, runOnJava(clazz));
+    assertEquals(expected, runOnArt(d8App, clazz.getCanonicalName()));
+    assertEquals(expected, runOnArt(dxApp, clazz.getCanonicalName()));
+
+    DebugInfoInspector inspector = inspectMethod(d8App, clazz, "int", "intAddition", "int", "int",
+        "int");
+    Instruction[] instructions = inspector.getMethod().getCode().asDexCode().instructions;
+    assertTrue(instructions[0] instanceof AddInt2Addr);
+    assertTrue(instructions[1] instanceof AddInt2Addr);
+    assertTrue(instructions[2] instanceof AddInt);
+    assertTrue(instructions[3] instanceof Return);
+  }
+
+}