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);
+        }
+    }
+}