Rewrite unused static-get instructions in dead code remover
Change-Id: Idd812693d188d7ee68d3d4e7d9473c51d61a2beb
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 1a401f7..b533145 100644
--- a/src/main/java/com/android/tools/r8/graph/RewrittenPrototypeDescription.java
+++ b/src/main/java/com/android/tools/r8/graph/RewrittenPrototypeDescription.java
@@ -790,18 +790,26 @@
public Instruction getConstantReturn(
AppView<AppInfoWithLiveness> appView,
IRCode code,
- ProgramMethod method,
Position position,
TypeAndLocalInfoSupplier info) {
assert rewrittenReturnInfo != null;
assert rewrittenReturnInfo.hasSingleValue();
- assert rewrittenReturnInfo.getSingleValue().isMaterializableInContext(appView, method);
Instruction instruction =
rewrittenReturnInfo.getSingleValue().createMaterializingInstruction(appView, code, info);
instruction.setPosition(position);
return instruction;
}
+ public boolean verifyConstantReturnAccessibleInContext(
+ AppView<AppInfoWithLiveness> appView, ProgramMethod method, GraphLens codeLens) {
+ SingleValue rewrittenSingleValue =
+ rewrittenReturnInfo
+ .getSingleValue()
+ .rewrittenWithLens(appView, appView.graphLens(), codeLens);
+ assert rewrittenSingleValue.isMaterializableInContext(appView, method);
+ return true;
+ }
+
public DexMethod rewriteMethod(ProgramMethod method, DexItemFactory dexItemFactory) {
if (isEmpty()) {
return method.getReference();
diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionListIterator.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionListIterator.java
index 2ad1f65..e1ed280 100644
--- a/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionListIterator.java
+++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionListIterator.java
@@ -34,6 +34,7 @@
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
+import java.util.function.Consumer;
public class BasicBlockInstructionListIterator implements InstructionListIterator {
@@ -350,8 +351,11 @@
}
@Override
- public boolean replaceCurrentInstructionByInitClassIfPossible(
- AppView<AppInfoWithLiveness> appView, IRCode code, DexType type) {
+ public boolean removeOrReplaceCurrentInstructionByInitClassIfPossible(
+ AppView<AppInfoWithLiveness> appView,
+ IRCode code,
+ DexType type,
+ Consumer<InitClass> consumer) {
Instruction toBeReplaced = current;
assert toBeReplaced != null;
assert toBeReplaced.isStaticFieldInstruction() || toBeReplaced.isInvokeStatic();
@@ -377,7 +381,9 @@
DexProgramClass clazz = asProgramClassOrNull(appView.definitionFor(type));
if (clazz != null) {
Value dest = code.createValue(TypeElement.getInt());
- replaceCurrentInstruction(new InitClass(dest, clazz.type));
+ InitClass initClass = new InitClass(dest, clazz.type);
+ replaceCurrentInstruction(initClass);
+ consumer.accept(initClass);
}
return true;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/IRCodeInstructionListIterator.java b/src/main/java/com/android/tools/r8/ir/code/IRCodeInstructionListIterator.java
index a68da1a..21b9df5 100644
--- a/src/main/java/com/android/tools/r8/ir/code/IRCodeInstructionListIterator.java
+++ b/src/main/java/com/android/tools/r8/ir/code/IRCodeInstructionListIterator.java
@@ -19,6 +19,7 @@
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.Set;
+import java.util.function.Consumer;
public class IRCodeInstructionListIterator implements InstructionListIterator {
@@ -62,9 +63,13 @@
}
@Override
- public boolean replaceCurrentInstructionByInitClassIfPossible(
- AppView<AppInfoWithLiveness> appView, IRCode code, DexType type) {
- return instructionIterator.replaceCurrentInstructionByInitClassIfPossible(appView, code, type);
+ public boolean removeOrReplaceCurrentInstructionByInitClassIfPossible(
+ AppView<AppInfoWithLiveness> appView,
+ IRCode code,
+ DexType type,
+ Consumer<InitClass> consumer) {
+ return instructionIterator.removeOrReplaceCurrentInstructionByInitClassIfPossible(
+ appView, code, type, consumer);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstructionListIterator.java b/src/main/java/com/android/tools/r8/ir/code/InstructionListIterator.java
index bc6bec6..f1eab89 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstructionListIterator.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstructionListIterator.java
@@ -15,10 +15,12 @@
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.ConsumerUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.Sets;
import java.util.ListIterator;
import java.util.Set;
+import java.util.function.Consumer;
public interface InstructionListIterator
extends InstructionIterator, ListIterator<Instruction>, PreviousUntilIterator<Instruction> {
@@ -109,8 +111,17 @@
boolean replaceCurrentInstructionByNullCheckIfPossible(AppView<?> appView, ProgramMethod context);
- boolean replaceCurrentInstructionByInitClassIfPossible(
- AppView<AppInfoWithLiveness> appView, IRCode code, DexType type);
+ default boolean removeOrReplaceCurrentInstructionByInitClassIfPossible(
+ AppView<AppInfoWithLiveness> appView, IRCode code, DexType type) {
+ return removeOrReplaceCurrentInstructionByInitClassIfPossible(
+ appView, code, type, ConsumerUtils.emptyConsumer());
+ }
+
+ boolean removeOrReplaceCurrentInstructionByInitClassIfPossible(
+ AppView<AppInfoWithLiveness> appView,
+ IRCode code,
+ DexType type,
+ Consumer<InitClass> consumer);
void replaceCurrentInstructionWithConstClass(
AppView<?> appView, IRCode code, DexType type, DebugLocalInfo localInfo);
diff --git a/src/main/java/com/android/tools/r8/ir/code/LinearFlowInstructionListIterator.java b/src/main/java/com/android/tools/r8/ir/code/LinearFlowInstructionListIterator.java
index 37d45df..ffb5d2b 100644
--- a/src/main/java/com/android/tools/r8/ir/code/LinearFlowInstructionListIterator.java
+++ b/src/main/java/com/android/tools/r8/ir/code/LinearFlowInstructionListIterator.java
@@ -18,6 +18,7 @@
import com.google.common.collect.Sets;
import java.util.ListIterator;
import java.util.Set;
+import java.util.function.Consumer;
public class LinearFlowInstructionListIterator implements InstructionListIterator {
@@ -86,9 +87,13 @@
}
@Override
- public boolean replaceCurrentInstructionByInitClassIfPossible(
- AppView<AppInfoWithLiveness> appView, IRCode code, DexType type) {
- return currentBlockIterator.replaceCurrentInstructionByInitClassIfPossible(appView, code, type);
+ public boolean removeOrReplaceCurrentInstructionByInitClassIfPossible(
+ AppView<AppInfoWithLiveness> appView,
+ IRCode code,
+ DexType type,
+ Consumer<InitClass> consumer) {
+ return currentBlockIterator.removeOrReplaceCurrentInstructionByInitClassIfPossible(
+ appView, code, type, consumer);
}
@Override
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 b1292dc..a52190d 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
@@ -401,11 +401,12 @@
.toTypeElement(appView);
}
};
+ prototypeChanges.verifyConstantReturnAccessibleInContext(
+ appView.withLiveness(), method, graphLens);
constantReturnMaterializingInstruction =
prototypeChanges.getConstantReturn(
appView.withLiveness(),
code,
- method,
invoke.getPosition(),
typeAndLocalInfo);
if (invoke.outValue().hasLocalInfo()) {
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 04ba47d..5dbfaba 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
@@ -14,11 +14,13 @@
import com.android.tools.r8.ir.code.CatchHandlers.CatchHandler;
import com.android.tools.r8.ir.code.CheckCast;
import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.code.InitClass;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.Phi;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.Timing;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
@@ -134,6 +136,23 @@
if (current.isInvoke() && !current.outValue().isUsed()) {
current.setOutValue(null);
}
+ if (current.isStaticGet() && !current.outValue().isUsed() && appView.hasLiveness()) {
+ Box<InitClass> initClass = new Box<>();
+ if (iterator.removeOrReplaceCurrentInstructionByInitClassIfPossible(
+ appView.withLiveness(),
+ code,
+ current.asStaticGet().getField().getHolderType(),
+ initClass::set)) {
+ if (initClass.isSet()) {
+ // Apply dead code remover to the new init-class instruction.
+ current = iterator.previous();
+ assert current == initClass.get();
+ } else {
+ // Instruction removed.
+ continue;
+ }
+ }
+ }
}
DeadInstructionResult deadInstructionResult = current.canBeDeadCode(appView, code);
if (deadInstructionResult.isNotDead()) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index 2c185bf..785c461 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -1099,7 +1099,7 @@
return false;
}
} else if (invoke.isInvokeStatic()) {
- if (!iterator.replaceCurrentInstructionByInitClassIfPossible(
+ if (!iterator.removeOrReplaceCurrentInstructionByInitClassIfPossible(
appView, code, resolvedMethod.getHolderType())) {
return false;
}
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 755f334..4807cda 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
@@ -246,7 +246,7 @@
iterator.replaceCurrentInstructionByNullCheckIfPossible(appView, code.context());
} else if (current.isStaticGet()) {
StaticGet staticGet = current.asStaticGet();
- iterator.replaceCurrentInstructionByInitClassIfPossible(
+ iterator.removeOrReplaceCurrentInstructionByInitClassIfPossible(
appView, code, staticGet.getField().holder);
}
replacement.setPosition(position);
@@ -333,7 +333,7 @@
if (invoke.isInvokeMethodWithReceiver()) {
iterator.replaceCurrentInstructionByNullCheckIfPossible(appView, context);
} else if (invoke.isInvokeStatic() && singleTarget != null) {
- iterator.replaceCurrentInstructionByInitClassIfPossible(
+ iterator.removeOrReplaceCurrentInstructionByInitClassIfPossible(
appView, code, singleTarget.getHolderType());
}
@@ -440,7 +440,7 @@
iterator.replaceCurrentInstructionByNullCheckIfPossible(appView, context);
} else {
assert current.isStaticGet();
- iterator.replaceCurrentInstructionByInitClassIfPossible(
+ iterator.removeOrReplaceCurrentInstructionByInitClassIfPossible(
appView, code, target.getHolderType());
}
@@ -491,7 +491,8 @@
return;
}
- iterator.replaceCurrentInstructionByInitClassIfPossible(appView, code, field.getHolderType());
+ iterator.removeOrReplaceCurrentInstructionByInitClassIfPossible(
+ appView, code, field.getHolderType());
}
/**
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java
index 5987d3c..15f68fc 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java
@@ -183,8 +183,7 @@
Lists.newArrayList(
"STATIC: String SimpleWithSideEffects.bar(String)",
"STATIC: String SimpleWithSideEffects.foo()",
- "STATIC: String TrivialTestClass.next()",
- "SimpleWithSideEffects SimpleWithSideEffects.INSTANCE"),
+ "STATIC: String TrivialTestClass.next()"),
references(clazz, "testSimpleWithSideEffects", "void"));
ClassSubject simpleWithSideEffects = inspector.clazz(SimpleWithSideEffects.class);
@@ -315,8 +314,7 @@
Lists.newArrayList(
"STATIC: String movetohost.CandidateOkSideEffects.bar(String)",
"STATIC: String movetohost.CandidateOkSideEffects.foo()",
- "STATIC: String movetohost.MoveToHostTestClass.next()",
- "movetohost.CandidateOkSideEffects movetohost.HostOkSideEffects.INSTANCE"),
+ "STATIC: String movetohost.MoveToHostTestClass.next()"),
references(clazz, "testOkSideEffects", "void"));
assertThat(inspector.clazz(HostOkSideEffects.class), isPresent());
diff --git a/src/test/java/com/android/tools/r8/ir/regalloc/RegisterMoveSchedulerTest.java b/src/test/java/com/android/tools/r8/ir/regalloc/RegisterMoveSchedulerTest.java
index b05928d..24f1672 100644
--- a/src/test/java/com/android/tools/r8/ir/regalloc/RegisterMoveSchedulerTest.java
+++ b/src/test/java/com/android/tools/r8/ir/regalloc/RegisterMoveSchedulerTest.java
@@ -21,6 +21,7 @@
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.BasicBlockIterator;
import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.code.InitClass;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.InvokeMethod;
@@ -34,6 +35,7 @@
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
+import java.util.function.Consumer;
import org.junit.Test;
public class RegisterMoveSchedulerTest {
@@ -84,8 +86,11 @@
}
@Override
- public boolean replaceCurrentInstructionByInitClassIfPossible(
- AppView<AppInfoWithLiveness> appView, IRCode code, DexType type) {
+ public boolean removeOrReplaceCurrentInstructionByInitClassIfPossible(
+ AppView<AppInfoWithLiveness> appView,
+ IRCode code,
+ DexType type,
+ Consumer<InitClass> consumer) {
throw new Unimplemented();
}