Rename merged exception classes in DeadCodeRemover
This CL renames the guards in catch handlers in the DeadCodeRemover, and removes catch handlers that are clearly not needed after renaming.
Example:
try { ... }
catch (ExceptionB e) { ... }
catch (ExceptionA e) {
// If ExceptionA gets merged into ExceptionB, then this handler is clearly dead
...
}
Bug: 73958515
Change-Id: I85613f28ee45fe1f6edad2644252fb3ba14a747a
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 5f0fb83..831edbe 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -264,10 +264,9 @@
public void setCode(
IRCode ir,
- GraphLense graphLense,
RegisterAllocator registerAllocator,
InternalOptions options) {
- final DexBuilder builder = new DexBuilder(ir, graphLense, registerAllocator, options);
+ final DexBuilder builder = new DexBuilder(ir, registerAllocator, options);
code = builder.build(method.getArity());
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
index 113d522..eb11aac 100644
--- a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
+++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
@@ -9,7 +9,9 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DebugLocalInfo.PrintLevel;
+import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.utils.CfgPrinter;
@@ -20,10 +22,13 @@
import com.google.common.base.Equivalence.Wrapper;
import com.google.common.collect.ImmutableList;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
+import it.unimi.dsi.fastutil.ints.IntArrayList;
+import it.unimi.dsi.fastutil.ints.IntList;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
@@ -173,7 +178,7 @@
public void removeSuccessor(BasicBlock block) {
int index = successors.indexOf(block);
assert index >= 0 : "removeSuccessor did not find the successor to remove";
- removeSuccessorsByIndex(Collections.singletonList(index));
+ removeSuccessorsByIndex(new IntArrayList(new int[] {index}));
}
public void removePredecessor(BasicBlock block) {
@@ -328,7 +333,7 @@
assert false : "replaceSuccessor did not find the predecessor to replace";
}
- public void removeSuccessorsByIndex(List<Integer> successorsToRemove) {
+ public void removeSuccessorsByIndex(IntList successorsToRemove) {
if (successorsToRemove.isEmpty()) {
return;
}
@@ -678,6 +683,47 @@
catchHandlers = new CatchHandlers<>(guards, successorIndexes);
}
+ // Due to class merging, it is possible that two exception classes have been merged into one.
+ // This function renames the guards according to the given graph lense.
+ public void renameGuardsInCatchHandlers(GraphLense graphLense) {
+ assert hasCatchHandlers();
+ List<DexType> newGuards = new ArrayList<>(catchHandlers.getGuards().size());
+ for (DexType guard : catchHandlers.getGuards()) {
+ // The type may have changed due to class merging.
+ // TODO(christofferqa): This assumes that the graph lense is context insensitive for the
+ // given type (which is always the case). Consider removing the context-argument from
+ // GraphLense.lookupType, since we do not currently have a use case for it.
+ newGuards.add(graphLense.lookupType(guard, null));
+ }
+ this.catchHandlers = new CatchHandlers<>(newGuards, catchHandlers.getAllTargets());
+ }
+
+ public boolean consistentCatchHandlers() {
+ // Check that catch handlers are always the first successors of a block.
+ if (hasCatchHandlers()) {
+ assert exit().isGoto() || exit().isThrow();
+ CatchHandlers<Integer> catchHandlers = getCatchHandlersWithSuccessorIndexes();
+ // If there is a catch-all guard it must be the last.
+ List<DexType> guards = catchHandlers.getGuards();
+ int lastGuardIndex = guards.size() - 1;
+ for (int i = 0; i < guards.size(); i++) {
+ assert guards.get(i) != DexItemFactory.catchAllType || i == lastGuardIndex;
+ }
+ // Check that all successors except maybe the last are catch successors.
+ List<Integer> sortedHandlerIndices = new ArrayList<>(catchHandlers.getAllTargets());
+ sortedHandlerIndices.sort(Comparator.naturalOrder());
+ int firstIndex = sortedHandlerIndices.get(0);
+ int lastIndex = sortedHandlerIndices.get(sortedHandlerIndices.size() - 1);
+ assert firstIndex == 0;
+ assert lastIndex < sortedHandlerIndices.size();
+ int lastSuccessorIndex = getSuccessors().size() - 1;
+ assert lastIndex == lastSuccessorIndex // All successors are catch successors.
+ || lastIndex == lastSuccessorIndex - 1; // All but one successors are catch successors.
+ assert lastIndex == lastSuccessorIndex || !exit().isThrow();
+ }
+ return true;
+ }
+
public void clearCurrentDefinitions() {
currentDefinitions = null;
for (Phi phi : getPhis()) {
diff --git a/src/main/java/com/android/tools/r8/ir/code/IRCode.java b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
index a5d3e4a..c832991 100644
--- a/src/main/java/com/android/tools/r8/ir/code/IRCode.java
+++ b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
@@ -5,8 +5,6 @@
import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.utils.CfgPrinter;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableList;
@@ -473,28 +471,7 @@
private boolean consistentCatchHandlers() {
for (BasicBlock block : blocks) {
- // Check that catch handlers are always the first successors of a block.
- if (block.hasCatchHandlers()) {
- assert block.exit().isGoto() || block.exit().isThrow();
- CatchHandlers<Integer> catchHandlers = block.getCatchHandlersWithSuccessorIndexes();
- // If there is a catch-all guard it must be the last.
- List<DexType> guards = catchHandlers.getGuards();
- int lastGuardIndex = guards.size() - 1;
- for (int i = 0; i < guards.size(); i++) {
- assert guards.get(i) != DexItemFactory.catchAllType || i == lastGuardIndex;
- }
- // Check that all successors except maybe the last are catch successors.
- List<Integer> sortedHandlerIndices = new ArrayList<>(catchHandlers.getAllTargets());
- sortedHandlerIndices.sort(Comparator.naturalOrder());
- int firstIndex = sortedHandlerIndices.get(0);
- int lastIndex = sortedHandlerIndices.get(sortedHandlerIndices.size() - 1);
- assert firstIndex == 0;
- assert lastIndex < sortedHandlerIndices.size();
- int lastSuccessorIndex = block.getSuccessors().size() - 1;
- assert lastIndex == lastSuccessorIndex // All successors are catch successors.
- || lastIndex == lastSuccessorIndex - 1; // All but one successors are catch successors.
- assert lastIndex == lastSuccessorIndex || !block.exit().isThrow();
- }
+ assert block.consistentCatchHandlers();
}
return true;
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
index e798fd2..de86cb4 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
@@ -22,6 +22,7 @@
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.ir.code.Argument;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.CatchHandlers;
@@ -118,13 +119,16 @@
}
public CfCode build(
- CodeRewriter rewriter, InternalOptions options, AppInfoWithSubtyping appInfo) {
+ CodeRewriter rewriter,
+ GraphLense graphLense,
+ InternalOptions options,
+ AppInfoWithSubtyping appInfo) {
computeInitializers();
types = new TypeVerificationHelper(code, factory, appInfo).computeVerificationTypes();
splitExceptionalBlocks();
LoadStoreHelper loadStoreHelper = new LoadStoreHelper(code, types);
loadStoreHelper.insertLoadsAndStores();
- DeadCodeRemover.removeDeadCode(code, rewriter, options);
+ DeadCodeRemover.removeDeadCode(code, rewriter, graphLense, options);
removeUnneededLoadsAndStores();
registerAllocator = new CfRegisterAllocator(code, options);
registerAllocator.allocateRegisters();
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
index ee7df48..8201562 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
@@ -43,7 +43,6 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.ir.code.Argument;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.CatchHandlers;
@@ -82,10 +81,6 @@
// The IR representation of the code to build.
private final IRCode ir;
- // Graph lense for building the exception handlers. Needed since program classes that inherit
- // from Throwable may get merged into their subtypes during class merging.
- private final GraphLense graphLense;
-
// The register allocator providing register assignments for the code to build.
private final RegisterAllocator registerAllocator;
@@ -121,14 +116,11 @@
public DexBuilder(
IRCode ir,
- GraphLense graphLense,
RegisterAllocator registerAllocator,
InternalOptions options) {
assert ir != null;
- assert graphLense != null;
assert registerAllocator != null;
this.ir = ir;
- this.graphLense = graphLense;
this.registerAllocator = registerAllocator;
this.options = options;
}
@@ -714,12 +706,7 @@
assert i == handlerGroup.getGuards().size() - 1;
catchAllOffset = targetOffset;
} else {
- // The type may have changed due to class merging.
- // TODO(christofferqa): This assumes that the graph lense is context insensitive for the
- // given type (which is always the case). Consider removing the context-argument from
- // GraphLense.lookupType, since we do not currently have a use case for it.
- DexType actualType = graphLense.lookupType(type, null);
- pairs.add(new TypeAddrPair(actualType, targetOffset));
+ pairs.add(new TypeAddrPair(type, targetOffset));
}
}
TypeAddrPair[] pairsArray = pairs.toArray(new TypeAddrPair[pairs.size()]);
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 df4e69c..a52637f 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
@@ -482,7 +482,7 @@
// StringBuilder/StringBuffer method invocations, and removeDeadCode() to remove
// unused out-values.
codeRewriter.rewriteMoveResult(code);
- DeadCodeRemover.removeDeadCode(code, codeRewriter, options);
+ DeadCodeRemover.removeDeadCode(code, codeRewriter, graphLense, options);
consumer.accept(code, method);
return null;
}));
@@ -532,7 +532,7 @@
assert code.isConsistentSSA();
code.traceBlocks();
RegisterAllocator registerAllocator = performRegisterAllocation(code, method);
- method.setCode(code, graphLense, registerAllocator, options);
+ method.setCode(code, registerAllocator, options);
if (Log.ENABLED) {
Log.debug(getClass(), "Resulting dex code for %s:\n%s",
method.toSourceString(), logCode(options, method));
@@ -705,7 +705,7 @@
// Dead code removal. Performed after simplifications to remove code that becomes dead
// as a result of those simplifications. The following optimizations could reveal more
// dead code which is removed right before register allocation in performRegisterAllocation.
- DeadCodeRemover.removeDeadCode(code, codeRewriter, options);
+ DeadCodeRemover.removeDeadCode(code, codeRewriter, graphLense, options);
assert code.isConsistentSSA();
if (options.enableDesugaring && enableTryWithResourcesDesugaring()) {
@@ -776,7 +776,7 @@
private void finalizeToCf(DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
assert !method.getCode().isDexCode();
CfBuilder builder = new CfBuilder(method, code, options.itemFactory);
- CfCode result = builder.build(codeRewriter, options, appInfo.withSubtyping());
+ CfCode result = builder.build(codeRewriter, graphLense, options, appInfo.withSubtyping());
method.setCode(result);
markProcessed(method, code, feedback);
}
@@ -784,7 +784,7 @@
private void finalizeToDex(DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
// Perform register allocation.
RegisterAllocator registerAllocator = performRegisterAllocation(code, method);
- method.setCode(code, graphLense, registerAllocator, options);
+ method.setCode(code, registerAllocator, options);
updateHighestSortingStrings(method);
if (Log.ENABLED) {
Log.debug(getClass(), "Resulting dex code for %s:\n%s",
@@ -818,7 +818,7 @@
private RegisterAllocator performRegisterAllocation(IRCode code, DexEncodedMethod method) {
// Always perform dead code elimination before register allocation. The register allocator
// does not allow dead code (to make sure that we do not waste registers for unneeded values).
- DeadCodeRemover.removeDeadCode(code, codeRewriter, options);
+ DeadCodeRemover.removeDeadCode(code, codeRewriter, graphLense, options);
materializeInstructionBeforeLongOperationsWorkaround(code, options);
LinearScanRegisterAllocator registerAllocator = new LinearScanRegisterAllocator(code, options);
registerAllocator.allocateRegisters(options.debug);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
index 531989e..83844c6 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
@@ -3,6 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.optimize;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.CatchHandlers;
import com.android.tools.r8.ir.code.IRCode;
@@ -11,15 +13,19 @@
import com.android.tools.r8.ir.code.Phi;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.utils.InternalOptions;
+import java.util.ArrayList;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
+import java.util.List;
import java.util.Queue;
+import java.util.Set;
public class DeadCodeRemover {
public static void removeDeadCode(
- IRCode code, CodeRewriter codeRewriter, InternalOptions options) {
- removeUnneededCatchHandlers(code);
+ IRCode code, CodeRewriter codeRewriter, GraphLense graphLense, InternalOptions options) {
+ removeUnneededCatchHandlers(code, graphLense, options);
Queue<BasicBlock> worklist = new LinkedList<>();
worklist.addAll(code.blocks);
for (BasicBlock block = worklist.poll(); block != null; block = worklist.poll()) {
@@ -98,15 +104,52 @@
}
}
- private static void removeUnneededCatchHandlers(IRCode code) {
+ private static void removeUnneededCatchHandlers(
+ IRCode code, GraphLense graphLense, InternalOptions options) {
for (BasicBlock block : code.blocks) {
- if (block.hasCatchHandlers() && !block.canThrow()) {
- CatchHandlers<BasicBlock> handlers = block.getCatchHandlers();
- for (BasicBlock target : handlers.getUniqueTargets()) {
- target.unlinkCatchHandler();
+ if (block.hasCatchHandlers()) {
+ if (block.canThrow()) {
+ if (options.enableClassMerging) {
+ // Handle the case where an exception class has been merged into its sub class.
+ block.renameGuardsInCatchHandlers(graphLense);
+ unlinkDeadCatchHandlers(block, graphLense);
+ }
+ } else {
+ CatchHandlers<BasicBlock> handlers = block.getCatchHandlers();
+ for (BasicBlock target : handlers.getUniqueTargets()) {
+ target.unlinkCatchHandler();
+ }
}
}
}
code.removeUnreachableBlocks();
}
+
+ // Due to class merging, it is possible that two exception classes have been merged into one. This
+ // function removes catch handlers where the guards ended up being the same as a previous one.
+ private static void unlinkDeadCatchHandlers(BasicBlock block, GraphLense graphLense) {
+ assert block.hasCatchHandlers();
+ CatchHandlers<BasicBlock> catchHandlers = block.getCatchHandlers();
+ List<DexType> guards = catchHandlers.getGuards();
+ List<BasicBlock> targets = catchHandlers.getAllTargets();
+
+ Set<DexType> previouslySeenGuards = new HashSet<>();
+ List<BasicBlock> deadCatchHandlers = new ArrayList<>();
+ for (int i = 0; i < guards.size(); i++) {
+ // The type may have changed due to class merging.
+ // TODO(christofferqa): This assumes that the graph lense is context insensitive for the
+ // given type (which is always the case). Consider removing the context-argument from
+ // GraphLense.lookupType, since we do not currently have a use case for it.
+ DexType guard = graphLense.lookupType(guards.get(i), null);
+ boolean guardSeenBefore = !previouslySeenGuards.add(guard);
+ if (guardSeenBefore) {
+ deadCatchHandlers.add(targets.get(i));
+ }
+ }
+ // Remove the guards that are guaranteed to be dead.
+ for (BasicBlock deadCatchHandler : deadCatchHandlers) {
+ deadCatchHandler.unlinkCatchHandler();
+ }
+ assert block.consistentCatchHandlers();
+ }
}
diff --git a/src/test/examples/classmerging/ExceptionTest.java b/src/test/examples/classmerging/ExceptionTest.java
index b365b2a..28442f3 100644
--- a/src/test/examples/classmerging/ExceptionTest.java
+++ b/src/test/examples/classmerging/ExceptionTest.java
@@ -8,12 +8,27 @@
public static void main(String[] args) {
// The following will lead to a catch handler for ExceptionA, which is merged into ExceptionB.
try {
- throw new ExceptionB("Ouch!");
+ doSomethingThatMightThrowExceptionB();
+ doSomethingThatMightThrowException2();
+ } catch (ExceptionB exception) {
+ System.out.println("Caught exception: " + exception.getMessage());
} catch (ExceptionA exception) {
System.out.println("Caught exception: " + exception.getMessage());
+ } catch (Exception2 exception) {
+ System.out.println("Caught exception: " + exception.getMessage());
+ } catch (Exception1 exception) {
+ System.out.println("Caught exception: " + exception.getMessage());
}
}
+ private static void doSomethingThatMightThrowExceptionB() throws ExceptionB {
+ throw new ExceptionB("Ouch!");
+ }
+
+ private static void doSomethingThatMightThrowException2() throws Exception2 {
+ throw new Exception2("Ouch!");
+ }
+
// Will be merged into ExceptionB when class merging is enabled.
public static class ExceptionA extends Exception {
public ExceptionA(String message) {
@@ -26,4 +41,16 @@
super(message);
}
}
+
+ public static class Exception1 extends Exception {
+ public Exception1(String message) {
+ super(message);
+ }
+ }
+
+ public static class Exception2 extends Exception1 {
+ public Exception2(String message) {
+ super(message);
+ }
+ }
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
index 69f925c..d2643cb 100644
--- a/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
@@ -3,8 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.classmerging;
+import static com.android.tools.r8.utils.DexInspectorMatchers.isPresent;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.CompilationFailedException;
@@ -12,9 +14,14 @@
import com.android.tools.r8.R8Command;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.code.Instruction;
+import com.android.tools.r8.code.MoveException;
+import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.DexInspector;
+import com.android.tools.r8.utils.DexInspector.ClassSubject;
import com.android.tools.r8.utils.DexInspector.FoundClassSubject;
+import com.android.tools.r8.utils.DexInspector.MethodSubject;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -110,14 +117,36 @@
new Path[] {
CF_DIR.resolve("ExceptionTest.class"),
CF_DIR.resolve("ExceptionTest$ExceptionA.class"),
- CF_DIR.resolve("ExceptionTest$ExceptionB.class")
+ CF_DIR.resolve("ExceptionTest$ExceptionB.class"),
+ CF_DIR.resolve("ExceptionTest$Exception1.class"),
+ CF_DIR.resolve("ExceptionTest$Exception2.class")
};
Set<String> preservedClassNames =
- ImmutableSet.of("classmerging.ExceptionTest", "classmerging.ExceptionTest$ExceptionB");
- runTest(main, programFiles, preservedClassNames);
+ ImmutableSet.of(
+ "classmerging.ExceptionTest",
+ "classmerging.ExceptionTest$ExceptionB",
+ "classmerging.ExceptionTest$Exception2");
+ DexInspector inspector = runTest(main, programFiles, preservedClassNames);
+
+ ClassSubject mainClass = inspector.clazz(main);
+ assertThat(mainClass, isPresent());
+
+ MethodSubject mainMethod =
+ mainClass.method("void", "main", ImmutableList.of("java.lang.String[]"));
+ assertThat(mainMethod, isPresent());
+
+ // Check that the second catch handler has been removed.
+ DexCode code = mainMethod.getMethod().getCode().asDexCode();
+ int numberOfMoveExceptionInstructions = 0;
+ for (Instruction instruction : code.instructions) {
+ if (instruction instanceof MoveException) {
+ numberOfMoveExceptionInstructions++;
+ }
+ }
+ assertEquals(2, numberOfMoveExceptionInstructions);
}
- private void runTest(String main, Path[] programFiles, Set<String> preservedClassNames)
+ private DexInspector runTest(String main, Path[] programFiles, Set<String> preservedClassNames)
throws Exception {
AndroidApp input = readProgramFiles(programFiles);
AndroidApp output = compileWithR8(input, EXAMPLE_KEEP, this::configure);
@@ -135,5 +164,6 @@
}
// Check that the R8-generated code produces the same result as D8-generated code.
assertEquals(runOnArt(compileWithD8(input), main), runOnArt(output, main));
+ return inspector;
}
}
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
index d6e3612..4214a67 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
@@ -38,7 +38,6 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.DirectMappedDexApplication;
-import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.ir.code.CatchHandlers;
@@ -653,7 +652,7 @@
code);
IRCode ir = code.buildIR(method, null, options, Origin.unknown());
RegisterAllocator allocator = new LinearScanRegisterAllocator(ir, options);
- method.setCode(ir, GraphLense.getIdentityLense(), allocator, options);
+ method.setCode(ir, allocator, options);
directMethods[i] = method;
}
builder.addProgramClass(