Allow same-length integral type mixing in SIMD.

Rationale:
Just like the incoming sequential code, the SIMD
code allows for some type matching, as long as
it is integral and same length.

Bug: 37764324
Test: test-art-target, test-art-host
Change-Id: Ide1c5403e0f3b8c5372e8ac6dd282d8211ca8f1b
diff --git a/compiler/optimizing/nodes_vector.h b/compiler/optimizing/nodes_vector.h
index c9d6ff8..52c247b 100644
--- a/compiler/optimizing/nodes_vector.h
+++ b/compiler/optimizing/nodes_vector.h
@@ -192,6 +192,24 @@
   DISALLOW_COPY_AND_ASSIGN(HVecMemoryOperation);
 };
 
+// Packed type consistency checker (same vector length integral types may mix freely).
+inline static bool HasConsistentPackedTypes(HInstruction* input, Primitive::Type type) {
+  DCHECK(input->IsVecOperation());
+  Primitive::Type input_type = input->AsVecOperation()->GetPackedType();
+  switch (input_type) {
+    case Primitive::kPrimBoolean:
+    case Primitive::kPrimByte:
+      return type == Primitive::kPrimBoolean ||
+             type == Primitive::kPrimByte;
+    case Primitive::kPrimChar:
+    case Primitive::kPrimShort:
+      return type == Primitive::kPrimChar ||
+             type == Primitive::kPrimShort;
+    default:
+      return type == input_type;
+  }
+}
+
 //
 // Definitions of concrete unary vector operations in HIR.
 //
@@ -222,8 +240,7 @@
                 size_t vector_length,
                 uint32_t dex_pc = kNoDexPc)
       : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
-    DCHECK(input->IsVecOperation());
-    DCHECK_EQ(input->AsVecOperation()->GetPackedType(), packed_type);
+    DCHECK(HasConsistentPackedTypes(input, packed_type));
   }
 
   // TODO: probably integral promotion
@@ -245,7 +262,7 @@
           uint32_t dex_pc = kNoDexPc)
       : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
     DCHECK(input->IsVecOperation());
-    DCHECK_NE(input->AsVecOperation()->GetPackedType(), packed_type);  // actual convert
+    DCHECK_NE(GetInputType(), GetResultType());  // actual convert
   }
 
   Primitive::Type GetInputType() const { return InputAt(0)->AsVecOperation()->GetPackedType(); }
@@ -267,8 +284,7 @@
           size_t vector_length,
           uint32_t dex_pc = kNoDexPc)
       : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
-    DCHECK(input->IsVecOperation());
-    DCHECK_EQ(input->AsVecOperation()->GetPackedType(), packed_type);
+    DCHECK(HasConsistentPackedTypes(input, packed_type));
   }
   DECLARE_INSTRUCTION(VecNeg);
  private:
@@ -285,8 +301,7 @@
           size_t vector_length,
           uint32_t dex_pc = kNoDexPc)
       : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
-    DCHECK(input->IsVecOperation());
-    DCHECK_EQ(input->AsVecOperation()->GetPackedType(), packed_type);
+    DCHECK(HasConsistentPackedTypes(input, packed_type));
   }
   DECLARE_INSTRUCTION(VecAbs);
  private:
@@ -326,9 +341,8 @@
           size_t vector_length,
           uint32_t dex_pc = kNoDexPc)
       : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
-    DCHECK(left->IsVecOperation() && right->IsVecOperation());
-    DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
-    DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
+    DCHECK(HasConsistentPackedTypes(left, packed_type));
+    DCHECK(HasConsistentPackedTypes(right, packed_type));
   }
   DECLARE_INSTRUCTION(VecAdd);
  private:
@@ -350,9 +364,8 @@
                  bool is_rounded,
                  uint32_t dex_pc = kNoDexPc)
       : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
-    DCHECK(left->IsVecOperation() && right->IsVecOperation());
-    DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
-    DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
+    DCHECK(HasConsistentPackedTypes(left, packed_type));
+    DCHECK(HasConsistentPackedTypes(right, packed_type));
     SetPackedFlag<kFieldHAddIsUnsigned>(is_unsigned);
     SetPackedFlag<kFieldHAddIsRounded>(is_rounded);
   }
@@ -383,9 +396,8 @@
           size_t vector_length,
           uint32_t dex_pc = kNoDexPc)
       : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
-    DCHECK(left->IsVecOperation() && right->IsVecOperation());
-    DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
-    DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
+    DCHECK(HasConsistentPackedTypes(left, packed_type));
+    DCHECK(HasConsistentPackedTypes(right, packed_type));
   }
   DECLARE_INSTRUCTION(VecSub);
  private:
@@ -403,9 +415,8 @@
           size_t vector_length,
           uint32_t dex_pc = kNoDexPc)
       : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
-    DCHECK(left->IsVecOperation() && right->IsVecOperation());
-    DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
-    DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
+    DCHECK(HasConsistentPackedTypes(left, packed_type));
+    DCHECK(HasConsistentPackedTypes(right, packed_type));
   }
   DECLARE_INSTRUCTION(VecMul);
  private:
@@ -423,9 +434,8 @@
           size_t vector_length,
           uint32_t dex_pc = kNoDexPc)
       : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
