Don't compile OSR methods that have phi equivalents at loop entry.
We currently don't handle this in the stack map, where we only encode
one stack slot for a dex register.
Bug: 136698025
Test: 721-osr
Change-Id: Ib395ed1165387ad5446a463c307cc0a45e365885
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 25f9e3c..09ae6fa 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -131,6 +131,7 @@
kAnalysisFailThrowCatchLoop,
kAnalysisFailAmbiguousArrayOp,
kAnalysisFailIrreducibleLoopAndStringInit,
+ kAnalysisFailPhiEquivalentInOsr,
kAnalysisSuccess,
};
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 6f3b9fe..b1a3abe 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -914,6 +914,11 @@
MethodCompilationStat::kNotCompiledIrreducibleLoopAndStringInit);
break;
}
+ case kAnalysisFailPhiEquivalentInOsr: {
+ MaybeRecordStat(compilation_stats_.get(),
+ MethodCompilationStat::kNotCompiledPhiEquivalentInOsr);
+ break;
+ }
case kAnalysisSuccess:
UNREACHABLE();
}
diff --git a/compiler/optimizing/optimizing_compiler_stats.h b/compiler/optimizing/optimizing_compiler_stats.h
index ddd57f5..83dbef7 100644
--- a/compiler/optimizing/optimizing_compiler_stats.h
+++ b/compiler/optimizing/optimizing_compiler_stats.h
@@ -61,6 +61,7 @@
kNotCompiledVerificationError,
kNotCompiledVerifyAtRuntime,
kNotCompiledIrreducibleLoopAndStringInit,
+ kNotCompiledPhiEquivalentInOsr,
kInlinedMonomorphicCall,
kInlinedPolymorphicCall,
kMonomorphicCall,
diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc
index 0d0e1ec..a5e8ff6 100644
--- a/compiler/optimizing/ssa_builder.cc
+++ b/compiler/optimizing/ssa_builder.cc
@@ -496,6 +496,22 @@
}
}
+static bool HasPhiEquivalentAtLoopEntry(HGraph* graph) {
+ // Phi equivalents for a dex register do not work with OSR, as the phis will
+ // receive two different stack slots but only one is recorded in the stack
+ // map.
+ for (HBasicBlock* block : graph->GetReversePostOrder()) {
+ if (block->IsLoopHeader()) {
+ for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
+ if (it.Current()->AsPhi()->HasEquivalentPhi()) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
GraphAnalysisResult SsaBuilder::BuildSsa() {
DCHECK(!graph_->IsInSsaForm());
@@ -574,6 +590,10 @@
// other optimizations.
RemoveRedundantUninitializedStrings();
+ if (graph_->IsCompilingOsr() && HasPhiEquivalentAtLoopEntry(graph_)) {
+ return kAnalysisFailPhiEquivalentInOsr;
+ }
+
graph_->SetInSsaForm();
return kAnalysisSuccess;
}
diff --git a/test/721-osr/expected.txt b/test/721-osr/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/721-osr/expected.txt
diff --git a/test/721-osr/info.txt b/test/721-osr/info.txt
new file mode 100644
index 0000000..d43357e
--- /dev/null
+++ b/test/721-osr/info.txt
@@ -0,0 +1,3 @@
+Regression test for OSR compilation, which used to not fill the
+right dex register value in the presence of equivalent phis.
+(see b/136698025)
diff --git a/test/721-osr/src/Main.java b/test/721-osr/src/Main.java
new file mode 100644
index 0000000..2f0892c
--- /dev/null
+++ b/test/721-osr/src/Main.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Main {
+ private enum TestType {
+ ONE,
+ TWO
+ }
+
+ private static TestType type = TestType.ONE;
+
+ public static void main(String[] args) {
+ float testFloat;
+ switch (type) {
+ case ONE: testFloat = 1000.0f; break;
+ default: testFloat = 5f; break;
+ }
+
+ // Loop enough to potentially trigger OSR.
+ List<Integer> dummyObjects = new ArrayList<Integer>(200_000);
+ for (int i = 0; i < 200_000; i++) {
+ dummyObjects.add(1024);
+ }
+
+ if (testFloat != 1000.0f) {
+ throw new Error("Expected 1000.0f, got " + testFloat);
+ }
+ }
+}