/* * Copyright (C) 2018 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. */ import java.lang.reflect.Method; // // Test loop optimizations, in particular scalar loop peeling and unrolling. public class Main { static final int LENGTH = 4 * 1024; int[] a = new int[LENGTH]; int[] b = new int[LENGTH]; private static final int LENGTH_A = LENGTH; private static final int LENGTH_B = 16; private static final int RESULT_POS = 4; double[][] mA; double[][] mB; double[][] mC; public Main() { mA = new double[LENGTH_A][]; mB = new double[LENGTH_B][]; mC = new double[LENGTH_B][]; for (int i = 0; i < LENGTH_A; i++) { mA[i] = new double[LENGTH_B]; } for (int i = 0; i < LENGTH_B; i++) { mB[i] = new double[LENGTH_A]; mC[i] = new double[LENGTH_B]; } } private static final void initMatrix(double[][] m) { for (int i = 0; i < m.length; i++) { for (int j = 0; j < m[i].length; j++) { m[i][j] = (double) (i * LENGTH / (j + 1)); } } } private static final void initIntArray(int[] a) { for (int i = 0; i < a.length; i++) { a[i] = i % 4; } } private static final void initDoubleArray(double[] a) { for (int i = 0; i < a.length; i++) { a[i] = (double)(i % 4); } } /// CHECK-START: void Main.unrollingLoadStoreElimination(int[]) loop_optimization (before) /// CHECK-DAG: <> ParameterValue loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 4094 loop:none /// CHECK-DAG: <> Phi loop:<> outer_loop:none /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> If [<>] loop:<> outer_loop:none /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: ArraySet [<>,<>,<>] loop:<> outer_loop:none // /// CHECK-NOT: ArrayGet loop:<> outer_loop:none /// CHECK-NOT: ArraySet loop:<> outer_loop:none /// CHECK-START: void Main.unrollingLoadStoreElimination(int[]) loop_optimization (after) /// CHECK-DAG: <> ParameterValue loop:none /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 4094 loop:none /// CHECK-DAG: <> Phi loop:<> outer_loop:none /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> If [<>] loop:<> outer_loop:none /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: ArraySet [<>,<>,<>] loop:<> outer_loop:none // /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> If [<>] loop:<> outer_loop:none /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: ArraySet [<>,<>,<>] loop:<> outer_loop:none // /// CHECK-NOT: ArrayGet loop:<> outer_loop:none /// CHECK-NOT: ArraySet loop:<> outer_loop:none private static final void unrollingLoadStoreElimination(int[] a) { for (int i = 0; i < LENGTH - 2; i++) { a[i] += a[i + 1]; } } // Simple check that loop unrolling has happened. // /// CHECK-START: void Main.unrollingSwitch(int[]) loop_optimization (before) /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 4096 loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> If [<>] loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none /// CHECK-DAG: Add [<>,<>] loop:<> outer_loop:none // /// CHECK-NOT: ArrayGet loop:<> outer_loop:none /// CHECK-NOT: ArraySet loop:<> outer_loop:none /// CHECK-START: void Main.unrollingSwitch(int[]) loop_optimization (after) /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 4096 loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> If [<>] loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none // /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> If [<>] loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none /// CHECK-DAG: Add [<>,<>] loop:<> outer_loop:none // /// CHECK-NOT: ArrayGet loop:<> outer_loop:none /// CHECK-NOT: ArraySet loop:<> outer_loop:none private static final void unrollingSwitch(int[] a) { for (int i = 0; i < LENGTH; i++) { switch (i % 3) { case 2: a[i]++; break; default: break; } } } // Simple check that loop unrolling has happened. // /// CHECK-START: void Main.unrollingSwapElements(int[]) loop_optimization (before) /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 4094 loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> If [<>] loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none /// CHECK-DAG: Add [<>,<>] loop:<> outer_loop:none // /// CHECK-NOT: ArrayGet loop:<> outer_loop:none /// CHECK-NOT: ArraySet loop:<> outer_loop:none /// CHECK-START: void Main.unrollingSwapElements(int[]) loop_optimization (after) /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 4094 loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> If [<>] loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none // /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> If [<>] loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none /// CHECK-DAG: Add [<>,<>] loop:<> outer_loop:none // /// CHECK-NOT: ArrayGet loop:<> outer_loop:none /// CHECK-NOT: ArraySet loop:<> outer_loop:none private static final void unrollingSwapElements(int[] array) { for (int i = 0; i < LENGTH - 2; i++) { if (array[i] > array[i + 1]) { int temp = array[i + 1]; array[i + 1] = array[i]; array[i] = temp; } } } // Simple check that loop unrolling has happened. // /// CHECK-START: void Main.unrollingRInnerproduct(double[][], double[][], double[][], int, int) loop_optimization (before) /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 16 loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> If [<>] loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none /// CHECK-DAG: Add [<>,<>] loop:<> outer_loop:none // /// CHECK-NOT: ArrayGet loop:<> outer_loop:none /// CHECK-NOT: ArraySet loop:<> outer_loop:none /// CHECK-START: void Main.unrollingRInnerproduct(double[][], double[][], double[][], int, int) loop_optimization (after) /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 16 loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> If [<>] loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none // /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> If [<>] loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none /// CHECK-DAG: Add [<>,<>] loop:<> outer_loop:none // /// CHECK-NOT: ArrayGet loop:<> outer_loop:none /// CHECK-NOT: ArraySet loop:<> outer_loop:none private static final void unrollingRInnerproduct(double[][] result, double[][] a, double[][] b, int row, int column) { // computes the inner product of A[row,*] and B[*,column] int i; result[row][column] = 0.0f; for (i = 0; i < LENGTH_B; i++) { result[row][column] = result[row][column] + a[row][i] * b[i][column]; } } // nested loop // [[[]]] /// CHECK-START: void Main.unrollingInTheNest(int[], int[], int) loop_optimization (before) /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 128 loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:<> /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:<> /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: If [<>] loop:<> outer_loop:<> /// CHECK-DAG: ArrayGet loop:<> outer_loop:<> /// CHECK-DAG: ArraySet loop:<> outer_loop:<> /// CHECK-DAG: ArrayGet loop:<> outer_loop:<> /// CHECK-DAG: ArraySet loop:<> outer_loop:<> /// CHECK-DAG: Add [<>,<>] loop:<> outer_loop:<> // /// CHECK-NOT: ArrayGet /// CHECK-NOT: ArraySet /// CHECK-NOT: If /// CHECK-START: void Main.unrollingInTheNest(int[], int[], int) loop_optimization (after) /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 128 loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:<> /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:<> /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: If [<>] loop:<> outer_loop:<> /// CHECK-DAG: ArrayGet loop:<> outer_loop:<> /// CHECK-DAG: ArraySet loop:<> outer_loop:<> /// CHECK-DAG: ArrayGet loop:<> outer_loop:<> /// CHECK-DAG: ArraySet loop:<> outer_loop:<> /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:<> // /// CHECK-DAG: If [<>] loop:<> outer_loop:<> /// CHECK-DAG: ArrayGet loop:<> outer_loop:<> /// CHECK-DAG: ArraySet loop:<> outer_loop:<> /// CHECK-DAG: ArrayGet loop:<> outer_loop:<> /// CHECK-DAG: ArraySet loop:<> outer_loop:<> // /// CHECK-NOT: ArrayGet /// CHECK-NOT: ArraySet /// CHECK-NOT: If private static final void unrollingInTheNest(int[] a, int[] b, int x) { for (int k = 0; k < 16; k++) { for (int j = 0; j < 16; j++) { for (int i = 0; i < 128; i++) { b[x]++; a[i] = a[i] + 1; } } } } // nested loop: // [ // if [] else [] // ] /// CHECK-START: void Main.unrollingTwoLoopsInTheNest(int[], int[], int) loop_optimization (before) /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 128 loop:none /// CHECK-DAG: <> IntConstant 100 loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none // /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:<> /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: If [<>] loop:<> outer_loop:<> /// CHECK-DAG: ArrayGet loop:<> outer_loop:<> /// CHECK-DAG: ArraySet loop:<> outer_loop:<> /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:<> // /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:<> /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: If [<>] loop:<> outer_loop:<> /// CHECK-DAG: ArrayGet loop:<> outer_loop:<> /// CHECK-DAG: ArraySet loop:<> outer_loop:<> /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:<> // /// CHECK-NOT: ArrayGet /// CHECK-NOT: ArraySet /// CHECK-NOT: If /// CHECK-START: void Main.unrollingTwoLoopsInTheNest(int[], int[], int) loop_optimization (after) /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 128 loop:none /// CHECK-DAG: <> IntConstant 100 loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none // /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:<> /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: If [<>] loop:<> outer_loop:<> /// CHECK-DAG: ArrayGet loop:<> outer_loop:<> /// CHECK-DAG: ArraySet loop:<> outer_loop:<> /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: If [<>] loop:<> outer_loop:<> /// CHECK-DAG: ArrayGet loop:<> outer_loop:<> /// CHECK-DAG: ArraySet loop:<> outer_loop:<> /// CHECK-DAG: Add [<>,<>] loop:<> outer_loop:<> // /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:<> /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: If [<>] loop:<> outer_loop:<> /// CHECK-DAG: ArrayGet loop:<> outer_loop:<> /// CHECK-DAG: ArraySet loop:<> outer_loop:<> /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: If [<>] loop:<> outer_loop:<> /// CHECK-DAG: ArrayGet loop:<> outer_loop:<> /// CHECK-DAG: ArraySet loop:<> outer_loop:<> /// CHECK-DAG: Add [<>,<>] loop:<> outer_loop:<> // /// CHECK-NOT: ArrayGet /// CHECK-NOT: ArraySet /// CHECK-NOT: If private static final void unrollingTwoLoopsInTheNest(int[] a, int[] b, int x) { for (int k = 0; k < 128; k++) { if (x > 100) { for (int j = 0; j < 128; j++) { a[x]++; } } else { for (int i = 0; i < 128; i++) { b[x]++; } } } } /// CHECK-START: int Main.unrollingSimpleLiveOuts(int[]) loop_optimization (before) /// CHECK-DAG: <> ParameterValue loop:none /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 2 loop:none /// CHECK-DAG: <> IntConstant 4094 loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: If [<>] loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> Mul [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: ArraySet [<>,<>,<>] loop:<> outer_loop:none // /// CHECK-DAG: <> Add [<>,<>] loop:none /// CHECK-DAG: <> DivZeroCheck [<>] env:[[<>,<>,<>,<>,_,<>]] loop:none /// CHECK-DAG: <> Div [<>,<>] loop:none /// CHECK-DAG: Return [<
>] loop:none /// CHECK-NOT: ArrayGet /// CHECK-NOT: ArraySet /// CHECK-START: int Main.unrollingSimpleLiveOuts(int[]) loop_optimization (after) /// CHECK-DAG: <> ParameterValue loop:none /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 2 loop:none /// CHECK-DAG: <> IntConstant 4094 loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: If [<>] loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> Mul [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: ArraySet [<>,<>,<>] loop:<> outer_loop:none // /// CHECK-DAG: GreaterThanOrEqual [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: If [<>] loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> Mul [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: ArraySet [<>,<>,<>] loop:<> outer_loop:none // /// CHECK-DAG: <> Phi [<>,<>] loop:none /// CHECK-DAG: <> Phi [<>,<>] loop:none /// CHECK-DAG: <> Add [<>,<>] loop:none /// CHECK-DAG: <> DivZeroCheck [<>] env:[[<>,<>,<>,<>,_,<>]] loop:none /// CHECK-DAG: <> Div [<>,<>] loop:none /// CHECK-DAG: Return [<
>] loop:none // /// CHECK-NOT: ArrayGet /// CHECK-NOT: ArraySet private static final int unrollingSimpleLiveOuts(int[] a) { int s = 1; int t = 2; for (int i = 0; i < LENGTH - 2; i++) { int temp = a[i + 1]; s += temp; t *= temp; a[i] += s; } return 1 / (s + t); } /// CHECK-START: int Main.unrollingLiveOutsNested(int[]) loop_optimization (before) /// CHECK-DAG: <> ParameterValue loop:none /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 2 loop:none /// CHECK-DAG: <> IntConstant 4094 loop:none // /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none // /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:<> /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:<> /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:<> /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: If [<>] loop:<> outer_loop:<> /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: <> Mul [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: ArraySet [<>,<>,<>] loop:<> outer_loop:<> // /// CHECK-DAG: Add [<>,<>] loop:<> outer_loop:none // /// CHECK-NOT: ArrayGet /// CHECK-NOT: ArraySet /// CHECK-START: int Main.unrollingLiveOutsNested(int[]) loop_optimization (after) /// CHECK-DAG: <> ParameterValue loop:none /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 2 loop:none /// CHECK-DAG: <> IntConstant 4094 loop:none // /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none // /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:<> /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:<> /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:<> /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: If [<>] loop:<> outer_loop:<> /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: <> Mul [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: ArraySet [<>,<>,<>] loop:<> outer_loop:<> // /// CHECK-DAG: If [<>] loop:<> outer_loop:<> /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: <> Mul [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: ArraySet [<>,<>,<>] loop:<> outer_loop:<> // /// CHECK-DAG: <> Phi [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> Phi [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: Add [<>,<>] loop:<> outer_loop:none // /// CHECK-DAG: <> Add [<>,<>] loop:none /// CHECK-DAG: Return [<>] loop:none // /// CHECK-NOT: ArrayGet /// CHECK-NOT: ArraySet private static final int unrollingLiveOutsNested(int[] a) { int s = 1; int t = 2; for (int j = 0; j < 16; j++) { for (int i = 0; i < LENGTH - 2; i++) { int temp = a[i + 1]; s += temp; t *= temp; a[i] += s; } } return s + t; } /// CHECK-START: void Main.unrollingInstanceOf(int[], java.lang.Object[]) loop_optimization (before) /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: InstanceOf loop:<> outer_loop:none // /// CHECK-NOT: InstanceOf /// CHECK-START: void Main.unrollingInstanceOf(int[], java.lang.Object[]) loop_optimization (after) /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: InstanceOf loop:<> outer_loop:none /// CHECK-DAG: InstanceOf loop:<> outer_loop:none // /// CHECK-NOT: InstanceOf public void unrollingInstanceOf(int[] a, Object[] obj_array) { for (int i = 0; i < LENGTH_B; i++) { if (obj_array[i] instanceof Integer) { a[i] += 1; } } } /// CHECK-START: void Main.unrollingDivZeroCheck(int[], int) loop_optimization (before) /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: DivZeroCheck loop:<> outer_loop:none // /// CHECK-NOT: DivZeroCheck /// CHECK-START: void Main.unrollingDivZeroCheck(int[], int) loop_optimization (after) /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: DivZeroCheck loop:<> outer_loop:none /// CHECK-DAG: DivZeroCheck loop:<> outer_loop:none // /// CHECK-NOT: DivZeroCheck public void unrollingDivZeroCheck(int[] a, int r) { for (int i = 0; i < LENGTH_B; i++) { a[i] += a[i] / r; } } /// CHECK-START: void Main.unrollingTypeConversion(int[], double[]) loop_optimization (before) /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: TypeConversion loop:<> outer_loop:none // /// CHECK-NOT: TypeConversion /// CHECK-START: void Main.unrollingTypeConversion(int[], double[]) loop_optimization (after) /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: TypeConversion loop:<> outer_loop:none /// CHECK-DAG: TypeConversion loop:<> outer_loop:none // /// CHECK-NOT: TypeConversion public void unrollingTypeConversion(int[] a, double[] b) { for (int i = 0; i < LENGTH_B; i++) { a[i] = (int) b[i]; } } interface Itf { } class SubMain extends Main implements Itf { } /// CHECK-START: void Main.unrollingCheckCast(int[], java.lang.Object) loop_optimization (before) /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: CheckCast loop:<> outer_loop:none // /// CHECK-NOT: CheckCast /// CHECK-START: void Main.unrollingCheckCast(int[], java.lang.Object) loop_optimization (after) /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: CheckCast loop:<> outer_loop:none /// CHECK-DAG: CheckCast loop:<> outer_loop:none // /// CHECK-NOT: CheckCast public void unrollingCheckCast(int[] a, Object o) { for (int i = 0; i < LENGTH_B; i++) { if (((SubMain)o) == o) { a[i] = i; } } } /// CHECK-START: void Main.noUnrollingOddTripCount(int[]) loop_optimization (before) /// CHECK-DAG: <> ParameterValue loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 4095 loop:none /// CHECK-DAG: <> Phi loop:<> outer_loop:none /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> If [<>] loop:<> outer_loop:none /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: ArraySet [<>,<>,<>] loop:<> outer_loop:none // /// CHECK-NOT: Phi /// CHECK-NOT: If /// CHECK-NOT: ArrayGet /// CHECK-NOT: ArraySet /// CHECK-START: void Main.noUnrollingOddTripCount(int[]) loop_optimization (after) /// CHECK-DAG: Phi loop:<> outer_loop:none /// CHECK-DAG: If loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none // /// CHECK-NOT: Phi /// CHECK-NOT: If /// CHECK-NOT: ArrayGet /// CHECK-NOT: ArraySet private static final void noUnrollingOddTripCount(int[] a) { for (int i = 0; i < LENGTH - 1; i++) { a[i] += a[i + 1]; } } /// CHECK-START: void Main.noUnrollingNotKnownTripCount(int[], int) loop_optimization (before) /// CHECK-DAG: <> ParameterValue loop:none /// CHECK-DAG: <> ParameterValue loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> Phi loop:<> outer_loop:none /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> If [<>] loop:<> outer_loop:none /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> ArrayGet [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: ArraySet [<>,<>,<>] loop:<> outer_loop:none // /// CHECK-NOT: Phi /// CHECK-NOT: ArrayGet /// CHECK-NOT: ArraySet /// CHECK-START: void Main.noUnrollingNotKnownTripCount(int[], int) loop_optimization (after) /// CHECK-DAG: Phi loop:<> outer_loop:none /// CHECK-DAG: If loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none // /// CHECK-NOT: Phi /// CHECK-NOT: ArrayGet /// CHECK-NOT: ArraySet private static final void noUnrollingNotKnownTripCount(int[] a, int n) { for (int i = 0; i < n; i++) { a[i] += a[i + 1]; } } /// CHECK-START: void Main.peelingSimple(int[], boolean) loop_optimization (before) /// CHECK-DAG: <> ParameterValue loop:none /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 4096 loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: If [<>] loop:<> outer_loop:none /// CHECK-DAG: If [<>] loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none // /// CHECK-NOT: If /// CHECK-NOT: ArraySet /// CHECK-START: void Main.peelingSimple(int[], boolean) loop_optimization (after) /// CHECK-DAG: <> ParameterValue loop:none /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 4096 loop:none /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:none /// CHECK-DAG: If [<>] loop:none /// CHECK-DAG: If [<>] loop:none /// CHECK-DAG: ArrayGet loop:none /// CHECK-DAG: ArraySet loop:none /// CHECK-DAG: <> Add [<>,<>] loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: If [<>] loop:<> outer_loop:none /// CHECK-DAG: If [<>] loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none // /// CHECK-NOT: If /// CHECK-NOT: ArraySet /// CHECK-START: void Main.peelingSimple(int[], boolean) dead_code_elimination$final (after) /// CHECK-DAG: <> ParameterValue loop:none /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 4096 loop:none /// CHECK-DAG: If [<>] loop:none /// CHECK-DAG: ArrayGet loop:none /// CHECK-DAG: ArraySet loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:none /// CHECK-DAG: If [<>] loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none // /// CHECK-NOT: GreaterThanOrEqual /// CHECK-NOT: If /// CHECK-NOT: ArrayGet /// CHECK-NOT: ArraySet private static final void peelingSimple(int[] a, boolean f) { for (int i = 0; i < LENGTH; i++) { if (f) { break; } a[i] += 1; } } // Often used idiom that, when not hoisted, prevents BCE and vectorization. // /// CHECK-START: void Main.peelingAddInts(int[]) loop_optimization (before) /// CHECK-DAG: <> ParameterValue loop:none /// CHECK-DAG: <> NullConstant loop:none /// CHECK-DAG: <> Equal [<>,<>] loop:none /// CHECK-DAG: <> Phi loop:<> outer_loop:none /// CHECK-DAG: If [<>] loop:<> outer_loop:none /// CHECK-DAG: <> GreaterThanOrEqual [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: If [<>] loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none /// CHECK-START: void Main.peelingAddInts(int[]) dead_code_elimination$final (after) /// CHECK-DAG: <> ParameterValue loop:none /// CHECK-DAG: <> NullConstant loop:none /// CHECK-DAG: <> Equal [<>,<>] loop:none /// CHECK-DAG: If [<>] loop:none /// CHECK-DAG: ArraySet loop:none /// CHECK-DAG: <> Phi loop:<> outer_loop:none /// CHECK-DAG: <> GreaterThanOrEqual [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: If [<>] loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none // /// CHECK-NOT: If [<>] loop:<> outer_loop:none private static final void peelingAddInts(int[] a) { for (int i = 0; a != null && i < a.length; i++) { a[i] += 1; } } /// CHECK-START: void Main.peelingBreakFromNest(int[], boolean) loop_optimization (before) /// CHECK-DAG: <> ParameterValue loop:none /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 4096 loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:<> /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: If [<>] loop:<> outer_loop:<> /// CHECK-DAG: If [<>] loop:<> outer_loop:<> /// CHECK-DAG: ArrayGet loop:<> outer_loop:<> /// CHECK-DAG: ArraySet loop:<> outer_loop:<> /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none // /// CHECK-NOT: If /// CHECK-NOT: ArraySet /// CHECK-START: void Main.peelingBreakFromNest(int[], boolean) dead_code_elimination$final (after) /// CHECK-DAG: <> ParameterValue loop:none /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 4096 loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: If [<>] loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:<> /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: If [<>] loop:<> outer_loop:<> /// CHECK-DAG: ArrayGet loop:<> outer_loop:<> /// CHECK-DAG: ArraySet loop:<> outer_loop:<> /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:<> /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none // /// CHECK-NOT: If /// CHECK-NOT: ArraySet private static final void peelingBreakFromNest(int[] a, boolean f) { outer: for (int i = 1; i < 32; i++) { for (int j = 0; j < LENGTH; j++) { if (f) { break outer; } a[j] += 1; } } } /// CHECK-START: int Main.peelingHoistOneControl(int) loop_optimization (before) /// CHECK-DAG: <> ParameterValue loop:none /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> NotEqual [<>,<>] loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: If [<>] loop:<> outer_loop:none /// CHECK-DAG: <> Add [<>,<>] loop:<> outer_loop:none // /// CHECK-NOT: If /// CHECK-START: int Main.peelingHoistOneControl(int) dead_code_elimination$final (after) /// CHECK-DAG: <> ParameterValue loop:none /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> NotEqual [<>,<>] loop:none /// CHECK-DAG: If [<>] loop:none /// CHECK-DAG: SuspendCheck loop:<> outer_loop:none /// CHECK-DAG: Goto loop:<> outer_loop:none // // Check that the loop has no instruction except SuspendCheck and Goto (indefinite loop). /// CHECK-NOT: loop:<> outer_loop:none /// CHECK-NOT: If /// CHECK-NOT: Phi /// CHECK-NOT: Add private static final int peelingHoistOneControl(int x) { int i = 0; while (true) { if (x == 0) return 1; i++; } } /// CHECK-START: int Main.peelingHoistOneControl(int, int) loop_optimization (before) /// CHECK-DAG: <> Phi loop:<> outer_loop:none /// CHECK-DAG: If loop:<> outer_loop:none /// CHECK-DAG: If loop:<> outer_loop:none // /// CHECK-START: int Main.peelingHoistOneControl(int, int) dead_code_elimination$final (after) /// CHECK-DAG: <> Phi loop:<> outer_loop:none /// CHECK-DAG: If loop:<> outer_loop:none /// CHECK-NOT: If loop:<> outer_loop:none private static final int peelingHoistOneControl(int x, int y) { while (true) { if (x == 0) return 1; if (y == 0) // no longer invariant return 2; y--; } } /// CHECK-START: int Main.peelingHoistTwoControl(int, int, int) loop_optimization (before) /// CHECK-DAG: <> Phi loop:<> outer_loop:none /// CHECK-DAG: If loop:<> outer_loop:none /// CHECK-DAG: If loop:<> outer_loop:none /// CHECK-DAG: If loop:<> outer_loop:none // /// CHECK-START: int Main.peelingHoistTwoControl(int, int, int) dead_code_elimination$final (after) /// CHECK-DAG: <> Phi loop:<> outer_loop:none /// CHECK-DAG: If loop:<> outer_loop:none /// CHECK-NOT: If loop:<> outer_loop:none private static final int peelingHoistTwoControl(int x, int y, int z) { while (true) { if (x == 0) return 1; if (y == 0) return 2; if (z == 0) // no longer invariant return 3; z--; } } /// CHECK-START: void Main.unrollingFull(int[]) loop_optimization (before) /// CHECK-DAG: <> ParameterValue loop:none /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 2 loop:none /// CHECK-DAG: <> Phi [<>,{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none // /// CHECK-NOT: ArrayGet /// CHECK-NOT: ArraySet /// CHECK-START: void Main.unrollingFull(int[]) loop_optimization (after) /// CHECK-DAG: <> ParameterValue loop:none /// CHECK-DAG: <> IntConstant 0 loop:none /// CHECK-DAG: <> IntConstant 1 loop:none /// CHECK-DAG: <> IntConstant 2 loop:none // Two peeled iterations /// CHECK-DAG: ArrayGet loop:none /// CHECK-DAG: ArrayGet loop:none /// CHECK-DAG: ArraySet loop:none /// CHECK-DAG: ArrayGet loop:none /// CHECK-DAG: ArrayGet loop:none /// CHECK-DAG: ArraySet loop:none // Loop /// CHECK-DAG: <> Phi [{{i\d+}},{{i\d+}}] loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArrayGet loop:<> outer_loop:none /// CHECK-DAG: ArraySet loop:<> outer_loop:none /// CHECK-DAG: If [<>] loop:<> outer_loop:none // /// CHECK-NOT: ArrayGet /// CHECK-NOT: ArraySet private static final void unrollingFull(int[] a) { for (int i = 0; i < 2; i++) { a[i] += a[i + 1]; } } private static void expectEquals(int expected, int result) { if (expected != result) { throw new Error("Expected: " + expected + ", found: " + result); } } public void verifyUnrolling() throws Exception { initIntArray(a); initIntArray(b); initMatrix(mA); initMatrix(mB); initMatrix(mC); int expected = 174291515; int found = 0; double[] doubleArray = new double[LENGTH_B]; initDoubleArray(doubleArray); unrollingInstanceOf(a, new Integer[LENGTH_B]); unrollingDivZeroCheck(a, 15); unrollingTypeConversion(a, doubleArray); unrollingCheckCast(a, new SubMain()); // Call unrollingWhile(a); Class c = Class.forName("PeelUnroll"); Method m = c.getMethod("unrollingWhile", Class.forName("[I")); Object[] arguments = { a }; m.invoke(null, arguments); unrollingLoadStoreElimination(a); unrollingSwitch(a); unrollingSwapElements(a); unrollingRInnerproduct(mC, mA, mB, RESULT_POS, RESULT_POS); unrollingInTheNest(a, b, RESULT_POS); unrollingTwoLoopsInTheNest(a, b, RESULT_POS); noUnrollingOddTripCount(b); noUnrollingNotKnownTripCount(b, 128); for (int i = 0; i < LENGTH; i++) { found += a[i]; found += b[i]; } found += (int)mC[RESULT_POS][RESULT_POS]; expectEquals(expected, found); } public void verifyPeeling() throws Exception { expectEquals(1, peelingHoistOneControl(0)); // anything else loops expectEquals(1, peelingHoistOneControl(0, 0)); expectEquals(1, peelingHoistOneControl(0, 1)); expectEquals(2, peelingHoistOneControl(1, 0)); expectEquals(2, peelingHoistOneControl(1, 1)); expectEquals(1, peelingHoistTwoControl(0, 0, 0)); expectEquals(1, peelingHoistTwoControl(0, 0, 1)); expectEquals(1, peelingHoistTwoControl(0, 1, 0)); expectEquals(1, peelingHoistTwoControl(0, 1, 1)); expectEquals(2, peelingHoistTwoControl(1, 0, 0)); expectEquals(2, peelingHoistTwoControl(1, 0, 1)); expectEquals(3, peelingHoistTwoControl(1, 1, 0)); expectEquals(3, peelingHoistTwoControl(1, 1, 1)); initIntArray(a); peelingSimple(a, false); peelingSimple(a, true); peelingAddInts(a); peelingAddInts(null); // okay peelingBreakFromNest(a, false); peelingBreakFromNest(a, true); unrollingSimpleLiveOuts(a); // Call unrollingWhileLiveOuts(a); Class c = Class.forName("PeelUnroll"); Method m = c.getMethod("unrollingWhileLiveOuts", Class.forName("[I")); Object[] arguments = { a }; m.invoke(null, arguments); unrollingLiveOutsNested(a); int expected = 51565978; int found = 0; for (int i = 0; i < a.length; i++) { found += a[i]; } expectEquals(expected, found); } public static void main(String[] args) throws Exception { Main obj = new Main(); obj.verifyUnrolling(); obj.verifyPeeling(); System.out.println("passed"); } }