Merge "Fix run_on_app.py for gmscore and Youtube"
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 2efe014..11cc9bc 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -308,7 +308,8 @@
         }
       }
 
-      if (!rootSet.checkDiscarded.isEmpty()) {
+      // Only perform discard-checking if tree-shaking is turned on.
+      if (options.useTreeShaking && !rootSet.checkDiscarded.isEmpty()) {
         new DiscardedChecker(rootSet, application).run();
       }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java b/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
index 4cca9dd..0ccf076 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
@@ -90,7 +90,7 @@
   @Override
   public void buildDex(DexBuilder builder) {
     if (!dest().needsRegister()) {
-      builder.addNop(this);
+      builder.addFallThrough(this);
       return;
     }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java b/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
index 4e078a5..28d6b2b 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
@@ -35,7 +35,7 @@
 
   @Override
   public void buildDex(DexBuilder builder) {
-    builder.addNop(this);
+    builder.addDebugPosition(this);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
index 50afe5f..a306bbd 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
@@ -44,6 +44,7 @@
 import com.android.tools.r8.ir.code.Argument;
 import com.android.tools.r8.ir.code.BasicBlock;
 import com.android.tools.r8.ir.code.CatchHandlers;
+import com.android.tools.r8.ir.code.DebugPosition;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.code.If;
 import com.android.tools.r8.ir.code.InstructionIterator;
@@ -331,8 +332,13 @@
   public void addGoto(com.android.tools.r8.ir.code.Goto jump) {
     if (jump.getTarget() != nextBlock) {
       add(jump, new GotoInfo(jump));
+      return;
+    }
+    List<com.android.tools.r8.ir.code.Instruction> instructions = jump.getBlock().getInstructions();
+    if (instructions.size() > 1) {
+      addFallThroughOrNop(jump, instructions.get(instructions.size() - 2), nextBlock.entry());
     } else {
-      addNop(jump);
+      addFallThrough(jump);
     }
   }
 
@@ -345,10 +351,32 @@
     add(move, new MoveInfo(move));
   }
 
-  public void addNop(com.android.tools.r8.ir.code.Instruction instruction) {
+  public void addFallThrough(com.android.tools.r8.ir.code.Instruction instruction) {
     add(instruction, new FallThroughInfo(instruction));
   }
 
+  private void addFallThroughOrNop(
+      com.android.tools.r8.ir.code.Instruction key,
+      com.android.tools.r8.ir.code.Instruction instruction,
+      com.android.tools.r8.ir.code.Instruction nextInstruction) {
+    if (nextInstruction != null
+        && instruction.isDebugPosition()
+        && nextInstruction.isDebugPosition()) {
+      add(key, new FixedSizeInfo(key, new Nop()));
+    } else {
+      addFallThrough(key);
+    }
+  }
+
+  public void addDebugPosition(DebugPosition position) {
+    BasicBlock block = position.getBlock();
+    int nextIndex = block.getInstructions().indexOf(position) + 1;
+    List<com.android.tools.r8.ir.code.Instruction> instructions = block.getInstructions();
+    com.android.tools.r8.ir.code.Instruction nextInstruction =
+        nextIndex < instructions.size() ? instructions.get(nextIndex) : null;
+    addFallThroughOrNop(position, position, nextInstruction);
+  }
+
   public void add(com.android.tools.r8.ir.code.Instruction ir, Instruction dex) {
     assert !ir.isGoto();
     add(ir, new FixedSizeInfo(ir, dex));
diff --git a/src/test/java/com/android/tools/r8/JctfTestSpecifications.java b/src/test/java/com/android/tools/r8/JctfTestSpecifications.java
index f7cbee8..d548e11 100644
--- a/src/test/java/com/android/tools/r8/JctfTestSpecifications.java
+++ b/src/test/java/com/android/tools/r8/JctfTestSpecifications.java
@@ -7,6 +7,7 @@
 import static com.android.tools.r8.TestCondition.D8_COMPILER;
 import static com.android.tools.r8.TestCondition.R8_AFTER_D8_COMPILER;
 import static com.android.tools.r8.TestCondition.R8_COMPILER;
+import static com.android.tools.r8.TestCondition.R8_NOT_AFTER_D8_COMPILER;
 import static com.android.tools.r8.TestCondition.any;
 import static com.android.tools.r8.TestCondition.match;
 import static com.android.tools.r8.TestCondition.runtimes;
@@ -4415,7 +4416,7 @@
           // 1) t02
           // java.lang.AssertionError: Failed to load serialization resource file: serialization/com/google/jctf/test/lib/java/util/concurrent/PriorityBlockingQueue/serialization/PriorityBlockingQueue_serialization_A01.golden.0.ser
 
-          .put("lang.ThreadGroup.destroy.ThreadGroup_destroy_A01", match(R8_COMPILER))
+          .put("lang.ThreadGroup.destroy.ThreadGroup_destroy_A01", match(R8_NOT_AFTER_D8_COMPILER))
           // 1) t05
           // java.lang.AssertionError: Destroyed thread group was not finalized
 
diff --git a/src/test/java/com/android/tools/r8/debuginfo/BackBranchToSelfTestRunner.java b/src/test/java/com/android/tools/r8/debuginfo/BackBranchToSelfTestRunner.java
index ebd1b0b..24eae68 100644
--- a/src/test/java/com/android/tools/r8/debuginfo/BackBranchToSelfTestRunner.java
+++ b/src/test/java/com/android/tools/r8/debuginfo/BackBranchToSelfTestRunner.java
@@ -27,14 +27,8 @@
   }
 
   private void checkBackBranchToSelf(DebugInfoInspector info, boolean dx) {
-    if (dx) {
-      info.checkStartLine(10);
-      // b/37494646 D8/R8 if-simplification has replaced if by a goto and lost this position.
-      info.checkLineHasExactLocals(10, "loop", "boolean");
-    } else {
-      // D8/R8 will always start at the first debuggable line.
-      info.checkStartLine(13);
-    }
+    info.checkStartLine(10);
+    info.checkLineHasExactLocals(10, "loop", "boolean");
     info.checkNoLine(11);
     info.checkNoLine(12);
     info.checkLineHasExactLocals(13, "loop", "boolean");
diff --git a/src/test/java/com/android/tools/r8/jasmin/JumpSubroutineDebugInfoTests.java b/src/test/java/com/android/tools/r8/jasmin/JumpSubroutineDebugInfoTests.java
index d0d1e83..f5254fc 100644
--- a/src/test/java/com/android/tools/r8/jasmin/JumpSubroutineDebugInfoTests.java
+++ b/src/test/java/com/android/tools/r8/jasmin/JumpSubroutineDebugInfoTests.java
@@ -60,8 +60,7 @@
     assertEquals(expected, artResult);
 
     DebugInfoInspector info = new DebugInfoInspector(d8App, clazz.name, foo);
-    // The first debuggable line will be line 3.
-    info.checkStartLine(3);
+    info.checkStartLine(1);
     // Check the subroutine line is duplicated 3 times.
     assertEquals(3, info.checkLineHasExactLocals(3, "x", "int"));
   }