Merge "Exploit NE/EQ tests on array length in BCE."
diff --git a/compiler/optimizing/bounds_check_elimination.cc b/compiler/optimizing/bounds_check_elimination.cc
index b65e98a..6c6e5af 100644
--- a/compiler/optimizing/bounds_check_elimination.cc
+++ b/compiler/optimizing/bounds_check_elimination.cc
@@ -800,6 +800,27 @@
ValueRange(GetGraph()->GetArena(), ValueBound::Min(), new_upper);
ApplyRangeFromComparison(left, block, false_successor, new_range);
}
+ } else if (cond == kCondNE || cond == kCondEQ) {
+ if (left->IsArrayLength() && lower.IsConstant() && upper.IsConstant()) {
+ // Special case:
+ // length == [c,d] yields [c, d] along true
+ // length != [c,d] yields [c, d] along false
+ if (!lower.Equals(ValueBound::Min()) || !upper.Equals(ValueBound::Max())) {
+ ValueRange* new_range = new (GetGraph()->GetArena())
+ ValueRange(GetGraph()->GetArena(), lower, upper);
+ ApplyRangeFromComparison(
+ left, block, cond == kCondEQ ? true_successor : false_successor, new_range);
+ }
+ // In addition:
+ // length == 0 yields [1, max] along false
+ // length != 0 yields [1, max] along true
+ if (lower.GetConstant() == 0 && upper.GetConstant() == 0) {
+ ValueRange* new_range = new (GetGraph()->GetArena())
+ ValueRange(GetGraph()->GetArena(), ValueBound(nullptr, 1), ValueBound::Max());
+ ApplyRangeFromComparison(
+ left, block, cond == kCondEQ ? false_successor : true_successor, new_range);
+ }
+ }
}
}
@@ -955,13 +976,7 @@
void VisitIf(HIf* instruction) OVERRIDE {
if (instruction->InputAt(0)->IsCondition()) {
HCondition* cond = instruction->InputAt(0)->AsCondition();
- IfCondition cmp = cond->GetCondition();
- if (cmp == kCondGT || cmp == kCondGE ||
- cmp == kCondLT || cmp == kCondLE) {
- HInstruction* left = cond->GetLeft();
- HInstruction* right = cond->GetRight();
- HandleIf(instruction, left, right, cmp);
- }
+ HandleIf(instruction, cond->GetLeft(), cond->GetRight(), cond->GetCondition());
}
}
diff --git a/test/449-checker-bce/src/Main.java b/test/449-checker-bce/src/Main.java
index 66e1d92..41771b5 100644
--- a/test/449-checker-bce/src/Main.java
+++ b/test/449-checker-bce/src/Main.java
@@ -927,6 +927,32 @@
}
}
+ /// CHECK-START: void Main.nonzeroLength(int[]) BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.nonzeroLength(int[]) BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK-NOT: Deoptimize
+ public static void nonzeroLength(int[] a) {
+ if (a.length != 0) {
+ a[0] = 112;
+ }
+ }
+
+ /// CHECK-START: void Main.knownLength(int[]) BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.knownLength(int[]) BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK-NOT: Deoptimize
+ public static void knownLength(int[] a) {
+ if (a.length == 2) {
+ a[0] = -1;
+ a[1] = -2;
+ }
+ }
+
static int[][] mA;
/// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (before)
@@ -1586,6 +1612,26 @@
}
}
+ nonzeroLength(array);
+ if (array[0] != 112) {
+ System.out.println("nonzero length failed!");
+ }
+
+ knownLength(array);
+ if (array[0] != 112 || array[1] != 1) {
+ System.out.println("nonzero length failed!");
+ }
+ array = new int[2];
+ knownLength(array);
+ if (array[0] != -1 || array[1] != -2) {
+ System.out.println("nonzero length failed!");
+ }
+
+ // Zero length array does not break.
+ array = new int[0];
+ nonzeroLength(array);
+ knownLength(array);
+
mA = new int[4][4];
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
diff --git a/test/530-checker-loops2/src/Main.java b/test/530-checker-loops2/src/Main.java
index c644692..b12fbd6 100644
--- a/test/530-checker-loops2/src/Main.java
+++ b/test/530-checker-loops2/src/Main.java
@@ -710,8 +710,8 @@
// making them a candidate for deoptimization based on constant indices.
// Compiler should ensure the array loads are not subsequently hoisted
// "above" the deoptimization "barrier" on the bounds.
- a[0][i] = 1;
- a[1][i] = 2;
+ a[1][i] = 1;
+ a[2][i] = 2;
a[99][i] = 3;
}
}
@@ -1042,11 +1042,11 @@
a = new int[100][10];
expectEquals(55, dynamicBCEAndConstantIndices(x, a, 0, 10));
for (int i = 0; i < 10; i++) {
- expectEquals((i % 10) != 0 ? 1 : 0, a[0][i]);
- expectEquals((i % 10) != 0 ? 2 : 0, a[1][i]);
+ expectEquals((i % 10) != 0 ? 1 : 0, a[1][i]);
+ expectEquals((i % 10) != 0 ? 2 : 0, a[2][i]);
expectEquals((i % 10) != 0 ? 3 : 0, a[99][i]);
}
- a = new int[2][10];
+ a = new int[3][10];
sResult = 0;
try {
expectEquals(55, dynamicBCEAndConstantIndices(x, a, 0, 10));
@@ -1054,8 +1054,8 @@
sResult = 1;
}
expectEquals(1, sResult);
- expectEquals(a[0][1], 1);
- expectEquals(a[1][1], 2);
+ expectEquals(a[1][1], 1);
+ expectEquals(a[2][1], 2);
// Dynamic BCE combined with constant indices of all types.
boolean[] x1 = { true };