Merge "Always rematerialize single-width numeric constants."
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 a54208d..67a4783 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
@@ -1549,8 +1549,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 d199f37..4099912 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -488,18 +488,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();
}