Force strongly connected phis to resolve for unused arguments
Bug:b/240282988
Change-Id: I182a84424ecb3a6f7d2807588b81d833c7b6e78b
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 207da48..173161f 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
@@ -103,6 +103,7 @@
import com.android.tools.r8.ir.code.UnusedArgument;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.code.ValueType;
+import com.android.tools.r8.ir.optimize.CodeRewriter;
import com.android.tools.r8.ir.optimize.enums.EnumUnboxer;
import com.android.tools.r8.optimize.MemberRebindingAnalysis;
import com.android.tools.r8.optimize.argumentpropagation.lenscoderewriter.NullCheckInserter;
@@ -224,6 +225,15 @@
assert graphLens.getPrevious() == codeLens;
affectedPhis.addAll(enumUnboxer.rewriteCode(code, methodProcessor, prototypeChanges));
}
+ if (!unusedArguments.isEmpty()) {
+ for (UnusedArgument unusedArgument : unusedArguments) {
+ if (unusedArgument.outValue().hasPhiUsers()) {
+ // See b/240282988: We can end up in situations where the second round of IR processing
+ // introduce phis for irreducible control flow, we need to resolve them.
+ CodeRewriter.replaceUnusedArgumentTrivialPhis(unusedArgument);
+ }
+ }
+ }
rewritePartialDefault(
code, method, graphLens, codeLens, prototypeChanges, affectedPhis, unusedArguments);
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index 38afb5d..401c5f2 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -95,6 +95,7 @@
import com.android.tools.r8.ir.code.StaticGet;
import com.android.tools.r8.ir.code.Switch;
import com.android.tools.r8.ir.code.Throw;
+import com.android.tools.r8.ir.code.UnusedArgument;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.code.Xor;
@@ -3738,6 +3739,14 @@
iterator.add(new InvokeVirtual(printLn, null, ImmutableList.of(out, empty)));
}
+ public static void replaceUnusedArgumentTrivialPhis(UnusedArgument unusedArgument) {
+ replaceTrivialPhis(unusedArgument.outValue());
+ for (Phi phiUser : unusedArgument.outValue().uniquePhiUsers()) {
+ phiUser.removeTrivialPhi();
+ }
+ assert !unusedArgument.outValue().hasPhiUsers();
+ }
+
public static void ensureDirectStringNewToInit(IRCode code, DexItemFactory dexItemFactory) {
for (Instruction instruction : code.instructions()) {
if (instruction.isInvokeDirect()) {
@@ -3747,7 +3756,7 @@
&& method.holder == dexItemFactory.stringType
&& invoke.getReceiver().isPhi()) {
NewInstance newInstance = findNewInstance(invoke.getReceiver().asPhi());
- replaceTrivialNewInstancePhis(newInstance.outValue());
+ replaceTrivialPhis(newInstance.outValue());
if (invoke.getReceiver().isPhi()) {
throw new CompilationError(
"Failed to remove trivial phis between new-instance and <init>");
@@ -3810,18 +3819,15 @@
}
}
- // If an <init> call takes place on a phi the code must contain an irreducible loop between the
- // new-instance and the <init>. Assuming the code is verifiable, new-instance must flow to a
- // unique <init>. Here we compute the set of strongly connected phis making use of the
- // new-instance value and replace all trivial ones by the new-instance value.
+ // We compute the set of strongly connected phis making use of the out value and replace all
+ // trivial ones by the out value.
// This is a simplified variant of the removeRedundantPhis algorithm in Section 3.2 of:
// http://compilers.cs.uni-saarland.de/papers/bbhlmz13cc.pdf
- private static void replaceTrivialNewInstancePhis(Value newInstanceValue) {
- List<Set<Value>> components =
- new SCC<Value>(Value::uniquePhiUsers).computeSCC(newInstanceValue);
+ private static void replaceTrivialPhis(Value outValue) {
+ List<Set<Value>> components = new SCC<Value>(Value::uniquePhiUsers).computeSCC(outValue);
for (int i = components.size() - 1; i >= 0; i--) {
Set<Value> component = components.get(i);
- if (component.size() == 1 && component.iterator().next() == newInstanceValue) {
+ if (component.size() == 1 && component.iterator().next() == outValue) {
continue;
}
Set<Phi> trivialPhis = Sets.newIdentityHashSet();
@@ -3829,7 +3835,7 @@
boolean isTrivial = true;
Phi p = value.asPhi();
for (Value op : p.getOperands()) {
- if (op != newInstanceValue && !component.contains(op)) {
+ if (op != value && !component.contains(op)) {
isTrivial = false;
break;
}
@@ -3842,7 +3848,7 @@
for (Value op : trivialPhi.getOperands()) {
op.removePhiUser(trivialPhi);
}
- trivialPhi.replaceUsers(newInstanceValue);
+ trivialPhi.replaceUsers(outValue);
trivialPhi.getBlock().removePhi(trivialPhi);
}
}