content: /*
   * Copyright (C) 2016 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  public class Main {
  
    /**
     * Method with an outer countable loop and an inner do-while loop.
     * Since all work is done in the header of the inner loop, any invariant hoisting
     * and deopting should be done in its proper loop preheader, not the true-block
     * of the newly generated taken-test after dynamic BCE.
     */
    public static int doit(int[][] x, int j) {
      float f = 0;
      int acc = 0;
      for (int i = 0; i < 2; i++) {
        // The full body of a do-while loop is the loop header.
        do {
          // Some "noise" to avoid hoisting the array reference
          // before the dynamic BCE phase runs.
          f++;
          // The invariant array reference with corresponding bounds check
          // is a candidate for hoisting when dynamic BCE runs. If it is
          // not moved to the proper loop preheader, the wrong values
          // cause the test to fail.
          acc += x[i][i];
        } while (++j < i);
      }
      return acc;
    }
  
    /**
     * Single countable loop with a clear header and a loop body. In this case,
     * after dynamic bce, some invariant hoisting and deopting must go to the
     * proper loop preheader and some must go to the true-block.
     */
    public static int foo(int[] x, int[] y, int n) {
      float f = 0;
      int acc = 0;
      int i = 0;
      while (true) {
        // This part is the loop header.
        // Some "noise" to avoid hoisting the array reference
        // before the dynamic BCE phase runs.
        f++;
        // The invariant array reference with corresponding bounds check
        // is a candidate for hoisting when dynamic BCE runs. If it is
        // not moved to the proper loop preheader, the wrong values
        // cause the test to fail.
        acc += y[0];
        if (++i > n)
          break;
        // From here on, this part is the loop body.
        // The unit-stride array reference is a candidate for dynamic BCE.
        // The deopting appears in the true-block.
        acc += x[i];
      }
      return acc;
    }
  
    /**
     * An artificial example with an inconsistent phi structure during
     * dynamic bce that is corrected afterwards. Note that only the last
     * assignment is really live, but the other statements set up an
     * interesting phi structure.
     */
    private static int doit(int[] z) {
      int a = 0;
      for (int i = 0; i < 10; ++i) {
        for (int j = i; j < 10; ++j) {
          a = z[i];
          for (int k = 0; k < 10; ++k) {
            a += z[k];
            a = z[i];
          }
        }
      }
      return a;
    }
  
    /**
     * Example shows that we can hoist ArrayGet to pre-header only if
     * its execution is guaranteed.
     */
    public static int hoistcheck(int[] c) {
      int i = 0, i2 = 0, i3 = 0, k = 0;
      int n = c.length;
      for (i = -100000000; i < 20; i += 10000000) {
        i3 = i;
        i2 = 0;
        while (i2++ < 1) {
          if (i3 >= 0 && i3 < n) {
            k += c[i3];
          }
        }
      }
      return k;
    }
  
    public static void main(String args[]) {
      int[][] x = new int[2][2];
      int y;
  
      x[0][0] = 1;
      x[1][1] = 2;
  
      expectEquals(8, doit(x, -6));
      expectEquals(7, doit(x, -5));
      expectEquals(6, doit(x, -4));
      expectEquals(5, doit(x, -3));
      expectEquals(4, doit(x, -2));
      expectEquals(3, doit(x, -1));
      expectEquals(3, doit(x,  0));
      expectEquals(3, doit(x,  1));
      expectEquals(3, doit(x, 22));
  
      int a[] = { 1, 2, 3, 5 };
      int b[] = { 7 };
  
      expectEquals(7,  foo(a, b, -1));
      expectEquals(7,  foo(a, b,  0));
      expectEquals(16, foo(a, b,  1));
      expectEquals(26, foo(a, b,  2));
      expectEquals(38, foo(a, b,  3));
  
      int[] z = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
      expectEquals(10, doit(z));
  
      int c[] = { 1, 2, 3, 5 };
      expectEquals(1, hoistcheck(c));
  
      System.out.println("passed");
    }
  
    private static void expectEquals(int expected, int result) {
      if (expected != result) {
        throw new Error("Expected: " + expected + ", found: " + result);
      }
    }
  }
  