Merge "Refine type information for MemberType and remove unneeded type from ConstNumber."
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index ad23c03..e93f147 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -218,7 +218,7 @@
 
       ProguardConfiguration.Builder configurationBuilder;
       if (proguardConfigs.isEmpty()) {
-        configurationBuilder = ProguardConfiguration.builderInitializedWithDefaults(factory);
+        configurationBuilder = ProguardConfiguration.builder(factory);
       } else {
         ProguardConfigurationParser parser =
             new ProguardConfigurationParser(factory, getDiagnosticsHandler());
diff --git a/src/main/java/com/android/tools/r8/ir/code/Invoke.java b/src/main/java/com/android/tools/r8/ir/code/Invoke.java
index 55d52dc..ba10ed5 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Invoke.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Invoke.java
@@ -138,7 +138,8 @@
     return true;
   }
 
-  protected void addInvokeAndMoveResult(com.android.tools.r8.code.Instruction instruction, DexBuilder builder) {
+  protected void addInvokeAndMoveResult(
+      com.android.tools.r8.code.Instruction instruction, DexBuilder builder) {
     if (outValue != null && outValue.needsRegister()) {
       MoveType moveType = MoveType.fromValueType(outType());
       int register = builder.allocatedRegister(outValue, getNumber());
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java
index 8f6ae85..62c5cc9 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java
@@ -285,7 +285,8 @@
             }
             int outRegister = allocator.getRegisterForValue(outValue, instructionNumber);
             ConstNumber numberInRegister = registerToNumber.get(outRegister);
-            if (numberInRegister != null && numberInRegister.identicalNonValueNonPositionParts(current)) {
+            if (numberInRegister != null
+                && numberInRegister.identicalNonValueNonPositionParts(current)) {
               // This instruction is not needed, the same constant is already in this register.
               // We don't consider the positions of the two (non-throwing) instructions.
               iterator.remove();
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
index 523d6db..5783ad4 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
@@ -136,9 +136,9 @@
   // List of active intervals.
   private List<LiveIntervals> active = new LinkedList<>();
   // List of intervals where the current instruction falls into one of their live range holes.
-  private List<LiveIntervals> inactive = new LinkedList<>();
+  protected List<LiveIntervals> inactive = new LinkedList<>();
   // List of intervals that no register has been allocated to sorted by first live range.
-  private PriorityQueue<LiveIntervals> unhandled = new PriorityQueue<>();
+  protected PriorityQueue<LiveIntervals> unhandled = new PriorityQueue<>();
 
   // The first register used for parallel moves. After register allocation the parallel move
   // temporary registers are [firstParallelMoveTemporary, maxRegisterNumber].
@@ -1517,7 +1517,7 @@
     splitOverlappingInactiveIntervals(unhandledInterval, needsRegisterPair, candidate);
   }
 
-  private void splitOverlappingInactiveIntervals(
+  protected void splitOverlappingInactiveIntervals(
       LiveIntervals unhandledInterval,
       boolean needsRegisterPair,
       int candidate) {
@@ -1529,10 +1529,16 @@
           (needsRegisterPair && intervals.usesRegister(candidate + 1))) &&
           intervals.overlaps(unhandledInterval)) {
         if (intervals.isLinked() && !intervals.isArgumentInterval()) {
+          // If the inactive register is linked but not an argument, it needs to get the
+          // same register again at the next use after the start of the unhandled interval.
+          // If there are no such uses, we can use a different register for the remainder
+          // of the inactive interval and therefore do not have to split here.
           int nextUsePosition = intervals.firstUseAfter(unhandledInterval.getStart());
-          LiveIntervals split = intervals.splitBefore(nextUsePosition);
-          split.setRegister(intervals.getRegister());
-          newInactive.add(split);
+          if (nextUsePosition != Integer.MAX_VALUE) {
+            LiveIntervals split = intervals.splitBefore(nextUsePosition);
+            split.setRegister(intervals.getRegister());
+            newInactive.add(split);
+          }
         }
         if (intervals.getStart() > unhandledInterval.getStart()) {
           // The inactive live intervals hasn't started yet. Clear the temporary register
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
index bdf7748..f8aa3e2 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
@@ -18,13 +18,13 @@
 
     private final List<FilteredClassPath> injars = new ArrayList<>();
     private final List<FilteredClassPath> libraryjars = new ArrayList<>();
-    private PackageObfuscationMode packageObfuscationMode;
-    private String packagePrefix;
+    private PackageObfuscationMode packageObfuscationMode = PackageObfuscationMode.NONE;
+    private String packagePrefix = "";
     private boolean allowAccessModification;
     private boolean ignoreWarnings;
-    private boolean optimizing;
-    private boolean obfuscating;
-    private boolean shrinking;
+    private boolean optimizing = true;
+    private boolean obfuscating = true;
+    private boolean shrinking = true;
     private boolean printUsage;
     private Path printUsageFile;
     private boolean printMapping;
@@ -49,37 +49,6 @@
 
     private Builder(DexItemFactory dexItemFactory) {
       this.dexItemFactory = dexItemFactory;
-      resetProguardDefaults();
-    }
-
-    public void resetProguardDefaults() {
-      injars.clear();
-      libraryjars.clear();
-      packageObfuscationMode = PackageObfuscationMode.NONE;
-      packagePrefix = "";
-      allowAccessModification = false;
-      ignoreWarnings = false;
-      optimizing = true;
-      obfuscating = true;
-      shrinking = true;
-      printUsage = false;
-      printUsageFile = null;
-      printMapping = false;
-      printMappingFile = null;
-      applyMappingFile = null;
-      verbose = false;
-      renameSourceFileAttribute = null;
-      keepAttributePatterns.clear();
-      dontWarnPatterns = ProguardClassFilter.builder();
-      rules.clear();
-      printSeeds = false;
-      seedFile = null;
-      obfuscationDictionary = null;
-      classObfuscationDictionary = null;
-      packageObfuscationDictionary = null;
-      useUniqueClassMemberNames = false;
-      keepParameterNames = false;
-      adaptClassStrings = ProguardClassFilter.builder();
     }
 
     public void addInjars(List<FilteredClassPath> injars) {
@@ -217,11 +186,16 @@
     }
 
     public ProguardConfiguration build() throws CompilationException {
-      ProguardKeepAttributes keepAttributes;
+      boolean rulesWasEmpty = rules.isEmpty();
+      if (rulesWasEmpty) {
+        setObfuscating(false);
+        setShrinking(false);
+        addRule(ProguardKeepRule.defaultKeepAllRule());
+      }
 
-      if (forceProguardCompatibility
-          && !isObfuscating()
-          && keepAttributePatterns.size() == 0) {
+      ProguardKeepAttributes keepAttributes;
+      if (keepAttributePatterns.isEmpty()
+          && (rulesWasEmpty || (forceProguardCompatibility && !isObfuscating()))) {
         keepAttributes = ProguardKeepAttributes.fromPatterns(ProguardKeepAttributes.KEEP_ALL);
       } else {
         keepAttributes = ProguardKeepAttributes.fromPatterns(keepAttributePatterns);
@@ -358,15 +332,6 @@
     return new Builder(dexItemFactory);
   }
 
-  public static Builder builderInitializedWithDefaults(DexItemFactory dexItemFactory) {
-    Builder builder = new Builder(dexItemFactory);
-    builder.setObfuscating(false);
-    builder.setShrinking(false);
-    builder.addKeepAttributePatterns(ProguardKeepAttributes.KEEP_ALL);
-    builder.addRule(ProguardKeepRule.defaultKeepAllRule());
-    return builder;
-  }
-
   public DexItemFactory getDexItemFactory() {
     return dexItemFactory;
   }
@@ -481,7 +446,7 @@
 
   public static ProguardConfiguration defaultConfiguration(DexItemFactory dexItemFactory) {
     try {
-      return builderInitializedWithDefaults(dexItemFactory).build();
+      return builder(dexItemFactory).build();
     } catch (CompilationException e) {
       // Building a builder initialized with defaults will not throw CompilationException because
       // DictionaryReader is called with empty lists.
diff --git a/src/test/java/com/android/tools/r8/ir/regalloc/Regress68656641.java b/src/test/java/com/android/tools/r8/ir/regalloc/Regress68656641.java
new file mode 100644
index 0000000..1d17e31
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/regalloc/Regress68656641.java
@@ -0,0 +1,83 @@
+// 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.ir.regalloc;
+
+import com.android.tools.r8.graph.DexApplication;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.code.Value;
+import com.android.tools.r8.ir.code.ValueNumberGenerator;
+import com.android.tools.r8.ir.code.ValueType;
+import com.android.tools.r8.smali.SmaliTestBase;
+import com.android.tools.r8.utils.InternalOptions;
+import com.google.common.collect.ImmutableList;
+import java.util.PriorityQueue;
+import org.junit.Test;
+
+public class Regress68656641 extends SmaliTestBase {
+
+  private static class MyRegisterAllocator extends LinearScanRegisterAllocator {
+    public MyRegisterAllocator(IRCode code, InternalOptions options) {
+      super(code, options);
+    }
+
+    public void addInactiveIntervals(LiveIntervals intervals) {
+      inactive.add(intervals);
+    }
+
+    public void splitOverlappingInactiveIntervals(LiveIntervals intervals, int register) {
+      splitOverlappingInactiveIntervals(intervals, false, register);
+    }
+
+    public PriorityQueue<LiveIntervals> getUnhandled() {
+      return unhandled;
+    }
+  }
+
+  IRCode simpleCode(InternalOptions options) throws Exception {
+    SmaliBuilder builder = new SmaliBuilder(DEFAULT_CLASS_NAME);
+    MethodSignature signature = builder.addStaticMethod(
+        "void",
+        DEFAULT_METHOD_NAME,
+        ImmutableList.of(),
+        1,
+        "    return-void");
+    DexApplication application = buildApplication(builder, options);
+    // Build the code, and split the code into three blocks.
+    ValueNumberGenerator valueNumberGenerator = new ValueNumberGenerator();
+    DexEncodedMethod method = getMethod(application, signature);
+    IRCode code = method.buildIR(new InternalOptions(), valueNumberGenerator);
+    return code;
+  }
+
+
+  @Test
+  public void splitOverlappingInactiveIntervalWithNoNextUse() throws Exception {
+    InternalOptions options = new InternalOptions();
+    IRCode code = simpleCode(options);
+    MyRegisterAllocator allocator = new MyRegisterAllocator(code, options);
+    // Setup live an inactive live interval with ranges [0, 10[ and [20, 30[ with only
+    // uses in the first interval and which is linked to another interval.
+    LiveIntervals inactiveIntervals = new LiveIntervals(new Value(0, ValueType.INT, null));
+    inactiveIntervals.addRange(new LiveRange(0, 10));
+    inactiveIntervals.addUse(new LiveIntervalsUse(0, 10));
+    inactiveIntervals.addUse(new LiveIntervalsUse(4, 10));
+    inactiveIntervals.addRange(new LiveRange(20, 30));
+    inactiveIntervals.setRegister(0);
+    LiveIntervals linked = new LiveIntervals(new Value(1, ValueType.INT, null));
+    linked.setRegister(1);
+    inactiveIntervals.link(linked);
+    allocator.addInactiveIntervals(inactiveIntervals);
+    // Setup an unhandled interval that overlaps the inactive interval.
+    LiveIntervals unhandledIntervals = new LiveIntervals(new Value(2, ValueType.INT, null));
+    unhandledIntervals.addRange(new LiveRange(12, 24));
+    // Split the overlapping inactive intervals and check that after the split, the second
+    // part of the inactive interval is unhandled and will therefore get a new register
+    // assigned later during allocation.
+    allocator.splitOverlappingInactiveIntervals(unhandledIntervals, 0);
+    assert allocator.getUnhandled().size() == 1;
+    assert allocator.getUnhandled().peek().getStart() == 20;
+    assert allocator.getUnhandled().peek().getEnd() == 30;
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java b/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java
index c4af25c..6306f91 100644
--- a/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java
+++ b/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java
@@ -91,11 +91,9 @@
     checkAnnotationContent(INPUT_PATH, result);
   }
 
-  /**
-   * Check that when dontshrink and dontobfuscate is used the annotation is transmitted.
-   */
+  /** Check that when dontshrink and dontobfuscate is used the annotation is transmitted. */
   @Test
-  public void testSourceDebugExtensionWithShriking1()
+  public void testSourceDebugExtensionWithShrinking1()
       throws IOException, CompilationException, ExecutionException {
     Path outputPath = tmpOutputDir.newFolder().toPath();
     AndroidApp result = compileWithR8(INPUT_PATH, outputPath, DONT_SHRINK_DONT_OBFUSCATE_CONFIG);
@@ -125,7 +123,7 @@
   }
 
   /**
-   * Check that the annotation is removed when shriking is enabled and that there is not
+   * Check that the annotation is removed when shrinking is enabled and that there is not
    * keepattributes option.
    */
   @Test
diff --git a/src/test/java/com/android/tools/r8/naming/RenameSourceFileDebugTest.java b/src/test/java/com/android/tools/r8/naming/RenameSourceFileDebugTest.java
index 46991d6..046a14b 100644
--- a/src/test/java/com/android/tools/r8/naming/RenameSourceFileDebugTest.java
+++ b/src/test/java/com/android/tools/r8/naming/RenameSourceFileDebugTest.java
@@ -31,8 +31,6 @@
             compileToDexViaR8(
                 null,
                 pg -> {
-                  pg.resetProguardDefaults();
-                  pg.addRule(ProguardKeepRule.defaultKeepAllRule());
                   pg.setRenameSourceFileAttribute(TEST_FILE);
                   pg.addKeepAttributePatterns(ImmutableList.of("SourceFile", "LineNumberTable"));
                 },
diff --git a/src/test/java/com/android/tools/r8/utils/R8CommandTest.java b/src/test/java/com/android/tools/r8/utils/R8CommandTest.java
index 2054b22..6dda185 100644
--- a/src/test/java/com/android/tools/r8/utils/R8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/utils/R8CommandTest.java
@@ -229,7 +229,7 @@
     R8Command command = parse("@" + argsFile.toString());
     assertEquals(CompilationMode.DEBUG, command.getMode());
     assertFalse(command.useMinification());
-    assertTrue(command.useTreeShaking());
+    assertFalse(command.useTreeShaking()); // We have no keep rules (proguard config file is empty).
     assertEquals(1, ToolHelper.getApp(command).getDexProgramResources().size());
   }