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