Version 0.1.21. R=sgjesse@google.com Merge: Fix bug in inactive linked interval splitting. CL: https://r8-review.googlesource.com/c/r8/+/9680 Change-Id: I2bf1f016bfa6e2cb302b541c5e62cdb3c1798e8c
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java index d9c37c0..70ad1f6 100644 --- a/src/main/java/com/android/tools/r8/D8.java +++ b/src/main/java/com/android/tools/r8/D8.java
@@ -55,7 +55,7 @@ */ public final class D8 { - private static final String VERSION = "v0.1.20"; + private static final String VERSION = "v0.1.21"; private static final int STATUS_ERROR = 1; private D8() {}
diff --git a/src/main/java/com/android/tools/r8/GenerateMainDexList.java b/src/main/java/com/android/tools/r8/GenerateMainDexList.java index 77917af..7c34d93 100644 --- a/src/main/java/com/android/tools/r8/GenerateMainDexList.java +++ b/src/main/java/com/android/tools/r8/GenerateMainDexList.java
@@ -28,7 +28,7 @@ import java.util.stream.Collectors; public class GenerateMainDexList { - private static final String VERSION = "v0.1.20"; + private static final String VERSION = "v0.1.21"; private final Timing timing = new Timing("maindex"); private final InternalOptions options;
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java index 3378afa..1a6e1b0 100644 --- a/src/main/java/com/android/tools/r8/R8.java +++ b/src/main/java/com/android/tools/r8/R8.java
@@ -71,7 +71,7 @@ public class R8 { - private static final String VERSION = "v0.1.20"; + private static final String VERSION = "v0.1.21"; private final Timing timing = new Timing("R8"); private final InternalOptions options;
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 d99e854..82b7c5e 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
@@ -137,9 +137,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 = + protected PriorityQueue<LiveIntervals> unhandled = new PriorityQueue<>(Comparator.comparingInt(LiveIntervals::getStart)); // The first register used for parallel moves. After register allocation the parallel move @@ -1553,7 +1553,7 @@ splitOverlappingInactiveIntervals(unhandledInterval, needsRegisterPair, candidate); } - private void splitOverlappingInactiveIntervals( + protected void splitOverlappingInactiveIntervals( LiveIntervals unhandledInterval, boolean needsRegisterPair, int candidate) { @@ -1565,10 +1565,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/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..c3a177d --- /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.MoveType; +import com.android.tools.r8.ir.code.Value; +import com.android.tools.r8.ir.code.ValueNumberGenerator; +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(valueNumberGenerator, new InternalOptions()); + 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, MoveType.SINGLE, 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, MoveType.SINGLE, 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, MoveType.SINGLE, 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; + } +}