Extend LIR phase past bridge hoisting
Bug: b/225838009
Change-Id: Ie41f1757fd388fc6b63ca6255c469e66054bb663
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 608e3cf..2ebb574 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -584,10 +584,7 @@
shrinker.rewriteDeadBuilderReferencesFromDynamicMethods(
conversionOptions, appViewWithLiveness, executorService, timing));
- if (!options.isShrinking()) {
- // TODO(b/225838009): Support tracing and building LIR in Enqueuer.
- PrimaryR8IRConverter.finalizeLirToOutputFormat(appView, timing, executorService);
- } else {
+ if (options.isShrinking()) {
// Mark dead proto extensions fields as neither being read nor written. This step must
// run prior to the tree pruner.
TreePrunerConfiguration treePrunerConfiguration =
@@ -611,8 +608,6 @@
options.reporter, options.usageInformationConsumer);
}
- // TODO(b/225838009): Support bridge hoisting from LIR code.
- PrimaryR8IRConverter.finalizeLirToOutputFormat(appView, timing, executorService);
new BridgeHoisting(appViewWithLiveness).run(executorService, timing);
assert Inliner.verifyAllSingleCallerMethodsHaveBeenPruned(appViewWithLiveness);
@@ -657,6 +652,9 @@
timing.end();
}
+ // TODO(b/225838009): Support LIR in proto shrinking.
+ PrimaryR8IRConverter.finalizeLirToOutputFormat(appView, timing, executorService);
+
if (appView.options().protoShrinking().isProtoShrinkingEnabled()) {
if (appView.options().protoShrinking().isEnumLiteProtoShrinkingEnabled()) {
appView.protoShrinker().enumLiteProtoShrinker.verifyDeadEnumLiteMapsAreDead();
diff --git a/src/main/java/com/android/tools/r8/lightir/LirCode.java b/src/main/java/com/android/tools/r8/lightir/LirCode.java
index 0fccf4e..b14c481 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirCode.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirCode.java
@@ -31,6 +31,7 @@
import com.android.tools.r8.ir.conversion.MethodConversionOptions;
import com.android.tools.r8.ir.conversion.MethodConversionOptions.MutableMethodConversionOptions;
import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.ArrayUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.RetracerForCodePrinting;
import com.google.common.collect.ImmutableMap;
@@ -39,6 +40,7 @@
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
+import java.util.function.Function;
public class LirCode<EV> extends Code implements Iterable<LirInstructionView> {
@@ -90,7 +92,7 @@
}
public static class TryCatchTable {
- final Int2ReferenceMap<CatchHandlers<Integer>> tryCatchHandlers;
+ private final Int2ReferenceMap<CatchHandlers<Integer>> tryCatchHandlers;
public TryCatchTable(Int2ReferenceMap<CatchHandlers<Integer>> tryCatchHandlers) {
assert !tryCatchHandlers.isEmpty();
@@ -101,6 +103,10 @@
public CatchHandlers<Integer> getHandlersForBlock(int blockIndex) {
return tryCatchHandlers.get(blockIndex);
}
+
+ public void forEachHandler(BiConsumer<Integer, CatchHandlers<Integer>> fn) {
+ tryCatchHandlers.forEach(fn);
+ }
}
public static class DebugLocalInfoTable<EV> {
@@ -451,4 +457,23 @@
positionConsumer.accept(entry.getPosition(method));
}
}
+
+ public LirCode<EV> newCodeWithRewrittenConstantPool(Function<DexItem, DexItem> rewriter) {
+ DexItem[] rewrittenConstants = ArrayUtils.map(constants, rewriter, new DexItem[0]);
+ if (constants == rewrittenConstants) {
+ return this;
+ }
+ return new LirCode<>(
+ irMetadata,
+ rewrittenConstants,
+ positionTable,
+ argumentCount,
+ instructions,
+ instructionCount,
+ tryCatchTable,
+ debugLocalInfoTable,
+ strategyInfo,
+ useDexEstimationStrategy,
+ metadataMap);
+ }
}
diff --git a/src/main/java/com/android/tools/r8/lightir/LirPrinter.java b/src/main/java/com/android/tools/r8/lightir/LirPrinter.java
index cfe1a08..dfbea22 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirPrinter.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirPrinter.java
@@ -90,8 +90,7 @@
if (code.getTryCatchTable() != null) {
builder.append("try-catch-handlers:\n");
code.getTryCatchTable()
- .tryCatchHandlers
- .forEach(
+ .forEachHandler(
(index, handlers) -> {
builder.append(index).append(":\n");
for (CatchHandler<Integer> handler : handlers) {
diff --git a/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoisting.java b/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoisting.java
index ae0133f..4a737f4 100644
--- a/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoisting.java
+++ b/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoisting.java
@@ -29,6 +29,7 @@
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
import com.android.tools.r8.ir.optimize.info.bridge.VirtualBridgeInfo;
+import com.android.tools.r8.lightir.LirCode;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.MethodSignatureEquivalence;
import com.android.tools.r8.utils.Timing;
@@ -326,6 +327,9 @@
private Code createCodeForVirtualBridge(ProgramMethod representative, DexMethod methodToInvoke) {
Code code = representative.getDefinition().getCode();
+ if (code.isLirCode()) {
+ return createLirCodeForVirtualBridge(code.asLirCode(), methodToInvoke);
+ }
if (code.isCfCode()) {
return createCfCodeForVirtualBridge(code.asCfCode(), methodToInvoke);
}
@@ -335,6 +339,18 @@
throw new Unreachable("Unexpected code object of type " + code.getClass().getTypeName());
}
+ private LirCode<Integer> createLirCodeForVirtualBridge(
+ LirCode<Integer> code, DexMethod methodToInvoke) {
+ return code.newCodeWithRewrittenConstantPool(
+ item -> {
+ if (item instanceof DexMethod) {
+ assert methodToInvoke.match((DexMethod) item);
+ return methodToInvoke;
+ }
+ return item;
+ });
+ }
+
private CfCode createCfCodeForVirtualBridge(CfCode code, DexMethod methodToInvoke) {
List<CfInstruction> newInstructions = new ArrayList<>();
boolean modified = false;