Fixed spilling bug (visible on ARM64): missed SIMD type.

Test: test-art-host test-art-target
Change-Id: I6f321446f54943e02f250732ec9da729f633c3a9
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index 1ca0960..3dc1ef7 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -1749,7 +1749,8 @@
 HInstruction* HLoopOptimization::ReduceAndExtractIfNeeded(HInstruction* instruction) {
   if (instruction->IsPhi()) {
     HInstruction* input = instruction->InputAt(1);
-    if (input->IsVecOperation() && !input->IsVecExtractScalar()) {
+    if (HVecOperation::ReturnsSIMDValue(input)) {
+      DCHECK(!input->IsPhi());
       HVecOperation* input_vector = input->AsVecOperation();
       uint32_t vector_length = input_vector->GetVectorLength();
       DataType::Type type = input_vector->GetPackedType();
diff --git a/compiler/optimizing/nodes_vector.h b/compiler/optimizing/nodes_vector.h
index 59d5b9f..096349f 100644
--- a/compiler/optimizing/nodes_vector.h
+++ b/compiler/optimizing/nodes_vector.h
@@ -150,6 +150,19 @@
     }
   }
 
+  // Helper method to determine if an instruction returns a SIMD value.
+  // TODO: This method is needed until we introduce SIMD as proper type.
+  static bool ReturnsSIMDValue(HInstruction* instruction) {
+    if (instruction->IsVecOperation()) {
+      return !instruction->IsVecExtractScalar();  // only scalar returning vec op
+    } else if (instruction->IsPhi()) {
+      return
+          instruction->GetType() == kSIMDType &&
+          instruction->InputAt(1)->IsVecOperation();  // vectorizer does not go deeper
+    }
+    return false;
+  }
+
   DECLARE_ABSTRACT_INSTRUCTION(VecOperation);
 
  protected:
@@ -879,7 +892,7 @@
                       vector_length,
                       dex_pc) {
     for (size_t i = 0; i < number_of_scalars; i++) {
-      DCHECK(!scalars[i]->IsVecOperation() || scalars[i]->IsVecExtractScalar());
+      DCHECK(!ReturnsSIMDValue(scalars[i]));
       SetRawInputAt(0, scalars[i]);
     }
   }
diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc
index 9ab7a89..f6bd052 100644
--- a/compiler/optimizing/ssa_liveness_analysis.cc
+++ b/compiler/optimizing/ssa_liveness_analysis.cc
@@ -474,9 +474,10 @@
   // For a SIMD operation, compute the number of needed spill slots.
   // TODO: do through vector type?
   HInstruction* definition = GetParent()->GetDefinedBy();
-  if (definition != nullptr &&
-      definition->IsVecOperation() &&
-      !definition->IsVecExtractScalar()) {
+  if (definition != nullptr && HVecOperation::ReturnsSIMDValue(definition)) {
+    if (definition->IsPhi()) {
+      definition = definition->InputAt(1);  // SIMD always appears on back-edge
+    }
     return definition->AsVecOperation()->GetVectorNumberOfBytes() / kVRegSize;
   }
   // Return number of needed spill slots based on type.