Simplify StringSwitch conversion
Fixes: b/325395722
Change-Id: Ie6ae28aa1bcf781394268d049a8f600fbf2c2111
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index 994ef53..b95529b 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -742,10 +742,6 @@
new TypeAnalysis(appView, ir).narrowing();
}
- if (conversionOptions.isStringSwitchConversionEnabled()) {
- StringSwitchConverter.convertToStringSwitchInstructions(ir, appView.dexItemFactory());
- }
-
ir.removeRedundantBlocks();
assert ir.isConsistentSSABeforeTypesAreCorrect(appView);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java
index 846d0c7..25df747 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java
@@ -19,6 +19,7 @@
import com.android.tools.r8.ir.conversion.passes.DexItemBasedConstStringRemover;
import com.android.tools.r8.ir.conversion.passes.FilledNewArrayRewriter;
import com.android.tools.r8.ir.conversion.passes.InitClassRemover;
+import com.android.tools.r8.ir.conversion.passes.StringSwitchConverter;
import com.android.tools.r8.ir.conversion.passes.StringSwitchRemover;
import com.android.tools.r8.ir.optimize.ConstantCanonicalizer;
import com.android.tools.r8.ir.optimize.DeadCodeRemover;
@@ -42,8 +43,9 @@
assert appView.testing().canUseLir(appView);
assert appView.testing().isPreLirPhase();
appView.testing().enterLirSupportedPhase();
- ConstResourceNumberRewriter constResourceNumberRewriter =
- new ConstResourceNumberRewriter(appView);
+ CodeRewriterPassCollection codeRewriterPassCollection =
+ new CodeRewriterPassCollection(
+ new ConstResourceNumberRewriter(appView), new StringSwitchConverter(appView));
// Convert code objects to LIR.
ThreadUtils.processItems(
appView.appInfo().classes(),
@@ -53,7 +55,7 @@
method -> {
assert !method.getDefinition().getCode().hasExplicitCodeLens();
IRCode code = method.buildIR(appView, MethodConversionOptions.forLirPhase(appView));
- constResourceNumberRewriter.run(code, Timing.empty());
+ codeRewriterPassCollection.run(code, null, null, Timing.empty());
LirCode<Integer> lirCode =
IR2LirConverter.translate(
code,
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/MethodConversionOptions.java b/src/main/java/com/android/tools/r8/ir/conversion/MethodConversionOptions.java
index 24f7613..fd3c580 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/MethodConversionOptions.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/MethodConversionOptions.java
@@ -7,7 +7,6 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.ir.optimize.DeadCodeRemover;
-import com.android.tools.r8.utils.InternalOptions;
public abstract class MethodConversionOptions {
@@ -16,7 +15,7 @@
return forD8(appView);
}
assert appView.testing().isPreLirPhase();
- return new MutableMethodConversionOptions(Target.CF, appView.options());
+ return new MutableMethodConversionOptions(Target.CF);
}
public static MutableMethodConversionOptions forPostLirPhase(AppView<?> appView) {
@@ -25,8 +24,7 @@
}
assert appView.testing().isPostLirPhase();
Target target = appView.options().isGeneratingClassFiles() ? Target.CF : Target.DEX;
- return new MutableMethodConversionOptions(target, appView.options())
- .disableStringSwitchConversion();
+ return new MutableMethodConversionOptions(target);
}
public static MutableMethodConversionOptions forLirPhase(AppView<?> appView) {
@@ -34,12 +32,12 @@
return forD8(appView);
}
assert appView.testing().isSupportedLirPhase();
- return new MutableMethodConversionOptions(determineTarget(appView), appView.options());
+ return new MutableMethodConversionOptions(determineTarget(appView));
}
public static MutableMethodConversionOptions forD8(AppView<?> appView) {
assert !appView.enableWholeProgramOptimizations();
- return new MutableMethodConversionOptions(determineTarget(appView), appView.options());
+ return new MutableMethodConversionOptions(determineTarget(appView));
}
public static MutableMethodConversionOptions nonConverting() {
@@ -82,24 +80,16 @@
public abstract boolean isPeepholeOptimizationsEnabled();
- public abstract boolean isStringSwitchConversionEnabled();
-
public abstract boolean shouldFinalizeAfterLensCodeRewriter();
public static class MutableMethodConversionOptions extends MethodConversionOptions {
- private Target target;
+ private final Target target;
private boolean enablePeepholeOptimizations = true;
- private boolean enableStringSwitchConversion;
private boolean finalizeAfterLensCodeRewriter;
- private MutableMethodConversionOptions(Target target, boolean enableStringSwitchConversion) {
+ private MutableMethodConversionOptions(Target target) {
this.target = target;
- this.enableStringSwitchConversion = enableStringSwitchConversion;
- }
-
- private MutableMethodConversionOptions(Target target, InternalOptions options) {
- this(target, options.isStringSwitchConversionEnabled());
}
public void disablePeepholeOptimizations(MethodProcessor methodProcessor) {
@@ -107,11 +97,6 @@
enablePeepholeOptimizations = false;
}
- public MutableMethodConversionOptions disableStringSwitchConversion() {
- enableStringSwitchConversion = false;
- return this;
- }
-
public MutableMethodConversionOptions setFinalizeAfterLensCodeRewriter() {
finalizeAfterLensCodeRewriter = true;
return this;
@@ -138,11 +123,6 @@
}
@Override
- public boolean isStringSwitchConversionEnabled() {
- return enableStringSwitchConversion;
- }
-
- @Override
public boolean shouldFinalizeAfterLensCodeRewriter() {
return finalizeAfterLensCodeRewriter;
}
@@ -151,7 +131,7 @@
public static class ThrowingMethodConversionOptions extends MutableMethodConversionOptions {
private ThrowingMethodConversionOptions() {
- super(null, true);
+ super(null);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/passes/CodeRewriterPass.java b/src/main/java/com/android/tools/r8/ir/conversion/passes/CodeRewriterPass.java
index 98a92e8..87fc847 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/passes/CodeRewriterPass.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/passes/CodeRewriterPass.java
@@ -59,7 +59,7 @@
return noChange();
}
- private boolean verifyConsistentCode(IRCode code, boolean ssa, String preposition) {
+ protected boolean verifyConsistentCode(IRCode code, boolean ssa, String preposition) {
boolean result;
String message = "Invalid code " + preposition + " " + getRewriterId();
try {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/passes/ConstResourceNumberRewriter.java b/src/main/java/com/android/tools/r8/ir/conversion/passes/ConstResourceNumberRewriter.java
index e6806fc..7783c5c 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/passes/ConstResourceNumberRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/passes/ConstResourceNumberRewriter.java
@@ -62,4 +62,10 @@
}
return CodeRewriterResult.hasChanged(hasChanged);
}
+
+ @Override
+ protected boolean verifyConsistentCode(IRCode code, boolean ssa, String preposition) {
+ // Skip verification since this runs prior to the removal of invalid code.
+ return true;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/StringSwitchConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/passes/StringSwitchConverter.java
similarity index 95%
rename from src/main/java/com/android/tools/r8/ir/conversion/StringSwitchConverter.java
rename to src/main/java/com/android/tools/r8/ir/conversion/passes/StringSwitchConverter.java
index 5d7faef..a49b93b 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/StringSwitchConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/passes/StringSwitchConverter.java
@@ -1,12 +1,15 @@
-// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
+// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-package com.android.tools.r8.ir.conversion;
+package com.android.tools.r8.ir.conversion.passes;
import static com.android.tools.r8.ir.code.ConstNumber.asConstNumberOrNull;
+import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.ir.code.BasicBlock;
@@ -24,6 +27,8 @@
import com.android.tools.r8.ir.code.Phi;
import com.android.tools.r8.ir.code.StringSwitch;
import com.android.tools.r8.ir.code.Value;
+import com.android.tools.r8.ir.conversion.MethodProcessor;
+import com.android.tools.r8.ir.conversion.passes.result.CodeRewriterResult;
import com.google.common.collect.Sets;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;
@@ -105,10 +110,28 @@
* }
* </pre>
*/
-public class StringSwitchConverter {
+public class StringSwitchConverter extends CodeRewriterPass<AppInfo> {
- public static boolean convertToStringSwitchInstructions(
- IRCode code, DexItemFactory dexItemFactory) {
+ public StringSwitchConverter(AppView<?> appView) {
+ super(appView);
+ }
+
+ @Override
+ protected String getRewriterId() {
+ return "StringSwitchConverter";
+ }
+
+ @Override
+ protected boolean shouldRewriteCode(IRCode code, MethodProcessor methodProcessor) {
+ return options.shouldCompileMethodInReleaseMode(appView, code.context())
+ && options.enableStringSwitchConversion;
+ }
+
+ @Override
+ protected CodeRewriterResult rewriteCode(
+ IRCode code,
+ MethodProcessor methodProcessor,
+ MethodProcessingContext methodProcessingContext) {
List<BasicBlock> rewritingCandidates = getRewritingCandidates(code, dexItemFactory);
if (rewritingCandidates != null) {
boolean changed = false;
@@ -121,9 +144,15 @@
code.removeAllDeadAndTrivialPhis();
code.removeUnreachableBlocks();
}
- return changed;
+ return CodeRewriterResult.hasChanged(changed);
}
- return false;
+ return CodeRewriterResult.NO_CHANGE;
+ }
+
+ @Override
+ protected boolean verifyConsistentCode(IRCode code, boolean ssa, String preposition) {
+ // Skip verification since this runs prior to the removal of invalid code.
+ return true;
}
private static List<BasicBlock> getRewritingCandidates(
diff --git a/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java b/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
index e8deff4..42c94e5 100644
--- a/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
+++ b/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
@@ -100,7 +100,6 @@
import com.android.tools.r8.ir.code.Xor;
import com.android.tools.r8.ir.conversion.ExtraParameter;
import com.android.tools.r8.ir.conversion.MethodConversionOptions.MutableMethodConversionOptions;
-import com.android.tools.r8.ir.conversion.StringSwitchConverter;
import com.android.tools.r8.lightir.LirBuilder.IntSwitchPayload;
import com.android.tools.r8.lightir.LirBuilder.StringSwitchPayload;
import com.android.tools.r8.lightir.LirCode.PositionEntry;
@@ -146,13 +145,6 @@
IRCode irCode = parser.getIRCode(method, conversionOptions);
// Some instructions have bottom types (e.g., phis). Compute their actual types by widening.
new TypeAnalysis(appView, irCode).widening();
-
- if (conversionOptions.isStringSwitchConversionEnabled()) {
- if (StringSwitchConverter.convertToStringSwitchInstructions(
- irCode, appView.dexItemFactory())) {
- irCode.removeRedundantBlocks();
- }
- }
return irCode;
}
diff --git a/src/main/java/com/android/tools/r8/lightir/LirLensCodeRewriter.java b/src/main/java/com/android/tools/r8/lightir/LirLensCodeRewriter.java
index b2331cc..de48365 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirLensCodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirLensCodeRewriter.java
@@ -366,11 +366,7 @@
@SuppressWarnings("unchecked")
private LirCode<EV> removeUnreachableBlocks(LirCode<EV> rewritten) {
- IRCode code =
- rewritten.buildIR(
- context,
- appView,
- MethodConversionOptions.forLirPhase(appView).disableStringSwitchConversion());
+ IRCode code = rewritten.buildIR(context, appView, MethodConversionOptions.forLirPhase(appView));
AffectedValues affectedValues = code.removeUnreachableBlocks();
affectedValues.narrowingWithAssumeRemoval(appView, code);
new DeadCodeRemover(appView).run(code, Timing.empty());
@@ -386,7 +382,6 @@
context.buildIR(
appView,
MethodConversionOptions.forLirPhase(appView)
- .disableStringSwitchConversion()
.setFinalizeAfterLensCodeRewriter());
// MethodProcessor argument is only used by unboxing lenses.
MethodProcessor methodProcessor = null;
diff --git a/src/main/java/com/android/tools/r8/optimize/singlecaller/SingleCallerInliner.java b/src/main/java/com/android/tools/r8/optimize/singlecaller/SingleCallerInliner.java
index 126960b..10731fb 100644
--- a/src/main/java/com/android/tools/r8/optimize/singlecaller/SingleCallerInliner.java
+++ b/src/main/java/com/android/tools/r8/optimize/singlecaller/SingleCallerInliner.java
@@ -116,10 +116,7 @@
.setApiLevelForCode(
appView.apiLevelCompute().computeInitialMinApiLevel(appView.options()));
}
- IRCode code =
- method.buildIR(
- appView,
- MethodConversionOptions.forLirPhase(appView).disableStringSwitchConversion());
+ IRCode code = method.buildIR(appView, MethodConversionOptions.forLirPhase(appView));
inliner.performInlining(
method, code, getSimpleFeedback(), methodProcessor, Timing.empty());
CodeRewriter.removeAssumeInstructions(appView, code);
diff --git a/src/main/java/com/android/tools/r8/profile/startup/instrumentation/StartupInstrumentation.java b/src/main/java/com/android/tools/r8/profile/startup/instrumentation/StartupInstrumentation.java
index ba3abda..192178b 100644
--- a/src/main/java/com/android/tools/r8/profile/startup/instrumentation/StartupInstrumentation.java
+++ b/src/main/java/com/android/tools/r8/profile/startup/instrumentation/StartupInstrumentation.java
@@ -176,8 +176,7 @@
private void instrumentMethod(ProgramMethod method, boolean skipMethodLogging) {
// Disable StringSwitch conversion to avoid having to run the StringSwitchRemover before
// finalizing the code.
- MutableMethodConversionOptions conversionOptions =
- MethodConversionOptions.forD8(appView).disableStringSwitchConversion();
+ MutableMethodConversionOptions conversionOptions = MethodConversionOptions.forD8(appView);
IRCode code = method.buildIR(appView, conversionOptions);
InstructionListIterator instructionIterator = code.entryBlock().listIterator(code);
instructionIterator.positionBeforeNextInstructionThatMatches(not(Instruction::isArgument));
diff --git a/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java b/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java
index 759ebd7..1eacba7 100644
--- a/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java
+++ b/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java
@@ -266,7 +266,6 @@
mode.isInitialTreeShaking()
? MethodConversionOptions.forPreLirPhase(appView)
: MethodConversionOptions.forLirPhase(appView);
- conversionOptions.disableStringSwitchConversion();
IRCode ir = method.buildIR(appView, conversionOptions);
diff --git a/src/test/java/com/android/tools/r8/ir/regalloc/IdenticalAfterRegisterAllocationTest.java b/src/test/java/com/android/tools/r8/ir/regalloc/IdenticalAfterRegisterAllocationTest.java
index 867f9c9..181c0c5 100644
--- a/src/test/java/com/android/tools/r8/ir/regalloc/IdenticalAfterRegisterAllocationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/regalloc/IdenticalAfterRegisterAllocationTest.java
@@ -151,11 +151,6 @@
}
@Override
- public boolean isStringSwitchConversionEnabled() {
- return false;
- }
-
- @Override
public boolean shouldFinalizeAfterLensCodeRewriter() {
return false;
}