OSDN Git Service

BCE: don't assume a bounds check always gets a HArrayLength.
authorNicolas Geoffray <ngeoffray@google.com>
Wed, 24 Jun 2015 13:57:44 +0000 (14:57 +0100)
committerNicolas Geoffray <ngeoffray@google.com>
Wed, 24 Jun 2015 14:02:23 +0000 (15:02 +0100)
Deoptimizations may change it to a HPhi.

bug:22056703
Change-Id: I8995209438764dac496ed856782b147ba21f93e5

compiler/optimizing/bounds_check_elimination.cc
test/499-bce-phi-array-length/src/Main.java

index 900dabe..7fe9fb2 100644 (file)
@@ -1388,7 +1388,7 @@ class BCEVisitor : public HGraphVisitor {
     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 @@ class BCEVisitor : public HGraphVisitor {
          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;
index c8c84a1..e917bc1 100644 (file)
@@ -32,11 +32,33 @@ public class Main {
     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);
+    }
   }
 }