StringBuilderAppendOptimizer as CodeRewriterPass
Bug: b/284304606
Change-Id: Idbea2ef38aa7609578d27a0d554b97734562df6e
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 6007ea9..8522b13 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
@@ -753,9 +753,7 @@
new ArrayConstructionSimplifier(appView).run(code, timing);
new MoveResultRewriter(appView).run(code, timing);
if (options.enableStringConcatenationOptimization && !isDebugMode) {
- timing.begin("Rewrite string concat");
- StringBuilderAppendOptimizer.run(appView, code);
- timing.end();
+ new StringBuilderAppendOptimizer(appView).run(code, timing);
}
timing.begin("Propagate sparse conditionals");
new SparseConditionalConstantPropagation(appView, code).run();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderAppendOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderAppendOptimizer.java
index 2798fb0..2ff8ec9 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderAppendOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderAppendOptimizer.java
@@ -16,6 +16,7 @@
import static com.android.tools.r8.ir.optimize.string.StringBuilderNode.createToStringNode;
import static com.android.tools.r8.utils.FunctionUtils.ignoreArgument;
+import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.ir.analysis.framework.intraprocedural.DataflowAnalysisResult.SuccessfulDataflowAnalysisResult;
import com.android.tools.r8.ir.analysis.framework.intraprocedural.IntraProceduralDataflowAnalysisOptions;
@@ -30,6 +31,8 @@
import com.android.tools.r8.ir.code.InvokeStatic;
import com.android.tools.r8.ir.code.Phi;
import com.android.tools.r8.ir.code.Value;
+import com.android.tools.r8.ir.conversion.passes.CodeRewriterPass;
+import com.android.tools.r8.ir.conversion.passes.result.CodeRewriterResult;
import com.android.tools.r8.ir.optimize.string.StringBuilderNode.AppendNode;
import com.android.tools.r8.ir.optimize.string.StringBuilderNode.ImplicitToStringNode;
import com.android.tools.r8.ir.optimize.string.StringBuilderNode.InitNode;
@@ -75,29 +78,33 @@
*
* <p>Finally, based on all optimizations, the IR is updated to reflect the optimizations.
*/
-public class StringBuilderAppendOptimizer {
+public class StringBuilderAppendOptimizer extends CodeRewriterPass<AppInfo> {
- private final AppView<?> appView;
private final StringBuilderOracle oracle;
- private final IRCode code;
-
private static final int NUMBER_OF_MUNCHING_PASSES = 3;
- private StringBuilderAppendOptimizer(AppView<?> appView, IRCode code) {
- this.appView = appView;
- this.code = code;
+ public StringBuilderAppendOptimizer(AppView<?> appView) {
+ super(appView);
oracle = new DefaultStringBuilderOracle(appView.dexItemFactory());
}
- public static void run(AppView<?> appView, IRCode code) {
- new StringBuilderAppendOptimizer(appView, code).run();
+ @Override
+ protected String getTimingId() {
+ return "StringBuilderAppendOptimizer";
}
- private void run() {
- Map<Value, StringBuilderNode> stringBuilderGraphs = computeStringBuilderGraphs();
- Map<Instruction, StringBuilderAction> actions = optimizeOnGraphs(stringBuilderGraphs);
+ @Override
+ protected boolean shouldRewriteCode(IRCode code) {
+ return code.metadata().mayHaveNewInstance()
+ || code.metadata().mayHaveInvokeMethodWithReceiver();
+ }
+
+ @Override
+ protected CodeRewriterResult rewriteCode(IRCode code) {
+ Map<Value, StringBuilderNode> stringBuilderGraphs = computeStringBuilderGraphs(code);
+ Map<Instruction, StringBuilderAction> actions = optimizeOnGraphs(code, stringBuilderGraphs);
if (actions.isEmpty()) {
- return;
+ return CodeRewriterResult.NO_CHANGE;
}
InstructionListIterator it = code.instructionListIterator();
while (it.hasNext()) {
@@ -108,6 +115,7 @@
}
}
code.removeAllDeadAndTrivialPhis();
+ return CodeRewriterResult.HAS_CHANGED;
}
private static class StringBuilderGraphState {
@@ -137,7 +145,7 @@
* answer, for a given instruction, is a string builder value escaping and all escaped values
* at the instruction.
*/
- private Map<Value, StringBuilderNode> computeStringBuilderGraphs() {
+ private Map<Value, StringBuilderNode> computeStringBuilderGraphs(IRCode code) {
StringBuilderEscapeTransferFunction transferFunction =
new StringBuilderEscapeTransferFunction(oracle);
IntraproceduralDataflowAnalysis<StringBuilderEscapeState> analysis =
@@ -516,7 +524,7 @@
* the munching and care about performance.
*/
private Map<Instruction, StringBuilderAction> optimizeOnGraphs(
- Map<Value, StringBuilderNode> stringBuilderGraphs) {
+ IRCode code, Map<Value, StringBuilderNode> stringBuilderGraphs) {
Map<Instruction, StringBuilderAction> actions = new IdentityHashMap<>();
// Build state to allow munching over the string builder graphs.
Map<StringBuilderNode, NewInstanceNode> newInstances = new IdentityHashMap<>();