BCE: don't assume a bounds check always gets a HArrayLength.
Deoptimizations may change it to a HPhi.
bug:22056703
Change-Id: I8995209438764dac496ed856782b147ba21f93e5
diff --git a/compiler/optimizing/bounds_check_elimination.cc b/compiler/optimizing/bounds_check_elimination.cc
index 900dabe..7fe9fb2 100644
--- a/compiler/optimizing/bounds_check_elimination.cc
+++ b/compiler/optimizing/bounds_check_elimination.cc
@@ -1388,7 +1388,7 @@
if (array_length->IsPhi()) {
// Input 1 of the phi contains the real array.length once the loop body is
// entered. That value will be used for bound analysis. The graph is still
- // strickly in SSA form.
+ // strictly in SSA form.
array_length = array_length->AsPhi()->InputAt(1)->AsArrayLength();
}
@@ -1780,7 +1780,13 @@
it != first_constant_index_bounds_check_map_.end();
++it) {
HBoundsCheck* bounds_check = it->second;
- HArrayLength* array_length = bounds_check->InputAt(1)->AsArrayLength();
+ HInstruction* array_length = bounds_check->InputAt(1);
+ if (!array_length->IsArrayLength()) {
+ // Prior deoptimizations may have changed the array length to a phi.
+ // TODO(mingyao): propagate the range to the phi?
+ DCHECK(array_length->IsPhi()) << array_length->DebugName();
+ continue;
+ }
HIntConstant* lower_bound_const_instr = nullptr;
int32_t lower_bound_const = INT_MIN;
size_t counter = 0;
diff --git a/test/499-bce-phi-array-length/src/Main.java b/test/499-bce-phi-array-length/src/Main.java
index c8c84a1..e917bc1 100644
--- a/test/499-bce-phi-array-length/src/Main.java
+++ b/test/499-bce-phi-array-length/src/Main.java
@@ -32,11 +32,33 @@
return result;
}
+ public static int bar(int start, int[] array) {
+ int result = 0;
+ for (int i = start; i < 3; i++) {
+ result += array[i];
+ for (int j = 0; j < 2; ++j) {
+ result += array[j];
+ // The following operations would lead to BCE wanting to add another
+ // deoptimization, but it crashed assuming the input of a `HBoundsCheck`
+ // must be a `HArrayLength`.
+ result += array[0];
+ result += array[1];
+ result += array[2];
+ }
+ }
+ return result;
+ }
+
public static void main(String[] args) {
int[] a = new int[] { 1, 2, 3, 4, 5 };
int result = foo(1, a);
if (result != 11) {
throw new Error("Got " + result + ", expected " + 11);
}
+
+ result = bar(1, a);
+ if (result != 35) {
+ throw new Error("Got " + result + ", expected " + 35);
+ }
}
}