-    DCHECK(left->IsVecOperation() && right->IsVecOperation());
-    DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
-    DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
+    DCHECK(HasConsistentPackedTypes(left, packed_type));
+    DCHECK(HasConsistentPackedTypes(right, packed_type));
   }
   DECLARE_INSTRUCTION(VecDiv);
  private:
@@ -443,9 +453,8 @@
           size_t vector_length,
           uint32_t dex_pc = kNoDexPc)
       : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
-    DCHECK(left->IsVecOperation() && right->IsVecOperation());
-    DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
-    DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
+    DCHECK(HasConsistentPackedTypes(left, packed_type));
+    DCHECK(HasConsistentPackedTypes(right, packed_type));
   }
   DECLARE_INSTRUCTION(VecMin);
  private:
@@ -463,9 +472,8 @@
           size_t vector_length,
           uint32_t dex_pc = kNoDexPc)
       : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
-    DCHECK(left->IsVecOperation() && right->IsVecOperation());
-    DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
-    DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type);
+    DCHECK(HasConsistentPackedTypes(left, packed_type));
+    DCHECK(HasConsistentPackedTypes(right, packed_type));
   }
   DECLARE_INSTRUCTION(VecMax);
  private:
@@ -555,8 +563,7 @@
           size_t vector_length,
           uint32_t dex_pc = kNoDexPc)
       : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
-    DCHECK(left->IsVecOperation());
-    DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
+    DCHECK(HasConsistentPackedTypes(left, packed_type));
   }
   DECLARE_INSTRUCTION(VecShl);
  private:
@@ -574,8 +581,7 @@
           size_t vector_length,
           uint32_t dex_pc = kNoDexPc)
       : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
-    DCHECK(left->IsVecOperation());
-    DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
+    DCHECK(HasConsistentPackedTypes(left, packed_type));
   }
   DECLARE_INSTRUCTION(VecShr);
  private:
@@ -593,8 +599,7 @@
            size_t vector_length,
            uint32_t dex_pc = kNoDexPc)
       : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) {
-    DCHECK(left->IsVecOperation());
-    DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type);
+    DCHECK(HasConsistentPackedTypes(left, packed_type));
   }
   DECLARE_INSTRUCTION(VecUShr);
  private:
@@ -650,12 +655,9 @@
                       dex_pc),
         op_kind_(op) {
     DCHECK(op == InstructionKind::kAdd || op == InstructionKind::kSub);
-    DCHECK(accumulator->IsVecOperation());
-    DCHECK(mul_left->IsVecOperation() && mul_right->IsVecOperation());
-    DCHECK_EQ(accumulator->AsVecOperation()->GetPackedType(), packed_type);
-    DCHECK_EQ(mul_left->AsVecOperation()->GetPackedType(), packed_type);
-    DCHECK_EQ(mul_right->AsVecOperation()->GetPackedType(), packed_type);
-
+    DCHECK(HasConsistentPackedTypes(accumulator, packed_type));
+    DCHECK(HasConsistentPackedTypes(mul_left, packed_type));
+    DCHECK(HasConsistentPackedTypes(mul_right, packed_type));
     SetRawInputAt(kInputAccumulatorIndex, accumulator);
     SetRawInputAt(kInputMulLeftIndex, mul_left);
     SetRawInputAt(kInputMulRightIndex, mul_right);
@@ -733,8 +735,7 @@
                             /* number_of_inputs */ 3,
                             vector_length,
                             dex_pc) {
-    DCHECK(value->IsVecOperation());
-    DCHECK_EQ(value->AsVecOperation()->GetPackedType(), packed_type);
+    DCHECK(HasConsistentPackedTypes(value, packed_type));
     SetRawInputAt(0, base);
     SetRawInputAt(1, index);
     SetRawInputAt(2, value);
diff --git a/test/623-checker-loop-regressions/src/Main.java b/test/623-checker-loop-regressions/src/Main.java
index 3f4297f..d1f36ed 100644
--- a/test/623-checker-loop-regressions/src/Main.java
+++ b/test/623-checker-loop-regressions/src/Main.java
@@ -320,6 +320,27 @@
     }
   }
 
+  /// CHECK-START: void Main.oneBoth(short[], char[]) loop_optimization (before)
+  /// CHECK-DAG: <<One:i\d+>>  IntConstant 1                       loop:none
+  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<One>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<One>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void Main.oneBoth(short[], char[]) loop_optimization (after)
+  /// CHECK-DAG: <<One:i\d+>>  IntConstant 1                        loop:none
+  /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>]         loop:none
+  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>>      outer_loop:none
+  //
+  // Bug b/37764324: integral same-length packed types can be mixed freely.
+  private static void oneBoth(short[] a, char[] b) {
+    for (int i = 0; i < Math.min(a.length, b.length); i++) {
+      a[i] = 1;
+      b[i] = 1;
+    }
+  }
+
   public static void main(String[] args) {
     expectEquals(10, earlyExitFirst(-1));
     for (int i = 0; i <= 10; i++) {
@@ -408,6 +429,13 @@
 
     envUsesInCond();
 
+    short[] dd = new short[23];
+    oneBoth(dd, aa);
+    for (int i = 0; i < aa.length; i++) {
+      expectEquals(aa[i], 1);
+      expectEquals(dd[i], 1);
+    }
+
     System.out.println("passed");
   }