Merge "Make usage of basic block marks more explicit"
diff --git a/src/main/java/com/android/tools/r8/graph/DexType.java b/src/main/java/com/android/tools/r8/graph/DexType.java
index 6544ea9..e9a84fa 100644
--- a/src/main/java/com/android/tools/r8/graph/DexType.java
+++ b/src/main/java/com/android/tools/r8/graph/DexType.java
@@ -76,7 +76,7 @@
}
}
- void addDirectSubtype(DexType type) {
+ synchronized void addDirectSubtype(DexType type) {
assert hierarchyLevel != UNKNOWN_LEVEL;
ensureDirectSubTypeSet();
directSubtypes.add(type);
@@ -96,7 +96,7 @@
return hierarchyLevel == INTERFACE_LEVEL;
}
- void addInterfaceSubtype(DexType type) {
+ synchronized void addInterfaceSubtype(DexType type) {
// Interfaces all inherit from java.lang.Object. However, we assign a special level to
// identify them later on.
setLevel(INTERFACE_LEVEL);
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 2c0e3b0..7af0451 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
@@ -73,7 +73,6 @@
public static final int REGISTER_CANDIDATE_NOT_FOUND = -1;
public static final int MIN_CONSTANT_FREE_FOR_POSITIONS = 5;
- private static final int RESERVED_MOVE_EXCEPTION_REGISTER = 0;
private enum ArgumentReuseMode {
ALLOW_ARGUMENT_REUSE,
@@ -142,9 +141,6 @@
// List of intervals that no register has been allocated to sorted by first live range.
protected PriorityQueue<LiveIntervals> unhandled = new PriorityQueue<>();
- // List of intervals for the result of move-exception instructions.
- private List<LiveIntervals> moveExceptionIntervals = new ArrayList<>();
-
// The first register used for parallel moves. After register allocation the parallel move
// temporary registers are [firstParallelMoveTemporary, maxRegisterNumber].
private int firstParallelMoveTemporary = NO_REGISTER;
@@ -157,11 +153,6 @@
// register.
private boolean hasDedicatedMoveExceptionRegister = false;
- private int getMoveExceptionRegister() {
- return numberOfArgumentRegisters + NUMBER_OF_SENTINEL_REGISTERS +
- RESERVED_MOVE_EXCEPTION_REGISTER;
- }
-
public LinearScanRegisterAllocator(IRCode code, InternalOptions options) {
this.code = code;
this.options = options;
@@ -672,7 +663,6 @@
active.clear();
inactive.clear();
unhandled.clear();
- moveExceptionIntervals.clear();
for (LiveIntervals intervals : liveIntervals) {
intervals.clearRegisterAssignment();
}
@@ -762,6 +752,7 @@
// Force all move exception ranges to start out with the exception in a fixed register. Split
// their live ranges which will force another register if used.
int moveExceptionRegister = NO_REGISTER;
+ List<LiveIntervals> moveExceptionIntervals = new ArrayList<>();
boolean overlappingMoveExceptionIntervals = false;
for (BasicBlock block : code.blocks) {
for (Instruction instruction : block.getInstructions()) {
@@ -770,12 +761,8 @@
Value exceptionValue = instruction.outValue();
LiveIntervals intervals = exceptionValue.getLiveIntervals();
unhandled.remove(intervals);
- moveExceptionIntervals.add(intervals);
if (moveExceptionRegister == NO_REGISTER) {
- assert RESERVED_MOVE_EXCEPTION_REGISTER == 0;
moveExceptionRegister = getFreeConsecutiveRegisters(1);
- assert moveExceptionRegister == getMoveExceptionRegister();
- assert !freeRegisters.contains(moveExceptionRegister);
}
intervals.setRegister(moveExceptionRegister);
if (!overlappingMoveExceptionIntervals) {
@@ -783,6 +770,7 @@
overlappingMoveExceptionIntervals |= other.overlaps(intervals);
}
}
+ moveExceptionIntervals.add(intervals);
}
}
}
@@ -1136,47 +1124,6 @@
return false;
}
- // Intervals overlap a move exception interval if one of the splits of the intervals does.
- // Since spill and restore moves are always put after the move exception we cannot give
- // a non-move exception interval the same register as a move exception instruction.
- //
- // For example:
- //
- // B0:
- // const v0, 0
- // invoke throwing_method v0 (catch handler B2)
- // goto B1
- // B1:
- // ...
- // B2:
- // move-exception v1
- // invoke method v0
- // return
- //
- // During register allocation we could split the const number intervals into multiple
- // parts. We have to avoid assigning the same register to v1 and and v0 in B0 even
- // if v0 has a different register in B2. That is because the spill/restore move when
- // transitioning from B0 to B2 has to be after the move-exception instruction.
- //
- // Assuming that v0 has register 0 in B0 and register 4 in B2 and v1 has register 0 in B2
- // we would generate the following incorrect code:
- //
- // B0:
- // const r0, 0
- // invoke throwing_method r0 (catch handler B2)
- // goto B1
- // B1:
- // ...
- // B2:
- // move-exception r0
- // move r4, r0 // Whoops.
- // invoke method r4
- // return
- private boolean overlapsMoveExceptionInterval(LiveIntervals intervals) {
- return hasDedicatedMoveExceptionRegister &&
- moveExceptionIntervals.stream().anyMatch((i) -> intervals.anySplitOverlaps(i));
- }
-
private boolean allocateSingleInterval(LiveIntervals unhandledInterval, ArgumentReuseMode mode) {
int registerConstraint = unhandledInterval.getRegisterLimit();
assert registerConstraint <= Constants.U16BIT_MAX;
@@ -1235,8 +1182,8 @@
// register. If we cannot find a free valid register for the move exception value we have no
// place to put a spill move (because the move exception instruction has to be the
// first instruction in the handler block).
- if (overlapsMoveExceptionInterval(unhandledInterval)) {
- int moveExceptionRegister = getMoveExceptionRegister();
+ if (hasDedicatedMoveExceptionRegister) {
+ int moveExceptionRegister = numberOfArgumentRegisters + NUMBER_OF_SENTINEL_REGISTERS;
if (moveExceptionRegister <= registerConstraint) {
freePositions.set(moveExceptionRegister, 0);
}
@@ -1583,8 +1530,8 @@
}
// Disallow reuse of the move exception register if we have reserved one.
- if (overlapsMoveExceptionInterval(unhandledInterval)) {
- usePositions.set(getMoveExceptionRegister(), 0);
+ if (hasDedicatedMoveExceptionRegister) {
+ usePositions.set(numberOfArgumentRegisters + NUMBER_OF_SENTINEL_REGISTERS, 0);
}
// Treat active linked argument intervals as pinned. They cannot be given another register
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/LiveIntervals.java b/src/main/java/com/android/tools/r8/ir/regalloc/LiveIntervals.java
index 2bbdaf9..b6d8b79 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/LiveIntervals.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/LiveIntervals.java
@@ -325,19 +325,6 @@
return nextOverlap(other) != -1;
}
- public boolean anySplitOverlaps(LiveIntervals other) {
- LiveIntervals parent = getSplitParent();
- if (parent.overlaps(other)) {
- return true;
- }
- for (LiveIntervals child : parent.getSplitChildren()) {
- if (child.overlaps(other)) {
- return true;
- }
- }
- return false;
- }
-
public int nextOverlap(LiveIntervals other) {
Iterator<LiveRange> it = other.ranges.iterator();
LiveRange otherRange = it.next();