Minor updates in preparation for constructor inlining
Change-Id: Iee0ee6fb319658a2495bc7b8f24d7b42a16901f1
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/bridge/BridgeAnalyzer.java b/src/main/java/com/android/tools/r8/ir/optimize/info/bridge/BridgeAnalyzer.java
index be806b4..88ee7f1 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/bridge/BridgeAnalyzer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/bridge/BridgeAnalyzer.java
@@ -6,14 +6,18 @@
import static com.android.tools.r8.ir.code.Opcodes.ARGUMENT;
import static com.android.tools.r8.ir.code.Opcodes.ASSUME;
import static com.android.tools.r8.ir.code.Opcodes.CHECK_CAST;
+import static com.android.tools.r8.ir.code.Opcodes.GOTO;
import static com.android.tools.r8.ir.code.Opcodes.INVOKE_DIRECT;
import static com.android.tools.r8.ir.code.Opcodes.INVOKE_VIRTUAL;
import static com.android.tools.r8.ir.code.Opcodes.RETURN;
import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.CheckCast;
+import com.android.tools.r8.ir.code.Goto;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.code.InvokeMethodWithReceiver;
import com.android.tools.r8.ir.code.Return;
@@ -24,17 +28,15 @@
/** Returns a {@link BridgeInfo} object describing this method if it is recognized as a bridge. */
public static BridgeInfo analyzeMethod(DexEncodedMethod method, IRCode code) {
- if (code.blocks.size() > 1) {
- return failure();
- }
-
// Scan through the instructions one-by-one. We expect a sequence of Argument instructions,
// followed by a (possibly empty) sequence of CheckCast instructions, followed by a single
// InvokeMethod instruction, followed by an optional CheckCast instruction, followed by a Return
// instruction.
InvokeMethodWithReceiver uniqueInvoke = null;
CheckCast uniqueReturnCast = null;
- for (Instruction instruction : code.entryBlock().getInstructions()) {
+ InstructionListIterator instructionIterator = code.entryBlock().listIterator(code);
+ while (instructionIterator.hasNext()) {
+ Instruction instruction = instructionIterator.next();
switch (instruction.opcode()) {
case ARGUMENT:
break;
@@ -74,6 +76,17 @@
break;
}
+ case GOTO:
+ {
+ Goto gotoInstruction = instruction.asGoto();
+ BasicBlock targetBlock = gotoInstruction.getTarget();
+ if (targetBlock.hasCatchHandlers()) {
+ return failure();
+ }
+ instructionIterator = targetBlock.listIterator(code);
+ break;
+ }
+
case RETURN:
if (!analyzeReturn(instruction.asReturn(), uniqueInvoke, uniqueReturnCast)) {
return failure();
@@ -107,8 +120,10 @@
}
int argumentIndex = object.definition.asArgument().getIndex();
Value castValue = checkCast.outValue();
- // The out value cannot have any phi users since there is only one block.
- assert !castValue.hasPhiUsers();
+ // The out value should not have any phi users since we only allow linear control flow.
+ if (castValue.hasPhiUsers()) {
+ return false;
+ }
// It is not allowed to have any other users than the invoke instruction.
if (castValue.hasDebugUsers() || !castValue.hasSingleUniqueUser()) {
return false;
@@ -142,8 +157,10 @@
Value returnValue = invoke.outValue();
Value uncastValue = checkCast.object().getAliasedValue();
Value castValue = checkCast.outValue();
- // The out value cannot have any phi users since there is only one block.
- assert !castValue.hasPhiUsers();
+ // The out value should not have any phi users since we only allow linear control flow.
+ if (castValue.hasPhiUsers()) {
+ return false;
+ }
// It must cast the result to the return type of the enclosing method and return the cast value.
return uncastValue == returnValue
&& checkCast.getType() == method.returnType()
diff --git a/src/main/java/com/android/tools/r8/optimize/redundantbridgeremoval/RedundantBridgeRemover.java b/src/main/java/com/android/tools/r8/optimize/redundantbridgeremoval/RedundantBridgeRemover.java
index d8ec5a2..44c94c4 100644
--- a/src/main/java/com/android/tools/r8/optimize/redundantbridgeremoval/RedundantBridgeRemover.java
+++ b/src/main/java/com/android/tools/r8/optimize/redundantbridgeremoval/RedundantBridgeRemover.java
@@ -116,6 +116,9 @@
if (kind == InvokeKind.STATIC) {
return appView.appInfo().isStrictSubtypeOf(method.getHolderType(), target.holder);
}
+ if (kind == InvokeKind.VIRTUAL) {
+ return false;
+ }
assert false : "Unexpected invoke-kind for visibility bridge: " + kind;
return false;
}
diff --git a/src/test/java/com/android/tools/r8/accessrelaxation/EffectiveFinalFieldMarkedFinalTest.java b/src/test/java/com/android/tools/r8/accessrelaxation/EffectiveFinalFieldMarkedFinalTest.java
index 83d80c8..d491189 100644
--- a/src/test/java/com/android/tools/r8/accessrelaxation/EffectiveFinalFieldMarkedFinalTest.java
+++ b/src/test/java/com/android/tools/r8/accessrelaxation/EffectiveFinalFieldMarkedFinalTest.java
@@ -10,6 +10,7 @@
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.MatcherAssert.assertThat;
+import com.android.tools.r8.NoRedundantFieldLoadElimination;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.utils.BooleanUtils;
@@ -42,6 +43,7 @@
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
.allowAccessModification(allowAccessModification)
+ .enableNoRedundantFieldLoadEliminationAnnotations()
.setMinApi(parameters)
.compile()
.inspect(
@@ -63,6 +65,7 @@
static String staticField = System.currentTimeMillis() > 0 ? "Hello" : null;
+ @NoRedundantFieldLoadElimination
String instanceField = System.currentTimeMillis() > 0 ? ", world!" : null;
public static void main(String[] args) {
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelNoVerticalMergingSubReferenceApiTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelNoVerticalMergingSubReferenceApiTest.java
index abee6a9..dff5d14 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelNoVerticalMergingSubReferenceApiTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelNoVerticalMergingSubReferenceApiTest.java
@@ -6,6 +6,7 @@
import static com.android.tools.r8.apimodel.ApiModelingTestHelper.setMockApiLevelForMethod;
import static com.android.tools.r8.utils.AndroidApiLevel.L_MR1;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsentIf;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static junit.framework.TestCase.assertEquals;
import static org.hamcrest.CoreMatchers.not;
@@ -77,7 +78,9 @@
assertThat(base, not(isPresent()));
ClassSubject sub = inspector.clazz(Sub.class);
assertThat(sub, isPresent());
- assertThat(sub.uniqueInstanceInitializer(), isPresent());
+ assertThat(
+ sub.uniqueInstanceInitializer(),
+ isAbsentIf(parameters.canHaveNonReboundConstructorInvoke()));
assertEquals(1, sub.virtualMethods().size());
FoundMethodSubject callCallApi = sub.virtualMethods().get(0);
assertEquals("callCallApi", callCallApi.getOriginalName());
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelNoVerticalMergingTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelNoVerticalMergingTest.java
index 7bc2df5..2e368e9 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelNoVerticalMergingTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelNoVerticalMergingTest.java
@@ -6,6 +6,7 @@
import static com.android.tools.r8.apimodel.ApiModelingTestHelper.setMockApiLevelForMethod;
import static com.android.tools.r8.utils.AndroidApiLevel.L_MR1;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsentIf;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static junit.framework.TestCase.assertEquals;
import static org.hamcrest.CoreMatchers.not;
@@ -76,7 +77,9 @@
assertThat(base, not(isPresent()));
ClassSubject sub = inspector.clazz(Sub.class);
assertThat(sub, isPresent());
- assertThat(sub.uniqueInstanceInitializer(), isPresent());
+ assertThat(
+ sub.uniqueInstanceInitializer(),
+ isAbsentIf(parameters.canHaveNonReboundConstructorInvoke()));
assertEquals(1, sub.virtualMethods().size());
FoundMethodSubject callCallApi = sub.virtualMethods().get(0);
assertEquals("callCallApi", callCallApi.getOriginalName());
diff --git a/src/test/java/com/android/tools/r8/classmerging/StatefulSingletonClassesMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/StatefulSingletonClassesMergingTest.java
index c36c12b..3604880 100644
--- a/src/test/java/com/android/tools/r8/classmerging/StatefulSingletonClassesMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/StatefulSingletonClassesMergingTest.java
@@ -85,7 +85,7 @@
static final B INSTANCE = new B("B");
- @NeverPropagateValue private final String data;
+ @NeverPropagateValue private String data;
// TODO(b/198758663): With argument propagation the constructors end up not being equivalent,
// which prevents merging in the final round of horizontal class merging.
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/singleton/SingletonFieldValuePropagationEnumWithSubclassTest.java b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/singleton/SingletonFieldValuePropagationEnumWithSubclassTest.java
index 657d32e..fc7b6d5 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/singleton/SingletonFieldValuePropagationEnumWithSubclassTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/singleton/SingletonFieldValuePropagationEnumWithSubclassTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.ir.optimize.membervaluepropagation.fields.singleton;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
@@ -36,6 +37,10 @@
testForR8(parameters.getBackend())
.addInnerClasses(SingletonFieldValuePropagationEnumWithSubclassTest.class)
.addKeepMainRule(TestClass.class)
+ .addEnumUnboxingInspector(
+ inspector ->
+ inspector.assertUnboxedIf(
+ parameters.canInitNewInstanceUsingSuperclassConstructor(), Characters.class))
.setMinApi(parameters)
.compile()
.inspect(this::inspect)
@@ -44,10 +49,14 @@
}
private void inspect(CodeInspector inspector) {
- ClassSubject charactersClassSubject = inspector.clazz(Characters.class);
- assertThat(charactersClassSubject, isPresent());
- // TODO(b/150368955): Field value propagation should cause Characters.value to become dead.
- assertEquals(1, charactersClassSubject.allInstanceFields().size());
+ if (parameters.canInitNewInstanceUsingSuperclassConstructor()) {
+ assertThat(inspector.clazz(Characters.class), isAbsent());
+ } else {
+ ClassSubject charactersClassSubject = inspector.clazz(Characters.class);
+ assertThat(charactersClassSubject, isPresent());
+ // TODO(b/150368955): Field value propagation should cause Characters.value to become dead.
+ assertEquals(1, charactersClassSubject.allInstanceFields().size());
+ }
}
static class TestClass {
diff --git a/src/test/java/com/android/tools/r8/shaking/RetainIndirectlyReferencedConstructorShakingOnDexTest.java b/src/test/java/com/android/tools/r8/shaking/RetainIndirectlyReferencedConstructorShakingOnDexTest.java
index 65d8260..a3d1fef 100644
--- a/src/test/java/com/android/tools/r8/shaking/RetainIndirectlyReferencedConstructorShakingOnDexTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/RetainIndirectlyReferencedConstructorShakingOnDexTest.java
@@ -48,11 +48,13 @@
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
.addOptionsModification(
- options ->
- options
- .getRedundantBridgeRemovalOptions()
- .setEnableRetargetingOfConstructorBridgeCalls(
- enableRetargetingOfConstructorBridgeCalls))
+ options -> {
+ options.inlinerOptions().setEnableConstructorInlining(false);
+ options
+ .getRedundantBridgeRemovalOptions()
+ .setEnableRetargetingOfConstructorBridgeCalls(
+ enableRetargetingOfConstructorBridgeCalls);
+ })
.enableInliningAnnotations()
.enableNoVerticalClassMergingAnnotations()
.setMinApi(parameters)