Fix a bug in type propagation.

If a phi requests its inputs to be of a certain type, the inputs need
to propagate that type to their users, as those users might be
phis.

Bug report and test courtesy of Serguei I Katkov.

Change-Id: I79baac271566ec4fa684c1edf11a1b3383d896a9
diff --git a/compiler/optimizing/primitive_type_propagation.cc b/compiler/optimizing/primitive_type_propagation.cc
index c20c8a1..af93438 100644
--- a/compiler/optimizing/primitive_type_propagation.cc
+++ b/compiler/optimizing/primitive_type_propagation.cc
@@ -65,6 +65,10 @@
         if (equivalent->IsPhi()) {
           equivalent->AsPhi()->SetLive();
           AddToWorklist(equivalent->AsPhi());
+        } else if (equivalent == input) {
+          // The input has changed its type. It can be an input of other phis,
+          // so we need to put phi users in the work list.
+          AddDependentInstructionsToWorklist(equivalent);
         }
       }
     }
@@ -117,10 +121,10 @@
   worklist_.Add(instruction);
 }
 
-void PrimitiveTypePropagation::AddDependentInstructionsToWorklist(HPhi* instruction) {
+void PrimitiveTypePropagation::AddDependentInstructionsToWorklist(HInstruction* instruction) {
   for (HUseIterator<HInstruction*> it(instruction->GetUses()); !it.Done(); it.Advance()) {
     HPhi* phi = it.Current()->GetUser()->AsPhi();
-    if (phi != nullptr && phi->IsLive()) {
+    if (phi != nullptr && phi->IsLive() && phi->GetType() != instruction->GetType()) {
       AddToWorklist(phi);
     }
   }
diff --git a/compiler/optimizing/primitive_type_propagation.h b/compiler/optimizing/primitive_type_propagation.h
index 1374cbb..6d370ed 100644
--- a/compiler/optimizing/primitive_type_propagation.h
+++ b/compiler/optimizing/primitive_type_propagation.h
@@ -33,7 +33,7 @@
   void VisitBasicBlock(HBasicBlock* block);
   void ProcessWorklist();
   void AddToWorklist(HPhi* phi);
-  void AddDependentInstructionsToWorklist(HPhi* phi);
+  void AddDependentInstructionsToWorklist(HInstruction* instruction);
   bool UpdateType(HPhi* phi);
 
   HGraph* const graph_;
diff --git a/test/472-type-propagation/expected.txt b/test/472-type-propagation/expected.txt
new file mode 100644
index 0000000..0b29bb1
--- /dev/null
+++ b/test/472-type-propagation/expected.txt
@@ -0,0 +1,2 @@
+4.3
+1.2
diff --git a/test/472-type-propagation/info.txt b/test/472-type-propagation/info.txt
new file mode 100644
index 0000000..b86e5a2
--- /dev/null
+++ b/test/472-type-propagation/info.txt
@@ -0,0 +1,3 @@
+Regression test for optimizing's type propagation:
+If a phi requests its inputs to be of a certain type, the inputs need
+to propagate that type to their users, as those users might be phis.
diff --git a/test/472-type-propagation/src/Main.java b/test/472-type-propagation/src/Main.java
new file mode 100644
index 0000000..f9e302f
--- /dev/null
+++ b/test/472-type-propagation/src/Main.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+class Main {
+  public static void main(String[] args) {
+    ssaBuilderDouble(new double[] { 1.2, 4.3, 5.2 });
+    ssaBuilderDouble(new double[] { 1.2, 4.3, 5.2, 6.8 });
+  }
+
+  public static void ssaBuilderDouble(double[] array) {
+    double x;
+    if (array.length > 3) {
+      x = array[0];
+    } else {
+      x = array[1];
+    }
+    array[2] = x;
+    System.out.println(x);
+  }
+}