Fix the workaround for overlapping long registers art bug.
We compute candidate registers in two places but only one of them
had the workaround code.
Creating a small test case is hard, so I added another full app
verification test to the suite to catch this.
R=sgjesse@google.com
Bug:
Change-Id: I00e7b77966edbdd6924f49dbe95e78f745fc8384
diff --git a/build.gradle b/build.gradle
index 0663b8a..45eade1 100644
--- a/build.gradle
+++ b/build.gradle
@@ -151,6 +151,7 @@
"gmscore/v8.tar.gz",
"gmscore/gmscore_v9.tar.gz",
"gmscore/gmscore_v10.tar.gz",
+ "photos/2017-06-06.tar.gz",
"youtube/youtube.android_11.47.tar.gz",
"youtube/youtube.android_12.10.tar.gz",
"youtube/youtube.android_12.17.tar.gz",
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 a981990..3a96ac2 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
@@ -870,7 +870,7 @@
assert leftReg != NO_REGISTER && rightReg != NO_REGISTER;
// The dalvik bug is actually only for overlap with the second operand, For now we
// make sure that there is no overlap with either operand.
- if ((leftReg + 1) == register|| (rightReg + 1) == register) {
+ if ((leftReg + 1) == register || (rightReg + 1) == register) {
return true;
}
return false;
@@ -977,14 +977,8 @@
// Get the register (pair) that is free the longest. That is the register with the largest
// free position.
- int candidate = getLargestCandidate(registerConstraint, freePositions, needsRegisterPair);
- if (needsOverlappingLongRegisterWorkaround(unhandledInterval)) {
- while (hasOverlappingLongRegisters(unhandledInterval, candidate)) {
- // Make the overlapping register unavailable for allocation and try again.
- freePositions.set(candidate, 0);
- candidate = getLargestCandidate(registerConstraint, freePositions, needsRegisterPair);
- }
- }
+ int candidate = getLargestValidCandidate(
+ unhandledInterval, registerConstraint, needsRegisterPair, freePositions);
int largestFreePosition = freePositions.get(candidate);
if (needsRegisterPair) {
largestFreePosition = Math.min(largestFreePosition, freePositions.get(candidate + 1));
@@ -1162,6 +1156,19 @@
return candidate;
}
+ private int getLargestValidCandidate(LiveIntervals unhandledInterval, int registerConstraint,
+ boolean needsRegisterPair, RegisterPositions freePositions) {
+ int candidate = getLargestCandidate(registerConstraint, freePositions, needsRegisterPair);
+ if (needsOverlappingLongRegisterWorkaround(unhandledInterval)) {
+ while (hasOverlappingLongRegisters(unhandledInterval, candidate)) {
+ // Make the overlapping register unavailable for allocation and try again.
+ freePositions.set(candidate, 0);
+ candidate = getLargestCandidate(registerConstraint, freePositions, needsRegisterPair);
+ }
+ }
+ return candidate;
+ }
+
private void allocateBlockedRegister(LiveIntervals unhandledInterval) {
int registerConstraint = unhandledInterval.getRegisterLimit();
if (registerConstraint < Constants.U16BIT_MAX) {
@@ -1225,9 +1232,9 @@
inactive, unhandledInterval, registerConstraint, usePositions, blockedPositions);
// Get the register (pair) that has the highest use position.
- assert unhandledInterval.requiredRegisters() <= 2;
boolean needsRegisterPair = unhandledInterval.requiredRegisters() == 2;
- int candidate = getLargestCandidate(registerConstraint, usePositions, needsRegisterPair);
+ int candidate = getLargestValidCandidate(
+ unhandledInterval, registerConstraint, needsRegisterPair, usePositions);
int largestUsePosition = usePositions.get(candidate);
int blockedPosition = blockedPositions.get(candidate);
if (needsRegisterPair) {
diff --git a/src/test/java/com/android/tools/r8/internal/D8PhotosVerificationTest.java b/src/test/java/com/android/tools/r8/internal/D8PhotosVerificationTest.java
new file mode 100644
index 0000000..de72fb2
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/internal/D8PhotosVerificationTest.java
@@ -0,0 +1,29 @@
+// 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.internal;
+
+import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
+import com.android.tools.r8.shaking.ProguardRuleParserException;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import org.junit.Test;
+
+public class D8PhotosVerificationTest extends CompilationTestBase {
+ public static final String PHOTOS =
+ "third_party/photos/2017-06-06/PhotosEnglishOnlyLegacy_proguard.jar";
+
+ public void runD8AndCheckVerification(CompilationMode mode, String version)
+ throws ProguardRuleParserException, ExecutionException, IOException, CompilationException {
+ runAndCheckVerification(
+ CompilerUnderTest.D8, mode, version, null, null, version);
+ }
+
+ @Test
+ public void verify()
+ throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+ runD8AndCheckVerification(CompilationMode.RELEASE, PHOTOS);
+ }
+}
diff --git a/third_party/photos/2017-06-06.tar.gz.sha1 b/third_party/photos/2017-06-06.tar.gz.sha1
new file mode 100644
index 0000000..b21e5a6
--- /dev/null
+++ b/third_party/photos/2017-06-06.tar.gz.sha1
@@ -0,0 +1 @@
+80389d76881463daf28b47f402c5013f499966bf
\ No newline at end of file