Insert assume instructions during StaticizingProcessor's reprocessing.
Bug: 143733090, 140767158
Change-Id: I959b197f32f99e8037c8e47c6f5370f586939194
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 0552b9f..358a7fe 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
@@ -48,6 +48,7 @@
import com.android.tools.r8.ir.desugar.StringConcatRewriter;
import com.android.tools.r8.ir.desugar.TwrCloseResourceRewriter;
import com.android.tools.r8.ir.optimize.AliasIntroducer;
+import com.android.tools.r8.ir.optimize.Assumer;
import com.android.tools.r8.ir.optimize.ClassInitializerDefaultsOptimization;
import com.android.tools.r8.ir.optimize.CodeRewriter;
import com.android.tools.r8.ir.optimize.ConstantCanonicalizer;
@@ -155,13 +156,12 @@
private final ServiceLoaderRewriter serviceLoaderRewriter;
// Assumers that will insert Assume instructions.
- private final AliasIntroducer aliasIntroducer;
+ public final Collection<Assumer> assumers = new ArrayList<>();
private final DynamicTypeOptimization dynamicTypeOptimization;
- private final NonNullTracker nonNullTracker;
final DeadCodeRemover deadCodeRemover;
- final MethodOptimizationInfoCollector methodOptimizationInfoCollector;
+ private final MethodOptimizationInfoCollector methodOptimizationInfoCollector;
private final OptimizationFeedbackDelayed delayedOptimizationFeedback =
new OptimizationFeedbackDelayed();
@@ -219,8 +219,6 @@
this.twrCloseResourceRewriter = null;
this.lambdaMerger = null;
this.covariantReturnTypeAnnotationTransformer = null;
- this.aliasIntroducer = null;
- this.nonNullTracker = null;
this.dynamicTypeOptimization = null;
this.classInliner = null;
this.classStaticizer = null;
@@ -258,9 +256,12 @@
options.processCovariantReturnTypeAnnotations
? new CovariantReturnTypeAnnotationTransformer(this, appView.dexItemFactory())
: null;
- this.aliasIntroducer =
- options.testing.forceAssumeNoneInsertion ? new AliasIntroducer(appView) : null;
- this.nonNullTracker = options.enableNonNullTracking ? new NonNullTracker(appView) : null;
+ if (options.testing.forceAssumeNoneInsertion) {
+ assumers.add(new AliasIntroducer(appView));
+ }
+ if (options.enableNonNullTracking) {
+ assumers.add(new NonNullTracker(appView));
+ }
this.desugaredLibraryAPIConverter =
appView.rewritePrefix.isRewriting() ? new DesugaredLibraryAPIConverter(appView) : null;
if (appView.enableWholeProgramOptimizations()) {
@@ -277,6 +278,9 @@
options.enableDynamicTypeOptimization
? new DynamicTypeOptimization(appViewWithLiveness)
: null;
+ if (dynamicTypeOptimization != null) {
+ assumers.add(dynamicTypeOptimization);
+ }
this.fieldBitAccessAnalysis =
options.enableFieldBitAccessAnalysis
? new FieldBitAccessAnalysis(appViewWithLiveness)
@@ -1146,25 +1150,13 @@
previous = printMethod(code, "IR after disable assertions (SSA)", previous);
- if (aliasIntroducer != null) {
- aliasIntroducer.insertAssumeInstructions(code);
- assert code.isConsistentSSA();
- }
+ CodeRewriter.insertAssumeInstructions(code, assumers);
- if (nonNullTracker != null) {
- nonNullTracker.insertAssumeInstructions(code);
- assert code.isConsistentSSA();
- }
-
- if (dynamicTypeOptimization != null) {
- assert appView.enableWholeProgramOptimizations();
- dynamicTypeOptimization.insertAssumeInstructions(code);
- assert code.isConsistentSSA();
- }
+ previous = printMethod(code, "IR after inserting assume instructions (SSA)", previous);
appView.withGeneratedMessageLiteShrinker(shrinker -> shrinker.run(method, code));
- previous = printMethod(code, "IR after null tracking (SSA)", previous);
+ previous = printMethod(code, "IR after generated message lite shrinking (SSA)", previous);
if (!isDebugMode && options.enableInlining && inliner != null) {
inliner.performInlining(method, code, feedback, methodProcessor);
@@ -1393,7 +1385,7 @@
collectOptimizationInfo(code, feedback);
}
- if (aliasIntroducer != null || nonNullTracker != null || dynamicTypeOptimization != null) {
+ if (!assumers.isEmpty()) {
CodeRewriter.removeAssumeInstructions(appView, code);
assert code.isConsistentSSA();
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Assumer.java b/src/main/java/com/android/tools/r8/ir/optimize/Assumer.java
index 10e7314..dfabec5 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Assumer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Assumer.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.optimize;
+import com.android.tools.r8.Keep;
import com.android.tools.r8.ir.code.Assume;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
@@ -13,10 +14,14 @@
/**
* One that assumes. Inherited tracker/optimization insert necessary variants of {@link Assume}.
*/
-interface Assumer {
+// TODO(b/143590191): should not need an explicit keep annotation to prevent the default interface
+// method from being shrunk.
+@Keep
+public interface Assumer {
default void insertAssumeInstructions(IRCode code) {
insertAssumeInstructionsInBlocks(code, code.listIterator(), Predicates.alwaysTrue());
}
+
void insertAssumeInstructionsInBlocks(
IRCode code, ListIterator<BasicBlock> blockIterator, Predicate<BasicBlock> blockTester);
}
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 f6fba1d..8925262 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
@@ -159,6 +159,13 @@
this.dexItemFactory = appView.dexItemFactory();
}
+ public static void insertAssumeInstructions(IRCode code, Collection<Assumer> assumers) {
+ for (Assumer assumer : assumers) {
+ assumer.insertAssumeInstructions(code);
+ assert code.isConsistentSSA();
+ }
+ }
+
public static void removeAssumeInstructions(AppView<?> appView, IRCode code) {
// We need to update the types of all values whose definitions depend on a non-null value.
// This is needed to preserve soundness of the types after the Assume<NonNullAssumption>
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
index 158fd9c..b98cff8 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
@@ -289,6 +289,7 @@
Origin origin = appView.appInfo().originFor(method.method.holder);
IRCode code = method.buildIR(appView, origin);
codeOptimizations.forEach(codeOptimization -> codeOptimization.accept(code));
+ CodeRewriter.insertAssumeInstructions(code, converter.assumers);
converter.collectOptimizationInfo(code, feedback);
CodeRewriter.removeAssumeInstructions(appView, code);
converter.finalizeIR(method, code, feedback);