Mirror def-use setup for normal values and debug-local values.
R=ager, shertz
Change-Id: Ia00c4004c79df5e13517ae4b262801ba03138584
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArithmeticBinop.java b/src/main/java/com/android/tools/r8/ir/code/ArithmeticBinop.java
index 8a001ae..49adcb4 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ArithmeticBinop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ArithmeticBinop.java
@@ -59,26 +59,26 @@
int left = leftValue().getConstInstruction().asConstNumber().getIntValue();
int right = rightValue().getConstInstruction().asConstNumber().getIntValue();
int result = foldIntegers(left, right);
- Value value = code.createValue(MoveType.SINGLE, getDebugInfo());
+ Value value = code.createValue(MoveType.SINGLE, getLocalInfo());
return new ConstNumber(ConstType.INT, value, result);
} else if (type == NumericType.LONG) {
long left = leftValue().getConstInstruction().asConstNumber().getLongValue();
long right = rightValue().getConstInstruction().asConstNumber().getLongValue();
long result = foldLongs(left, right);
- Value value = code.createValue(MoveType.WIDE, getDebugInfo());
+ Value value = code.createValue(MoveType.WIDE, getLocalInfo());
return new ConstNumber(ConstType.LONG, value, result);
} else if (type == NumericType.FLOAT) {
float left = leftValue().getConstInstruction().asConstNumber().getFloatValue();
float right = rightValue().getConstInstruction().asConstNumber().getFloatValue();
float result = foldFloat(left, right);
- Value value = code.createValue(MoveType.SINGLE, getDebugInfo());
+ Value value = code.createValue(MoveType.SINGLE, getLocalInfo());
return new ConstNumber(ConstType.FLOAT, value, Float.floatToIntBits(result));
} else {
assert type == NumericType.DOUBLE;
double left = leftValue().getConstInstruction().asConstNumber().getDoubleValue();
double right = rightValue().getConstInstruction().asConstNumber().getDoubleValue();
double result = foldDouble(left, right);
- Value value = code.createValue(MoveType.WIDE, getDebugInfo());
+ Value value = code.createValue(MoveType.WIDE, getLocalInfo());
return new ConstNumber(ConstType.DOUBLE, value, Double.doubleToLongBits(result));
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
index 5f1b33f..80100da 100644
--- a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
+++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
@@ -575,10 +575,6 @@
for (Value value : instruction.getDebugValues()) {
value.removeDebugUser(instruction);
}
- Value previousLocalValue = instruction.getPreviousLocalValue();
- if (previousLocalValue != null) {
- previousLocalValue.removeDebugUser(instruction);
- }
}
}
}
@@ -1144,7 +1140,7 @@
// Remove the move-exception instruction.
move = entry().asMoveException();
position = move.getPosition();
- assert move.getPreviousLocalValue() == null;
+ assert move.getDebugValues().isEmpty();
getInstructions().remove(0);
}
// Create new predecessor blocks.
@@ -1158,8 +1154,7 @@
BasicBlock newBlock = new BasicBlock();
newPredecessors.add(newBlock);
if (hasMoveException) {
- Value value = new Value(
- valueNumberGenerator.next(), MoveType.OBJECT, move.getDebugInfo());
+ Value value = new Value(valueNumberGenerator.next(), MoveType.OBJECT, move.getLocalInfo());
values.add(value);
MoveException newMove = new MoveException(value);
newBlock.add(newMove);
diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionIterator.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionIterator.java
index 968e560..140f579 100644
--- a/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionIterator.java
+++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionIterator.java
@@ -114,10 +114,6 @@
for (Value value : current.getDebugValues()) {
value.removeDebugUser(current);
}
- Value previousLocalValue = current.getPreviousLocalValue();
- if (previousLocalValue != null) {
- previousLocalValue.removeDebugUser(current);
- }
listIterator.remove();
current = null;
}
@@ -350,7 +346,7 @@
assert invoke.inValues().size() == arguments.size();
for (int i = 0; i < invoke.inValues().size(); i++) {
// TODO(zerny): Support inlining in --debug mode.
- assert arguments.get(i).getDebugInfo() == null;
+ assert arguments.get(i).getLocalInfo() == null;
if ((i == 0) && (downcast != null)) {
Value invokeValue = invoke.inValues().get(0);
Value receiverValue = arguments.get(0);
diff --git a/src/main/java/com/android/tools/r8/ir/code/Cmp.java b/src/main/java/com/android/tools/r8/ir/code/Cmp.java
index 9b54353..aeb0a51 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Cmp.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Cmp.java
@@ -180,7 +180,7 @@
}
}
assert result == -1 || result == 0 || result == 1;
- Value value = code.createValue(MoveType.SINGLE, getDebugInfo());
+ Value value = code.createValue(MoveType.SINGLE, getLocalInfo());
return new ConstNumber(ConstType.INT, value, result);
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java b/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
index 1880668..9f8dc4e 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
@@ -33,10 +33,7 @@
public static ConstNumber copyOf(IRCode code, ConstNumber original) {
Value newValue =
- new Value(
- code.valueNumberGenerator.next(),
- original.outType(),
- original.getDebugInfo());
+ new Value(code.valueNumberGenerator.next(), original.outType(), original.getLocalInfo());
return new ConstNumber(original.type, newValue, original.getRawValue());
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/IRCode.java b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
index 824d75c..21ed16e 100644
--- a/src/main/java/com/android/tools/r8/ir/code/IRCode.java
+++ b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.code;
+import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
@@ -155,14 +156,11 @@
values.add(phi);
for (Value value : phi.getOperands()) {
values.add(value);
- if (value.isPhi()) {
- Phi phiOperand = value.asPhi();
- assert phiOperand.getBlock().getPhis().contains(phiOperand);
- assert phiOperand.uniquePhiUsers().contains(phi);
- } else {
- Instruction definition = value.definition;
- assert definition.outValue() == value;
- }
+ assert value.uniquePhiUsers().contains(phi);
+ }
+ for (Value value : phi.getDebugValues()) {
+ values.add(value);
+ value.debugPhiUsers().contains(phi);
}
}
for (Instruction instruction : block.getInstructions()) {
@@ -171,33 +169,41 @@
if (outValue != null) {
values.add(outValue);
assert outValue.definition == instruction;
- Value previousLocalValue = outValue.getPreviousLocalValue();
- if (previousLocalValue != null) {
- values.add(previousLocalValue);
- assert previousLocalValue.debugUsers().contains(instruction);
- }
}
for (Value value : instruction.inValues()) {
values.add(value);
assert value.uniqueUsers().contains(instruction);
- if (value.isPhi()) {
- Phi phi = value.asPhi();
- assert phi.getBlock().getPhis().contains(phi);
- } else {
- Instruction definition = value.definition;
- assert definition.outValue() == value;
- }
+ }
+ for (Value value : instruction.getDebugValues()) {
+ values.add(value);
+ assert value.debugUsers().contains(instruction);
}
}
}
for (Value value : values) {
+ assert verifyValue(value);
assert consistentValueUses(value);
}
return true;
}
+ private boolean verifyValue(Value value) {
+ assert value.isPhi() ? verifyPhi(value.asPhi()) : verifyDefinition(value);
+ return true;
+ }
+
+ private boolean verifyPhi(Phi phi) {
+ assert phi.getBlock().getPhis().contains(phi);
+ return true;
+ }
+
+ private boolean verifyDefinition(Value value) {
+ assert value.definition.outValue() == value;
+ return true;
+ }
+
private boolean consistentValueUses(Value value) {
for (Instruction user : value.uniqueUsers()) {
assert user.inValues().contains(value);
@@ -206,10 +212,13 @@
assert phiUser.getOperands().contains(value);
assert phiUser.getBlock().getPhis().contains(phiUser);
}
- if (value.debugUsers() != null) {
+ if (value.getLocalInfo() != null) {
for (Instruction debugUser : value.debugUsers()) {
- assert debugUser.getPreviousLocalValue() == value
- || debugUser.getDebugValues().contains(value);
+ assert debugUser.getDebugValues().contains(value);
+ }
+ for (Phi phiUser : value.debugPhiUsers()) {
+ assert verifyPhi(phiUser);
+ assert phiUser.getDebugValues().contains(value);
}
}
return true;
@@ -367,8 +376,8 @@
return arguments;
}
- public Value createValue(MoveType moveType, Value.DebugInfo debugInfo) {
- return new Value(valueNumberGenerator.next(), moveType, debugInfo);
+ public Value createValue(MoveType moveType, DebugLocalInfo local) {
+ return new Value(valueNumberGenerator.next(), moveType, local);
}
public Value createValue(MoveType moveType) {
diff --git a/src/main/java/com/android/tools/r8/ir/code/Instruction.java b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
index e33c796..13325d8 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
@@ -7,7 +7,6 @@
import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.code.Value.DebugInfo;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
import com.android.tools.r8.ir.regalloc.RegisterAllocator;
@@ -65,10 +64,6 @@
outValue = value;
if (outValue != null) {
outValue.definition = this;
- Value previousLocalValue = getPreviousLocalValue();
- if (previousLocalValue != null) {
- previousLocalValue.addDebugUser(this);
- }
}
}
@@ -107,27 +102,29 @@
}
}
- public void replaceDebugPhi(Phi phi, Value value) {
- if (debugValues != null) {
- for (int i = 0; i < debugValues.size(); i++) {
- if (phi == debugValues.get(i)) {
- if (value.getLocalInfo() == null) {
- debugValues.remove(i);
- } else {
- debugValues.set(i, value);
- value.addDebugUser(this);
- }
+ // Similar to Phi::replaceTrivialPhi, removal can cause a concurrent modification error.
+ // TODO(ager): Consider unifying with other replace methods and avoid the C.M.E.
+ public boolean replaceDebugValue(Value oldValue, Value newValue) {
+ if (debugValues == null) {
+ return false;
+ }
+ int found = -1;
+ for (int i = 0; i < debugValues.size(); i++) {
+ if (oldValue == debugValues.get(i)) {
+ assert found == -1;
+ found = i;
+ if (newValue.getLocalInfo() != null) {
+ // TODO(zerny): Insert a write if replacing a phi with different debug-local info.
+ debugValues.set(i, newValue);
+ newValue.addDebugUser(this);
}
}
}
- if (phi == getPreviousLocalValue()) {
- if (value.getDebugInfo() == null) {
- replacePreviousLocalValue(null);
- } else {
- replacePreviousLocalValue(value);
- value.addDebugUser(this);
- }
+ if (found >= 0 && newValue.getLocalInfo() == null) {
+ // TODO(zerny): Insert a write if replacing a phi with associated debug-local info.
+ debugValues.remove(found);
}
+ return found >= 0;
}
/**
@@ -323,26 +320,14 @@
public abstract int maxOutValueRegister();
- public DebugInfo getDebugInfo() {
- return outValue == null ? null : outValue.getDebugInfo();
- }
-
public DebugLocalInfo getLocalInfo() {
return outValue == null ? null : outValue.getLocalInfo();
}
- public Value getPreviousLocalValue() {
- return outValue == null ? null : outValue.getPreviousLocalValue();
- }
-
public List<Value> getDebugValues() {
return debugValues != null ? debugValues : ImmutableList.of();
}
- public void replacePreviousLocalValue(Value value) {
- outValue.replacePreviousLocalValue(value);
- }
-
public boolean isArrayGet() {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java b/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java
index 52a0f55..770278a 100644
--- a/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java
@@ -37,7 +37,7 @@
int left = leftValue().getConstInstruction().asConstNumber().getIntValue();
int right = rightValue().getConstInstruction().asConstNumber().getIntValue();
int result = foldIntegers(left, right);
- Value value = code.createValue(MoveType.SINGLE, getDebugInfo());
+ Value value = code.createValue(MoveType.SINGLE, getLocalInfo());
return new ConstNumber(ConstType.INT, value, result);
} else {
assert type == NumericType.LONG;
@@ -50,7 +50,7 @@
right = rightValue().getConstInstruction().asConstNumber().getLongValue();
}
long result = foldLongs(left, right);
- Value value = code.createValue(MoveType.WIDE, getDebugInfo());
+ Value value = code.createValue(MoveType.WIDE, getLocalInfo());
return new ConstNumber(ConstType.LONG, value, result);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Neg.java b/src/main/java/com/android/tools/r8/ir/code/Neg.java
index 59022de..f858d70 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Neg.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Neg.java
@@ -31,20 +31,20 @@
assert canBeFolded();
if (type == NumericType.INT) {
int result = -source().getConstInstruction().asConstNumber().getIntValue();
- Value value = code.createValue(MoveType.SINGLE, getDebugInfo());
+ Value value = code.createValue(MoveType.SINGLE, getLocalInfo());
return new ConstNumber(ConstType.INT, value, result);
} else if (type == NumericType.LONG) {
long result = -source().getConstInstruction().asConstNumber().getLongValue();
- Value value = code.createValue(MoveType.WIDE, getDebugInfo());
+ Value value = code.createValue(MoveType.WIDE, getLocalInfo());
return new ConstNumber(ConstType.LONG, value, result);
} else if (type == NumericType.FLOAT) {
float result = -source().getConstInstruction().asConstNumber().getFloatValue();
- Value value = code.createValue(MoveType.SINGLE, getDebugInfo());
+ Value value = code.createValue(MoveType.SINGLE, getLocalInfo());
return new ConstNumber(ConstType.FLOAT, value, Float.floatToIntBits(result));
} else {
assert type == NumericType.DOUBLE;
double result = -source().getConstInstruction().asConstNumber().getDoubleValue();
- Value value = code.createValue(MoveType.WIDE, getDebugInfo());
+ Value value = code.createValue(MoveType.WIDE, getLocalInfo());
return new ConstNumber(ConstType.DOUBLE, value, Double.doubleToLongBits(result));
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Not.java b/src/main/java/com/android/tools/r8/ir/code/Not.java
index cae6118..4c42b80 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Not.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Not.java
@@ -27,12 +27,12 @@
assert canBeFolded();
if (type == NumericType.INT) {
int result = ~(source().getConstInstruction().asConstNumber().getIntValue());
- Value value = code.createValue(MoveType.SINGLE, getDebugInfo());
+ Value value = code.createValue(MoveType.SINGLE, getLocalInfo());
return new ConstNumber(ConstType.INT, value, result);
} else {
assert type == NumericType.LONG;
long result = ~source().getConstInstruction().asConstNumber().getLongValue();
- Value value = code.createValue(MoveType.WIDE, getDebugInfo());
+ Value value = code.createValue(MoveType.WIDE, getLocalInfo());
return new ConstNumber(ConstType.LONG, value, result);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Phi.java b/src/main/java/com/android/tools/r8/ir/code/Phi.java
index 7e05dc9..185d2fd 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Phi.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Phi.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.utils.CfgPrinter;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -20,6 +21,7 @@
private final BasicBlock block;
private final List<Value> operands = new ArrayList<>();
+ private List<Value> debugValues = null;
// Trivial phis are eliminated during IR construction. When a trivial phi is eliminated
// we need to update all references to it. A phi can be referenced from phis, instructions
@@ -36,7 +38,7 @@
private MoveType outType = null;
public Phi(int number, BasicBlock block, MoveType type, DebugLocalInfo local) {
- super(number, type, local == null ? null : new DebugInfo(local, null));
+ super(number, type, local);
this.block = block;
block.addPhi(this);
}
@@ -96,6 +98,15 @@
removeTrivialPhi();
}
+ public void addDebugValue(Value value) {
+ assert value.getLocalInfo() != null;
+ if (debugValues == null) {
+ debugValues = new ArrayList<>();
+ }
+ debugValues.add(value);
+ value.addDebugPhiUser(this);
+ }
+
private void throwUndefinedValueError() {
throw new CompilationError(
"Undefined value encountered during compilation. "
@@ -157,6 +168,20 @@
}
}
+ private void replaceTrivialDebugPhi(Value current, Value newValue) {
+ if (debugValues == null) {
+ return;
+ }
+ assert current.getLocalInfo() != null;
+ assert current.getLocalInfo() == newValue.getLocalInfo();
+ for (int i = 0; i < debugValues.size(); i++) {
+ if (debugValues.get(i) == current) {
+ debugValues.set(i, newValue);
+ newValue.addDebugPhiUser(this);
+ }
+ }
+ }
+
public boolean isTrivialPhi() {
Value same = null;
for (Value op : operands) {
@@ -202,8 +227,15 @@
user.replaceTrivialPhi(this, same);
}
if (debugUsers() != null) {
+ List<Instruction> removed = new ArrayList<>();
for (Instruction user : debugUsers()) {
- user.replaceDebugPhi(this, same);
+ if (user.replaceDebugValue(this, same)) {
+ removed.add(user);
+ }
+ }
+ removed.forEach(this::removeDebugUser);
+ for (Phi user : debugPhiUsers()) {
+ user.replaceTrivialDebugPhi(this, same);
}
}
// If IR construction is taking place, update the definition users.
@@ -316,4 +348,8 @@
public boolean needsRegister() {
return true;
}
+
+ public List<Value> getDebugValues() {
+ return debugValues != null ? debugValues : ImmutableList.of();
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Value.java b/src/main/java/com/android/tools/r8/ir/code/Value.java
index 44bd9d4..78cb4a5 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Value.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Value.java
@@ -18,39 +18,17 @@
public class Value {
- /**
- * Immutable view of the debug info associated with an SSA value.
- *
- * Used during IR building and to construct replacement values.
- */
- public static class DebugInfo {
- private final DebugLocalInfo local;
- private final Value previousLocalValue;
-
- public DebugInfo(DebugLocalInfo local, Value previousLocalValue) {
- assert local != null;
- this.local = local;
- this.previousLocalValue = previousLocalValue;
- }
- }
-
- // Actual internal data for the debug information of locals.
+ // Lazily allocated internal data for the debug information of locals.
// This is wrapped in a class to avoid multiple pointers in the value structure.
private static class DebugData {
final DebugLocalInfo local;
- Value previousLocalValue;
- Set<Instruction> debugUsers = new HashSet<>();
+ Set<Instruction> users = new HashSet<>();
+ Set<Phi> phiUsers = new HashSet<>();
List<Instruction> localStarts = new ArrayList<>();
List<Instruction> localEnds = new ArrayList<>();
- DebugData(DebugInfo info) {
- this(info.local, info.previousLocalValue);
- }
-
- DebugData(DebugLocalInfo local, Value previousLocalValue) {
- assert previousLocalValue == null || !previousLocalValue.isUninitializedLocal();
+ DebugData(DebugLocalInfo local) {
this.local = local;
- this.previousLocalValue = previousLocalValue;
}
}
@@ -73,10 +51,10 @@
private LongInterval valueRange;
private final DebugData debugData;
- public Value(int number, MoveType type, DebugInfo debugInfo) {
+ public Value(int number, MoveType type, DebugLocalInfo local) {
this.number = number;
this.type = type;
- this.debugData = debugInfo == null ? null : new DebugData(debugInfo);
+ this.debugData = local == null ? null : new DebugData(local);
}
public boolean isFixedRegisterValue() {
@@ -95,26 +73,10 @@
return type.requiredRegisters();
}
- public DebugInfo getDebugInfo() {
- return debugData == null ? null : new DebugInfo(debugData.local, debugData.previousLocalValue);
- }
-
public DebugLocalInfo getLocalInfo() {
return debugData == null ? null : debugData.local;
}
- public Value getPreviousLocalValue() {
- return debugData == null ? null : debugData.previousLocalValue;
- }
-
- public void replacePreviousLocalValue(Value value) {
- if (value == null || value.isUninitializedLocal()) {
- debugData.previousLocalValue = null;
- } else {
- debugData.previousLocalValue = value;
- }
- }
-
public List<Instruction> getDebugLocalStarts() {
return debugData.localStarts;
}
@@ -189,10 +151,11 @@
}
public Set<Instruction> debugUsers() {
- if (debugData == null) {
- return null;
- }
- return Collections.unmodifiableSet(debugData.debugUsers);
+ return debugData == null ? null : Collections.unmodifiableSet(debugData.users);
+ }
+
+ public Set<Phi> debugPhiUsers() {
+ return debugData == null ? null : Collections.unmodifiableSet(debugData.phiUsers);
}
public int numberOfUsers() {
@@ -211,18 +174,30 @@
return uniquePhiUsers().size();
}
+ public int numberOfAllNonDebugUsers() {
+ return numberOfUsers() + numberOfPhiUsers();
+ }
+
public int numberOfDebugUsers() {
- return debugData == null ? 0 : debugData.debugUsers.size();
+ return debugData == null ? 0 : debugData.users.size();
+ }
+
+ public int numberOfDebugPhiUsers() {
+ return debugData == null ? 0 : debugData.phiUsers.size();
+ }
+
+ public int numberOfAllDebugUsers() {
+ return numberOfDebugUsers() + numberOfDebugPhiUsers();
}
public int numberOfAllUsers() {
- return numberOfUsers() + numberOfPhiUsers() + numberOfDebugUsers();
+ return numberOfAllNonDebugUsers() + numberOfAllDebugUsers();
}
public boolean isUsed() {
return !users.isEmpty()
|| !phiUsers.isEmpty()
- || ((debugData != null) && !debugData.debugUsers.isEmpty());
+ || ((debugData != null) && !debugData.users.isEmpty());
}
public boolean usedInMonitorOperation() {
@@ -250,7 +225,7 @@
phiUsers.clear();
uniquePhiUsers = null;
if (debugData != null) {
- debugData.debugUsers.clear();
+ debugData.users.clear();
}
}
@@ -268,7 +243,14 @@
if (isUninitializedLocal()) {
return;
}
- debugData.debugUsers.add(user);
+ debugData.users.add(user);
+ }
+
+ public void addDebugPhiUser(Phi user) {
+ if (isUninitializedLocal()) {
+ return;
+ }
+ debugData.phiUsers.add(user);
}
public boolean isUninitializedLocal() {
@@ -280,7 +262,11 @@
}
public void removeDebugUser(Instruction user) {
- debugData.debugUsers.remove(user);
+ debugData.users.remove(user);
+ }
+
+ public void removeDebugPhiUser(Phi user) {
+ debugData.phiUsers.remove(user);
}
public boolean hasUsersInfo() {
@@ -293,7 +279,8 @@
phiUsers = null;
uniquePhiUsers = null;
if (debugData != null) {
- debugData.debugUsers = null;
+ debugData.users = null;
+ debugData.phiUsers = null;
}
}
@@ -328,10 +315,15 @@
}
return v;
});
- if (user.getPreviousLocalValue() == this) {
- newValue.addDebugUser(user);
- user.replacePreviousLocalValue(newValue);
- }
+ }
+ for (Phi user : debugPhiUsers()) {
+ user.getDebugValues().replaceAll(v -> {
+ if (v == this) {
+ newValue.addDebugPhiUser(user);
+ return newValue;
+ }
+ return v;
+ });
}
}
clearUsers();
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index 976020c2..1f29d26 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -75,7 +75,6 @@
import com.android.tools.r8.ir.code.Throw;
import com.android.tools.r8.ir.code.Ushr;
import com.android.tools.r8.ir.code.Value;
-import com.android.tools.r8.ir.code.Value.DebugInfo;
import com.android.tools.r8.ir.code.ValueNumberGenerator;
import com.android.tools.r8.ir.code.Xor;
import com.android.tools.r8.utils.InternalOptions;
@@ -269,6 +268,7 @@
private final InternalOptions options;
// Pending local changes.
+ private Value previousLocalValue = null;
private List<Value> debugLocalStarts = new ArrayList<>();
private List<Value> debugLocalReads = new ArrayList<>();
private List<Value> debugLocalEnds = new ArrayList<>();
@@ -489,16 +489,14 @@
public void addThisArgument(int register) {
DebugLocalInfo local = getCurrentLocal(register);
- DebugInfo info = local == null ? null : new DebugInfo(local, null);
- Value value = writeRegister(register, MoveType.OBJECT, ThrowingInfo.NO_THROW, info);
+ Value value = writeRegister(register, MoveType.OBJECT, ThrowingInfo.NO_THROW, local);
addInstruction(new Argument(value));
value.markAsThis();
}
public void addNonThisArgument(int register, MoveType moveType) {
DebugLocalInfo local = getCurrentLocal(register);
- DebugInfo info = local == null ? null : new DebugInfo(local, null);
- Value value = writeRegister(register, moveType, ThrowingInfo.NO_THROW, info);
+ Value value = writeRegister(register, moveType, ThrowingInfo.NO_THROW, local);
addInstruction(new Argument(value));
}
@@ -1096,7 +1094,7 @@
public void addMoveException(int dest) {
Value out = writeRegister(dest, MoveType.OBJECT, ThrowingInfo.NO_THROW);
- assert out.getDebugInfo() == null;
+ assert out.getLocalInfo() == null;
MoveException instruction = new MoveException(out);
assert !instruction.instructionTypeCanThrow();
if (!currentBlock.getInstructions().isEmpty()) {
@@ -1501,21 +1499,18 @@
// This special write register is needed when changing the scoping of a local variable.
// See addDebugLocalStart and addDebugLocalEnd.
- private Value writeRegister(int register, MoveType type, ThrowingInfo throwing, DebugInfo info) {
+ private Value writeRegister(
+ int register, MoveType type, ThrowingInfo throwing, DebugLocalInfo local) {
checkRegister(register);
- Value value = new Value(valueNumberGenerator.next(), type, info);
+ Value value = new Value(valueNumberGenerator.next(), type, local);
currentBlock.writeCurrentDefinition(register, value, throwing);
return value;
}
public Value writeRegister(int register, MoveType type, ThrowingInfo throwing) {
DebugLocalInfo local = getCurrentLocal(register);
- DebugInfo info = null;
- if (local != null) {
- Value previousLocal = readRegisterIgnoreLocal(register, type);
- info = new DebugInfo(local, previousLocal.getLocalInfo() != local ? null : previousLocal);
- }
- return writeRegister(register, type, throwing, info);
+ previousLocalValue = local == null ? null : readRegisterIgnoreLocal(register, type);
+ return writeRegister(register, type, throwing, local);
}
public Value writeNumericRegister(int register, NumericType type, ThrowingInfo throwing) {
@@ -1596,6 +1591,12 @@
if (!options.debug) {
return;
}
+ // Add a use if this instruction is overwriting a previous value of the same local.
+ if (previousLocalValue != null && previousLocalValue.getLocalInfo() == ir.getLocalInfo()) {
+ assert ir.outValue() != null;
+ ir.addDebugValue(previousLocalValue);
+ }
+ previousLocalValue = null;
if (debugLocalStarts.isEmpty() && debugLocalReads.isEmpty() && debugLocalEnds.isEmpty()) {
return;
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
index ca1d53c..c21c090 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
@@ -260,7 +260,8 @@
@Override
public void buildPrelude(IRBuilder builder) {
// Record types for arguments.
- Map<Integer, MoveType> initializedLocals = recordArgumentTypes();
+ Int2ReferenceMap<MoveType> argumentLocals = recordArgumentTypes();
+ Int2ReferenceMap<MoveType> initializedLocals = new Int2ReferenceOpenHashMap<>(argumentLocals);
// Initialize all non-argument locals to ensure safe insertion of debug-local instructions.
for (Object o : node.localVariables) {
LocalVariableNode local = (LocalVariableNode) o;
@@ -294,7 +295,11 @@
}
// Add debug information for all locals at the initial label.
if (initialLabel != null) {
- state.openLocals(initialLabel);
+ for (Local local : state.openLocals(initialLabel)) {
+ if (!argumentLocals.containsKey(local.slot.register)) {
+ builder.addDebugLocalStart(local.slot.register, local.info);
+ }
+ }
}
// Build the actual argument instructions now that type and debug information is known
// for arguments.
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
index a7c40d1..71de2b6 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
@@ -51,7 +51,7 @@
if (insn.outValue() == null) {
return null;
} else {
- return code.createValue(insn.outType(), insn.getDebugInfo());
+ return code.createValue(insn.outType(), insn.getLocalInfo());
}
}
@@ -105,7 +105,7 @@
// Fix up the return type if needed.
if (actualTarget.proto.returnType != invokedMethod.proto.returnType
&& newInvoke.outValue() != null) {
- Value newValue = code.createValue(newInvoke.outType(), invoke.getDebugInfo());
+ Value newValue = code.createValue(newInvoke.outType(), invoke.getLocalInfo());
newInvoke.outValue().replaceUsers(newValue);
CheckCast cast = new CheckCast(
newValue,
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
index 3a1902e..50f224c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
@@ -61,10 +61,6 @@
for (Value debugValue : instruction.getDebugValues()) {
updateWorklist(worklist, debugValue);
}
- Value previousLocalValue = instruction.getPreviousLocalValue();
- if (previousLocalValue != null) {
- updateWorklist(worklist, previousLocalValue);
- }
}
private static void removeDeadPhis(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java b/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
index a34c8cb..241106c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
@@ -75,7 +75,7 @@
MoveType moveType = instruction.outValue().outType();
if (rule != null && rule.hasReturnValue() && rule.getReturnValue().isSingleValue()) {
assert moveType != MoveType.OBJECT;
- Value value = code.createValue(moveType, instruction.getDebugInfo());
+ Value value = code.createValue(moveType, instruction.getLocalInfo());
replacement = new ConstNumber(
ConstType.fromMoveType(moveType), value, rule.getReturnValue().getSingleValue());
}
@@ -84,7 +84,7 @@
DexField field = rule.getReturnValue().getField();
DexEncodedField staticField = appInfo.lookupStaticTarget(field.clazz, field);
if (staticField != null) {
- Value value = code.createValue(moveType, instruction.getDebugInfo());
+ Value value = code.createValue(moveType, instruction.getLocalInfo());
replacement = staticField.staticValue.asConstInstruction(false, value);
} else {
throw new CompilationError(field.clazz.toSourceString() + "." + field.name.toString() +
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 460fe92..6cd453b 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
@@ -1841,6 +1841,8 @@
int predIndex = succ.getPredecessors().indexOf(block);
for (Phi phi : succ.getPhis()) {
live.add(phi.getOperand(predIndex));
+ assert phi.getDebugValues().stream().allMatch(Value::needsRegister);
+ live.addAll(phi.getDebugValues());
}
}
ListIterator<Instruction> iterator =
@@ -1855,17 +1857,8 @@
live.add(use);
}
}
- if (options.debug) {
- for (Value use : instruction.getDebugValues()) {
- assert use.needsRegister();
- live.add(use);
- }
- Value use = instruction.getPreviousLocalValue();
- if (use != null) {
- assert use.needsRegister();
- live.add(use);
- }
- }
+ assert instruction.getDebugValues().stream().allMatch(Value::needsRegister);
+ live.addAll(instruction.getDebugValues());
}
for (Phi phi : block.getPhis()) {
live.remove(phi);
@@ -1942,6 +1935,8 @@
for (Phi phi : successor.getPhis()) {
live.remove(phi);
phiOperands.add(phi.getOperand(successor.getPredecessors().indexOf(block)));
+ assert phi.getDebugValues().stream().allMatch(Value::needsRegister);
+ phiOperands.addAll(phi.getDebugValues());
}
}
live.addAll(phiOperands);
@@ -1990,14 +1985,6 @@
addLiveRange(use, block, number);
}
}
- Value use = instruction.getPreviousLocalValue();
- if (use != null) {
- assert use.needsRegister();
- if (!live.contains(use)) {
- live.add(use);
- addLiveRange(use, block, number);
- }
- }
}
}
}