Merge "Do not replace assumevalue target twice."
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfo.java b/src/main/java/com/android/tools/r8/graph/AppInfo.java
index 3601ee9..afd923c 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfo.java
@@ -331,6 +331,10 @@
return null;
}
+ public void registerNewType(DexType newType, DexType superType) {
+ // We do not track subtyping relationships in the basic AppInfo. So do nothing.
+ }
+
public List<DexClass> getSuperTypeClasses(DexType type) {
List<DexClass> result = new ArrayList<>();
do {
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java b/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
index 503bc89..9c87b61 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
@@ -227,6 +227,12 @@
}
@Override
+ public void registerNewType(DexType newType, DexType superType) {
+ // Register the relationship between this type and its superType.
+ superType.addDirectSubtype(newType);
+ }
+
+ @Override
public boolean hasSubtyping() {
return true;
}
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 b2041d3..968e560 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
@@ -106,7 +106,7 @@
if (current == null) {
throw new IllegalStateException();
}
- assert current.outValue() == null || current.outValue().numberOfAllUsers() == 0;
+ assert current.outValue() == null || !current.outValue().isUsed();
for (int i = 0; i < current.inValues().size(); i++) {
Value value = current.inValues().get(i);
value.removeUser(current);
@@ -323,7 +323,7 @@
while (inlineeIterator.hasNext()) {
Instruction instruction = inlineeIterator.next();
if (instruction.isArgument()) {
- assert instruction.outValue().numberOfAllUsers() == 0;
+ assert !instruction.outValue().isUsed();
assert instruction.outValue() == arguments.get(index++);
inlineeIterator.remove();
}
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 e6ba6c0..b7a18f0 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
@@ -61,7 +61,7 @@
}
public void setOutValue(Value value) {
- assert outValue == null || !outValue.hasUsersInfo() || outValue.numberOfAllUsers() == 0;
+ assert outValue == null || !outValue.hasUsersInfo() || !outValue.isUsed();
outValue = value;
if (outValue != null) {
outValue.definition = this;
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 e0bfdd0..035bf95 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
@@ -219,6 +219,12 @@
return numberOfUsers() + numberOfPhiUsers() + numberOfDebugUsers();
}
+ public boolean isUsed() {
+ return !users.isEmpty()
+ || !phiUsers.isEmpty()
+ || ((debugData != null) && !debugData.debugUsers.isEmpty());
+ }
+
public void addUser(Instruction user) {
users.add(user);
uniqueUsers = null;
@@ -503,7 +509,7 @@
public boolean isDead(InternalOptions options) {
// Totally unused values are trivially dead.
- return numberOfAllUsers() == 0 || isDead(new HashSet<>(), options);
+ return !isUsed() || isDead(new HashSet<>(), options);
}
protected boolean isDead(Set<Value> active, InternalOptions options) {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index a4bb015..659a503 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -369,6 +369,8 @@
count++;
result = application.dexItemFactory.createType(DescriptorUtils.javaTypeToDescriptor(name));
} while (application.definitionFor(result) != null);
+ // Register the newly generated type in the subtyping hierarchy, if we have one.
+ appInfo.registerNewType(result, appInfo.dexItemFactory.objectType);
return result;
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
index 7954ae4..0a6ea7e 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
@@ -83,9 +83,7 @@
: factory.createField(lambdaClassType, lambdaClassType, rewriter.instanceFieldName);
// We have to register this new class as a subtype of object.
- if (rewriter.appInfo.hasSubtyping()) {
- factory.objectType.addDirectSubtype(type);
- }
+ rewriter.appInfo.registerNewType(type, factory.objectType);
}
// Generate unique lambda class type for lambda descriptor and instantiation point context.
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 b683f3a..3a1902e 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
@@ -105,7 +105,7 @@
// Remove unused invoke results.
if (current.isInvoke()
&& current.outValue() != null
- && current.outValue().numberOfAllUsers() == 0) {
+ && !current.outValue().isUsed()) {
current.setOutValue(null);
}
// Never remove instructions that can have side effects, except for const-class.
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 8a02435..a34c8cb 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
@@ -137,10 +137,10 @@
ProguardMemberRuleLookup lookup = lookupMemberRule(definition);
if (lookup != null) {
if (lookup.type == RuleType.ASSUME_NO_SIDE_EFFECTS
- && (invoke.outValue() == null || invoke.outValue().numberOfAllUsers() == 0)) {
+ && (invoke.outValue() == null || !invoke.outValue().isUsed())) {
iterator.remove();
invokeReplaced = true;
- } else {
+ } else if (invoke.outValue() != null && invoke.outValue().isUsed()) {
// Check to see if a constant value can be assumed.
Instruction replacement =
constantReplacementFromProguardRule(lookup.rule, code, invoke);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
index 8cc8ec4..3857c1f 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
@@ -400,7 +400,7 @@
// Allow all new-instance instructions in a outline.
if (instruction.isNewInstance()) {
- if (instruction.outValue().numberOfAllUsers() > 0) {
+ if (instruction.outValue().isUsed()) {
// Track the new-instance value to make sure the <init> call is part of the outline.
pendingNewInstanceIndex = index;
}
@@ -711,7 +711,7 @@
}
}
assert m.proto.shorty.toString().length() - 1 == in.size();
- if (returnValue != null && returnValue.numberOfAllUsers() == 0) {
+ if (returnValue != null && !returnValue.isUsed()) {
returnValue = null;
}
Invoke outlineInvoke = new InvokeStatic(m, returnValue, in);
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 fae2e54..38cdb29 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
@@ -1955,7 +1955,7 @@
// For instructions that define values which have no use create a live range covering
// the instruction. This will typically be instructions that can have side effects even
// if their output is not used.
- if (definition.numberOfAllUsers() == 0) {
+ if (!definition.isUsed()) {
addLiveRange(definition, block, instruction.getNumber() + INSTRUCTION_NUMBER_DELTA);
}
live.remove(definition);
diff --git a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java b/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java
index 8b0ac9e..4610f41 100644
--- a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java
+++ b/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java
@@ -196,7 +196,7 @@
// Remove now unneeded constructor calls.
InvokeStatic invokeStatic = insn.asInvokeStatic();
DexMethod invokedMethod = invokeStatic.getInvokedMethod();
- if ((invokeStatic.outValue().numberOfAllUsers() == 0)
+ if ((!invokeStatic.outValue().isUsed())
&& invokedMethod.proto.returnType.isSubtypeOf(protobufListType, appInfo)) {
it.remove();
}