Version 1.0.23
Merge: Always rematerialize single-width numeric constants.
CL: https://r8-review.googlesource.com/c/r8/+/19884
Change-Id: I778c3cfa86f57d4034dca79272b6d23431ffa1c5
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index ab1f699..76e9fbf 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
// This field is accessed from release scripts using simple pattern matching.
// Therefore, changing this field could break our release scripts.
- public static final String LABEL = "v1.0.22";
+ public static final String LABEL = "v1.0.23";
private Version() {
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index 54efe87..61cd3e7 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -1294,8 +1294,7 @@
insertAt.nextUntil(i ->
i.inValues().contains(instruction.outValue())
|| i.isJumpInstruction()
- || (hasCatchHandlers && i.instructionTypeCanThrow())
- || (options.canHaveBoundsCheckEliminationBug() && i.isArrayLength()));
+ || (hasCatchHandlers && i.instructionTypeCanThrow()));
Instruction next = insertAt.previous();
instruction.forceSetPosition(
next.isGoto() ? next.asGoto().getTarget().getPosition() : next.getPosition());
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/SpillMoveSet.java b/src/main/java/com/android/tools/r8/ir/regalloc/SpillMoveSet.java
index 2dbc015..3dc151d 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/SpillMoveSet.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/SpillMoveSet.java
@@ -296,8 +296,18 @@
scheduler.addMove(
new RegisterMove(move.to.getRegister(), move.type, move.from.getValue().definition));
} else if (move.to.getRegister() != move.from.getRegister()) {
- scheduler.addMove(
- new RegisterMove(move.to.getRegister(), move.from.getRegister(), move.type));
+ // In case the runtime might have a bound-check elimination bug we make sure to define all
+ // indexing constants with an actual const instruction rather than a move. This appears to
+ // avoid a bug where the index variable could end up being uninitialized.
+ if (code.options.canHaveBoundsCheckEliminationBug()
+ && move.from.getValue().isConstNumber()
+ && move.type == MoveType.SINGLE) {
+ scheduler.addMove(
+ new RegisterMove(move.to.getRegister(), move.type, move.from.getValue().definition));
+ } else {
+ scheduler.addMove(
+ new RegisterMove(move.to.getRegister(), move.from.getRegister(), move.type));
+ }
}
}
scheduler.schedule();
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 45834d7..6a92af6 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -451,18 +451,16 @@
// Some Lollipop versions of Art found in the wild perform invalid bounds
// check elimination. There is a fast path of loops and a slow path.
// The bailout to the slow path is performed too early and therefore
- // the loop variable might not be defined in the slow path code leading
+ // the array-index variable might not be defined in the slow path code leading
// to use of undefined registers as indices into arrays. The result
// is ArrayIndexOutOfBounds exceptions.
//
- // In an attempt to help these Art VMs get the loop variable initialized
- // early, we do not lower constants past array-length instructions when
- // building for Lollipop or below.
+ // In an attempt to help these Art VMs, all single-width constants are initialized and not moved.
//
// There is no guarantee that this works, but it does make the problem
// disappear on the one known instance of this problem.
//
- // See b/69364976.
+ // See b/69364976 and b/77996377.
public boolean canHaveBoundsCheckEliminationBug() {
return minApiLevel <= AndroidApiLevel.L.getLevel();
}