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.
diff --git a/test/623-checker-loop-regressions/src/Main.java b/test/623-checker-loop-regressions/src/Main.java
index 3ef8fe6..29f3817 100644
--- a/test/623-checker-loop-regressions/src/Main.java
+++ b/test/623-checker-loop-regressions/src/Main.java
@@ -493,6 +493,95 @@
}
}
+ // Avoid bad scheduler-SIMD interaction.
+ static int doNotMoveSIMD() {
+ int sum = 0;
+ for (int j = 0; j <= 8; j++) {
+ int[] a = new int[17]; // a[i] = 0;
+ // ConstructorFence ?
+ for (int i = 0; i < a.length; i++) {
+ a[i] += 1; // a[i] = 1;
+ }
+ for (int i = 0; i < a.length; i++) {
+ sum += a[i]; // expect a[i] = 1;
+ }
+ }
+ return sum;
+ }
+
+ // Ensure spilling saves full SIMD values.
+ private static final int reduction32Values(int[] a, int[] b, int[] c, int[] d) {
+ int s0 = 0;
+ int s1 = 0;
+ int s2 = 0;
+ int s3 = 0;
+ int s4 = 0;
+ int s5 = 0;
+ int s6 = 0;
+ int s7 = 0;
+ int s8 = 0;
+ int s9 = 0;
+ int s10 = 0;
+ int s11 = 0;
+ int s12 = 0;
+ int s13 = 0;
+ int s14 = 0;
+ int s15 = 0;
+ int s16 = 0;
+ int s17 = 0;
+ int s18 = 0;
+ int s19 = 0;
+ int s20 = 0;
+ int s21 = 0;
+ int s22 = 0;
+ int s23 = 0;
+ int s24 = 0;
+ int s25 = 0;
+ int s26 = 0;
+ int s27 = 0;
+ int s28 = 0;
+ int s29 = 0;
+ int s30 = 0;
+ int s31 = 0;
+ for (int i = 1; i < 100; i++) {
+ s0 += a[i];
+ s1 += b[i];
+ s2 += c[i];
+ s3 += d[i];
+ s4 += a[i];
+ s5 += b[i];
+ s6 += c[i];
+ s7 += d[i];
+ s8 += a[i];
+ s9 += b[i];
+ s10 += c[i];
+ s11 += d[i];
+ s12 += a[i];
+ s13 += b[i];
+ s14 += c[i];
+ s15 += d[i];
+ s16 += a[i];
+ s17 += b[i];
+ s18 += c[i];
+ s19 += d[i];
+ s20 += a[i];
+ s21 += b[i];
+ s22 += c[i];
+ s23 += d[i];
+ s24 += a[i];
+ s25 += b[i];
+ s26 += c[i];
+ s27 += d[i];
+ s28 += a[i];
+ s29 += b[i];
+ s30 += c[i];
+ s31 += d[i];
+ }
+ return s0 + s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10 + s11 + s12 + s13 + s14 + s15 +
+ s16 + s17 + s18 + s19 + s20 + s21 + s22 + s23 +
+ s24 + s25 + s26 + s27 + s28 + s29 + s30 + s31;
+ }
+
public static void main(String[] args) {
expectEquals(10, earlyExitFirst(-1));
for (int i = 0; i <= 10; i++) {
@@ -655,6 +744,22 @@
expectEquals((byte)((short) cx[i] + 1), b1[i]);
}
+ expectEquals(153, doNotMoveSIMD());
+
+ {
+ int[] a1 = new int[100];
+ int[] a2 = new int[100];
+ int[] a3 = new int[100];
+ int[] a4 = new int[100];
+ for (int i = 0; i < 100; i++) {
+ a1[i] = i;
+ a2[i] = 1;
+ a3[i] = 100 - i;
+ a4[i] = i % 16;
+ }
+ expectEquals(85800, reduction32Values(a1, a2, a3, a4));
+ }
+
System.out.println("passed");
}