Check for compare when shorting live ranges for instance-get
Bug: b/251015885
Change-Id: Ia914ba6c4cc1e54686299cc2ce50bb06d1ee2718
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 4d31397..6099074 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
@@ -1980,8 +1980,13 @@
Map<BasicBlock, LinkedHashMap<Value, Instruction>> addConstantInBlock,
Predicate<Instruction> selector) {
InstructionListIterator iterator = block.listIterator(code);
+ boolean seenCompareExit = false;
while (iterator.hasNext()) {
Instruction instruction = iterator.next();
+ if (options.canHaveCmpIfFloatBug() && instruction.isCmp()) {
+ seenCompareExit = true;
+ }
+
if (instruction.hasUnusedOutValue() || instruction.outValue().hasLocalInfo()) {
continue;
}
@@ -2008,6 +2013,7 @@
Instruction uniqueUse = instruction.outValue().singleUniqueUser();
Instruction next = iterator.next();
if (uniqueUse == next) {
+ iterator.previous();
continue;
}
if (next.hasOutValue()
@@ -2017,6 +2023,7 @@
Instruction nextNext = iterator.peekNext();
Instruction uniqueUseNext = next.outValue().singleUniqueUser();
if (uniqueUse == nextNext && uniqueUseNext == nextNext) {
+ iterator.previous();
continue;
}
}
@@ -2053,6 +2060,14 @@
}
}
+ // If the dominator block has a potential compare exit we will chose that as the insertion
+ // point. Uniquely for instructions having invalues this can be before the definition of them.
+ // Bail-out when this is the case. See b/251015885 for more information.
+ if (seenCompareExit
+ && Iterables.any(instruction.inValues(), x -> x.getBlock() == dominator)) {
+ continue;
+ }
+
Instruction copy;
switch (instruction.opcode()) {
case CONST_CLASS:
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/canonicalization/InstanceGetOnCheckCastCompareLongTest.java b/src/test/java/com/android/tools/r8/ir/optimize/canonicalization/InstanceGetOnCheckCastCompareLongTest.java
index c2721f1..f94bba3 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/canonicalization/InstanceGetOnCheckCastCompareLongTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/canonicalization/InstanceGetOnCheckCastCompareLongTest.java
@@ -4,16 +4,10 @@
package com.android.tools.r8.ir.optimize.canonicalization;
-import static org.hamcrest.CoreMatchers.containsString;
-import static org.junit.Assert.assertThrows;
-
-import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.NeverInline;
-import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.utils.AndroidApiLevel;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -49,29 +43,15 @@
// For R8 we will try to shorten the live range and we have a bailout to find an insertion
// point if we see a cmp instruction and the api is lower than 23. The receiver of the instance
// get is not defined on the insertion point which is why this regression test was made.
- R8FullTestBuilder r8FullTestBuilder =
- testForR8(parameters.getBackend())
- .addProgramClasses(I.class, Main.class)
- .addProgramClassFileData(getTestClassWithRewrittenLongCompareToLCmp())
- .addKeepMainRule(Main.class)
- .addKeepClassRules(I.class)
- .setMinApi(parameters.getApiLevel())
- .enableInliningAnnotations();
- if (parameters.getApiLevel().isLessThan(AndroidApiLevel.M)) {
- // TODO(b/251015885). We should not fail compilation.
- assertThrows(
- CompilationFailedException.class,
- () ->
- r8FullTestBuilder.compileWithExpectedDiagnostics(
- diagnostics ->
- diagnostics.assertErrorMessageThatMatches(
- containsString("Unexpected values live at entry to first block"))));
-
- } else {
- r8FullTestBuilder
- .run(parameters.getRuntime(), Main.class)
- .assertSuccessWithOutputLines(EXPECTED);
- }
+ testForR8(parameters.getBackend())
+ .addProgramClasses(I.class, Main.class)
+ .addProgramClassFileData(getTestClassWithRewrittenLongCompareToLCmp())
+ .addKeepMainRule(Main.class)
+ .addKeepClassRules(I.class)
+ .setMinApi(parameters.getApiLevel())
+ .enableInliningAnnotations()
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(EXPECTED);
}
private byte[] getTestClassWithRewrittenLongCompareToLCmp() throws Exception {