Generalize graph lens to support non-null constant parameter replacement
Change-Id: Ibc55d32dd3f6fe47f0d6f7b1532ebef947dd2508
diff --git a/src/main/java/com/android/tools/r8/graph/RewrittenPrototypeDescription.java b/src/main/java/com/android/tools/r8/graph/RewrittenPrototypeDescription.java
index c016016..90c504e 100644
--- a/src/main/java/com/android/tools/r8/graph/RewrittenPrototypeDescription.java
+++ b/src/main/java/com/android/tools/r8/graph/RewrittenPrototypeDescription.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.graph;
+import com.android.tools.r8.ir.analysis.value.SingleValue;
import com.android.tools.r8.ir.code.ConstInstruction;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Position;
@@ -68,11 +69,11 @@
public static class Builder {
- private boolean isAlwaysNull = false;
- private DexType type = null;
+ private SingleValue singleValue;
+ private DexType type;
- public Builder setIsAlwaysNull() {
- this.isAlwaysNull = true;
+ public Builder setSingleValue(SingleValue singleValue) {
+ this.singleValue = singleValue;
return this;
}
@@ -83,15 +84,15 @@
public RemovedArgumentInfo build() {
assert type != null;
- return new RemovedArgumentInfo(isAlwaysNull, type);
+ return new RemovedArgumentInfo(singleValue, type);
}
}
- private final boolean isAlwaysNull;
+ private final SingleValue singleValue;
private final DexType type;
- private RemovedArgumentInfo(boolean isAlwaysNull, DexType type) {
- this.isAlwaysNull = isAlwaysNull;
+ private RemovedArgumentInfo(SingleValue singleValue, DexType type) {
+ this.singleValue = singleValue;
this.type = type;
}
@@ -99,16 +100,20 @@
return new Builder();
}
+ public boolean hasSingleValue() {
+ return singleValue != null;
+ }
+
+ public SingleValue getSingleValue() {
+ return singleValue;
+ }
+
public DexType getType() {
return type;
}
- public boolean isAlwaysNull() {
- return isAlwaysNull;
- }
-
public boolean isNeverUsed() {
- return !isAlwaysNull;
+ return !hasSingleValue();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleConstClassValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleConstClassValue.java
index 8f4baa6..c42a3bb 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleConstClassValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleConstClassValue.java
@@ -17,8 +17,8 @@
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.ConstClass;
-import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.NumberGenerator;
import com.android.tools.r8.ir.code.TypeAndLocalInfoSupplier;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
@@ -64,7 +64,8 @@
@Override
public Instruction createMaterializingInstruction(
AppView<? extends AppInfoWithClassHierarchy> appView,
- IRCode code,
+ ProgramMethod context,
+ NumberGenerator valueNumberGenerator,
TypeAndLocalInfoSupplier info) {
TypeElement typeLattice = info.getOutType();
DebugLocalInfo debugLocalInfo = info.getLocalInfo();
@@ -73,9 +74,12 @@
.isSubtype(appView.dexItemFactory().classType, typeLattice.asClassType().getClassType())
.isTrue();
Value returnedValue =
- code.createValue(classClassType(appView, definitelyNotNull()), debugLocalInfo);
+ new Value(
+ valueNumberGenerator.next(),
+ classClassType(appView, definitelyNotNull()),
+ debugLocalInfo);
ConstClass instruction = new ConstClass(returnedValue, type);
- assert !instruction.instructionMayHaveSideEffects(appView, code.context());
+ assert !instruction.instructionMayHaveSideEffects(appView, context);
return instruction;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleDexItemBasedStringValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleDexItemBasedStringValue.java
index 13df457..a537863 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleDexItemBasedStringValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleDexItemBasedStringValue.java
@@ -15,8 +15,8 @@
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.DexItemBasedConstString;
-import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.NumberGenerator;
import com.android.tools.r8.ir.code.TypeAndLocalInfoSupplier;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.naming.dexitembasedstring.NameComputationInfo;
@@ -74,7 +74,8 @@
@Override
public Instruction createMaterializingInstruction(
AppView<? extends AppInfoWithClassHierarchy> appView,
- IRCode code,
+ ProgramMethod context,
+ NumberGenerator valueNumberGenerator,
TypeAndLocalInfoSupplier info) {
TypeElement typeLattice = info.getOutType();
DebugLocalInfo debugLocalInfo = info.getLocalInfo();
@@ -83,7 +84,10 @@
.isSubtype(appView.dexItemFactory().stringType, typeLattice.asClassType().getClassType())
.isTrue();
Value returnedValue =
- code.createValue(stringClassType(appView, definitelyNotNull()), debugLocalInfo);
+ new Value(
+ valueNumberGenerator.next(),
+ stringClassType(appView, definitelyNotNull()),
+ debugLocalInfo);
DexItemBasedConstString instruction =
new DexItemBasedConstString(returnedValue, item, nameComputationInfo);
assert !instruction.instructionInstanceCanThrow();
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleFieldValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleFieldValue.java
index 911174b..8769ab2 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleFieldValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleFieldValue.java
@@ -17,8 +17,8 @@
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.TypeElement;
-import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.NumberGenerator;
import com.android.tools.r8.ir.code.StaticGet;
import com.android.tools.r8.ir.code.TypeAndLocalInfoSupplier;
import com.android.tools.r8.ir.code.Value;
@@ -69,11 +69,12 @@
@Override
public Instruction createMaterializingInstruction(
AppView<? extends AppInfoWithClassHierarchy> appView,
- IRCode code,
+ ProgramMethod context,
+ NumberGenerator valueNumberGenerator,
TypeAndLocalInfoSupplier info) {
TypeElement type = TypeElement.fromDexType(field.type, maybeNull(), appView);
assert type.lessThanOrEqual(info.getOutType(), appView);
- Value outValue = code.createValue(type, info.getLocalInfo());
+ Value outValue = new Value(valueNumberGenerator.next(), type, info.getLocalInfo());
return new StaticGet(outValue, field);
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleNumberValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleNumberValue.java
index d51b94a..c01133e 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleNumberValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleNumberValue.java
@@ -11,8 +11,8 @@
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.ConstNumber;
-import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.NumberGenerator;
import com.android.tools.r8.ir.code.TypeAndLocalInfoSupplier;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
@@ -126,14 +126,17 @@
@Override
public Instruction createMaterializingInstruction(
AppView<? extends AppInfoWithClassHierarchy> appView,
- IRCode code,
+ ProgramMethod context,
+ NumberGenerator valueNumberGenerator,
TypeAndLocalInfoSupplier info) {
TypeElement typeLattice = info.getOutType();
DebugLocalInfo debugLocalInfo = info.getLocalInfo();
assert !typeLattice.isReferenceType() || value == 0;
Value returnedValue =
- code.createValue(
- typeLattice.isReferenceType() ? TypeElement.getNull() : typeLattice, debugLocalInfo);
+ new Value(
+ valueNumberGenerator.next(),
+ typeLattice.isReferenceType() ? TypeElement.getNull() : typeLattice,
+ debugLocalInfo);
return new ConstNumber(returnedValue, value);
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStringValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStringValue.java
index cd0c9e9..35acae4 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStringValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStringValue.java
@@ -15,8 +15,8 @@
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.ConstString;
-import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.NumberGenerator;
import com.android.tools.r8.ir.code.TypeAndLocalInfoSupplier;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
@@ -62,7 +62,8 @@
@Override
public Instruction createMaterializingInstruction(
AppView<? extends AppInfoWithClassHierarchy> appView,
- IRCode code,
+ ProgramMethod context,
+ NumberGenerator valueNumberGenerator,
TypeAndLocalInfoSupplier info) {
TypeElement typeLattice = info.getOutType();
DebugLocalInfo debugLocalInfo = info.getLocalInfo();
@@ -71,7 +72,10 @@
.isSubtype(appView.dexItemFactory().stringType, typeLattice.asClassType().getClassType())
.isTrue();
Value returnedValue =
- code.createValue(stringClassType(appView, definitelyNotNull()), debugLocalInfo);
+ new Value(
+ valueNumberGenerator.next(),
+ stringClassType(appView, definitelyNotNull()),
+ debugLocalInfo);
ConstString instruction = new ConstString(returnedValue, string);
assert !instruction.instructionInstanceCanThrow();
return instruction;
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleValue.java
index 4a3a11c..94cd837 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleValue.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.NumberGenerator;
import com.android.tools.r8.ir.code.TypeAndLocalInfoSupplier;
import com.android.tools.r8.ir.optimize.info.field.InstanceFieldInitializationInfo;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
@@ -35,9 +36,17 @@
* Note that calls to this method should generally be guarded by {@link
* #isMaterializableInContext}.
*/
- public abstract Instruction createMaterializingInstruction(
+ public final Instruction createMaterializingInstruction(
AppView<? extends AppInfoWithClassHierarchy> appView,
IRCode code,
+ TypeAndLocalInfoSupplier info) {
+ return createMaterializingInstruction(appView, code.context(), code.valueNumberGenerator, info);
+ }
+
+ public abstract Instruction createMaterializingInstruction(
+ AppView<? extends AppInfoWithClassHierarchy> appView,
+ ProgramMethod context,
+ NumberGenerator valueNumberGenerator,
TypeAndLocalInfoSupplier info);
public abstract boolean isMaterializableInContext(
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 e06df9e..90ca265 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
@@ -123,6 +123,10 @@
public static ThrowingInfo defaultForConstString(InternalOptions options) {
return options.isGeneratingClassFiles() ? NO_THROW : CAN_THROW;
}
+
+ public static ThrowingInfo defaultForInstruction(Instruction instruction) {
+ return instruction.instructionTypeCanThrow() ? CAN_THROW : NO_THROW;
+ }
}
public enum EdgeType {
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 3911614..b35e2ca 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
@@ -43,6 +43,7 @@
import com.android.tools.r8.ir.analysis.type.PrimitiveTypeElement;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
import com.android.tools.r8.ir.analysis.type.TypeElement;
+import com.android.tools.r8.ir.analysis.value.SingleValue;
import com.android.tools.r8.ir.code.Add;
import com.android.tools.r8.ir.code.And;
import com.android.tools.r8.ir.code.Argument;
@@ -110,6 +111,7 @@
import com.android.tools.r8.ir.code.StaticPut;
import com.android.tools.r8.ir.code.Sub;
import com.android.tools.r8.ir.code.Throw;
+import com.android.tools.r8.ir.code.TypeAndLocalInfoSupplier;
import com.android.tools.r8.ir.code.Ushr;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.code.ValueType;
@@ -1037,13 +1039,27 @@
private void handleConstantOrUnusedArgument(
int register, RemovedArgumentInfo removedArgumentInfo) {
assert removedArgumentInfo != null;
- if (removedArgumentInfo.isAlwaysNull()) {
+ if (removedArgumentInfo.hasSingleValue()) {
if (pendingArgumentInstructions == null) {
pendingArgumentInstructions = new ArrayList<>();
}
DebugLocalInfo local = getOutgoingLocal(register);
- Value value = writeRegister(register, getNull(), ThrowingInfo.NO_THROW, local);
- pendingArgumentInstructions.add(new ConstNumber(value, 0));
+ SingleValue singleValue = removedArgumentInfo.getSingleValue();
+ TypeElement type =
+ removedArgumentInfo.getType().isReferenceType() && singleValue.isNull()
+ ? getNull()
+ : removedArgumentInfo.getType().toTypeElement(appView);
+ Instruction materializingInstruction =
+ singleValue.createMaterializingInstruction(
+ appView.withClassHierarchy(),
+ method,
+ valueNumberGenerator,
+ TypeAndLocalInfoSupplier.create(type, local));
+ writeRegister(
+ register,
+ materializingInstruction.outValue(),
+ ThrowingInfo.defaultForInstruction(materializingInstruction));
+ pendingArgumentInstructions.add(materializingInstruction);
} else {
assert removedArgumentInfo.isNeverUsed();
}
@@ -2339,8 +2355,12 @@
// See addDebugLocalStart and addDebugLocalEnd.
private Value writeRegister(
int register, TypeElement typeLattice, ThrowingInfo throwing, DebugLocalInfo local) {
+ return writeRegister(
+ register, new Value(valueNumberGenerator.next(), typeLattice, local), throwing);
+ }
+
+ private Value writeRegister(int register, Value value, ThrowingInfo throwing) {
checkRegister(register);
- Value value = new Value(valueNumberGenerator.next(), typeLattice, local);
currentBlock.writeCurrentDefinition(register, value, throwing);
return value;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
index df30aac..b2e8366 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
@@ -310,7 +310,10 @@
DexType type = proto.parameters.values[i];
if (type.isAlwaysNull(appView)) {
RemovedArgumentInfo removedArg =
- RemovedArgumentInfo.builder().setIsAlwaysNull().setType(type).build();
+ RemovedArgumentInfo.builder()
+ .setSingleValue(appView.abstractValueFactory().createNullValue())
+ .setType(type)
+ .build();
argInfosBuilder.addArgumentInfo(i + offset, removedArg);
}
}
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/ArgumentInfoCollectionTest.java b/src/test/java/com/android/tools/r8/enumunboxing/ArgumentInfoCollectionTest.java
index ddef0b4..b0be3f7 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/ArgumentInfoCollectionTest.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/ArgumentInfoCollectionTest.java
@@ -13,6 +13,7 @@
import com.android.tools.r8.graph.RewrittenPrototypeDescription.ArgumentInfoCollection;
import com.android.tools.r8.graph.RewrittenPrototypeDescription.RemovedArgumentInfo;
import com.android.tools.r8.graph.RewrittenPrototypeDescription.RewrittenTypeInfo;
+import com.android.tools.r8.ir.analysis.value.AbstractValueFactory;
import org.junit.Test;
public class ArgumentInfoCollectionTest extends TestBase {
@@ -49,13 +50,22 @@
@Test
public void testCombineRemoved() {
DexItemFactory factory = new DexItemFactory();
+ AbstractValueFactory abstractValueFactory = new AbstractValueFactory();
// Arguments removed: 0 1 2 3 4 -> 0 2 4.
ArgumentInfoCollection.Builder builder1 = ArgumentInfoCollection.builder();
builder1.addArgumentInfo(
- 1, RemovedArgumentInfo.builder().setType(factory.intType).setIsAlwaysNull().build());
+ 1,
+ RemovedArgumentInfo.builder()
+ .setType(factory.intType)
+ .setSingleValue(abstractValueFactory.createNullValue())
+ .build());
builder1.addArgumentInfo(
- 3, RemovedArgumentInfo.builder().setType(factory.intType).setIsAlwaysNull().build());
+ 3,
+ RemovedArgumentInfo.builder()
+ .setType(factory.intType)
+ .setSingleValue(abstractValueFactory.createNullValue())
+ .build());
ArgumentInfoCollection arguments1 = builder1.build();
// Arguments removed: 0 2 4 -> 0. Arguments 2 and 4 are at position 1 and 2 after first removal.
@@ -69,27 +79,36 @@
RemovedArgumentInfo arg1 = combine.getArgumentInfo(1).asRemovedArgumentInfo();
assertEquals(arg1.getType(), factory.intType);
- assertTrue(arg1.isAlwaysNull());
+ assertTrue(arg1.hasSingleValue());
RemovedArgumentInfo arg2 = combine.getArgumentInfo(2).asRemovedArgumentInfo();
assertEquals(arg2.getType(), factory.doubleType);
- assertFalse(arg2.isAlwaysNull());
+ assertFalse(arg2.hasSingleValue());
RemovedArgumentInfo arg3 = combine.getArgumentInfo(3).asRemovedArgumentInfo();
assertEquals(arg3.getType(), factory.intType);
- assertTrue(arg3.isAlwaysNull());
+ assertTrue(arg3.hasSingleValue());
RemovedArgumentInfo arg4 = combine.getArgumentInfo(4).asRemovedArgumentInfo();
assertEquals(arg4.getType(), factory.doubleType);
- assertFalse(arg4.isAlwaysNull());
+ assertFalse(arg4.hasSingleValue());
}
@Test
public void testCombineRemoveRewritten() {
DexItemFactory factory = new DexItemFactory();
+ AbstractValueFactory abstractValueFactory = new AbstractValueFactory();
ArgumentInfoCollection.Builder builder1 = ArgumentInfoCollection.builder();
builder1.addArgumentInfo(
- 1, RemovedArgumentInfo.builder().setType(factory.intType).setIsAlwaysNull().build());
+ 1,
+ RemovedArgumentInfo.builder()
+ .setType(factory.intType)
+ .setSingleValue(abstractValueFactory.createNullValue())
+ .build());
builder1.addArgumentInfo(
- 3, RemovedArgumentInfo.builder().setType(factory.intType).setIsAlwaysNull().build());
+ 3,
+ RemovedArgumentInfo.builder()
+ .setType(factory.intType)
+ .setSingleValue(abstractValueFactory.createNullValue())
+ .build());
ArgumentInfoCollection arguments1 = builder1.build();
ArgumentInfoCollection.Builder builder2 = ArgumentInfoCollection.builder();
@@ -101,13 +120,13 @@
RemovedArgumentInfo arg1 = combine.getArgumentInfo(1).asRemovedArgumentInfo();
assertEquals(arg1.getType(), factory.intType);
- assertTrue(arg1.isAlwaysNull());
+ assertTrue(arg1.hasSingleValue());
RewrittenTypeInfo arg2 = combine.getArgumentInfo(2).asRewrittenTypeInfo();
assertEquals(arg2.getOldType(), factory.floatType);
assertEquals(arg2.getNewType(), factory.doubleType);
RemovedArgumentInfo arg3 = combine.getArgumentInfo(3).asRemovedArgumentInfo();
assertEquals(arg3.getType(), factory.intType);
- assertTrue(arg3.isAlwaysNull());
+ assertTrue(arg3.hasSingleValue());
RewrittenTypeInfo arg4 = combine.getArgumentInfo(4).asRewrittenTypeInfo();
assertEquals(arg4.getOldType(), factory.floatType);
assertEquals(arg4.getNewType(), factory.doubleType);