Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 public class Main {
     18 
     19   /// CHECK-START: int Main.div() licm (before)
     20   /// CHECK-DAG: Div loop:{{B\d+}}
     21 
     22   /// CHECK-START: int Main.div() licm (after)
     23   /// CHECK-NOT: Div loop:{{B\d+}}
     24 
     25   /// CHECK-START: int Main.div() licm (after)
     26   /// CHECK-DAG: Div loop:none
     27 
     28   public static int div() {
     29     int result = 0;
     30     for (int i = 0; i < 10; ++i) {
     31       result += staticField / 42;
     32     }
     33     return result;
     34   }
     35 
     36   /// CHECK-START: int Main.innerDiv() licm (before)
     37   /// CHECK-DAG: Div loop:{{B\d+}}
     38 
     39   /// CHECK-START: int Main.innerDiv() licm (after)
     40   /// CHECK-NOT: Div loop:{{B\d+}}
     41 
     42   /// CHECK-START: int Main.innerDiv() licm (after)
     43   /// CHECK-DAG: Div loop:none
     44 
     45   public static int innerDiv() {
     46     int result = 0;
     47     for (int i = 0; i < 10; ++i) {
     48       for (int j = 0; j < 10; ++j) {
     49         result += staticField / 42;
     50       }
     51     }
     52     return result;
     53   }
     54 
     55   /// CHECK-START: int Main.innerMul() licm (before)
     56   /// CHECK-DAG: Mul loop:B4
     57 
     58   /// CHECK-START: int Main.innerMul() licm (after)
     59   /// CHECK-DAG: Mul loop:B2
     60 
     61   public static int innerMul() {
     62     int result = 0;
     63     for (int i = 0; i < 10; ++i) {
     64       for (int j = 0; j < 10; ++j) {
     65         // The operation has been hoisted out of the inner loop.
     66         // Note that we depend on the compiler's block numbering to
     67         // check if it has been moved.
     68         result += staticField * i;
     69       }
     70     }
     71     return result;
     72   }
     73 
     74   /// CHECK-START: int Main.divByA(int, int) licm (before)
     75   /// CHECK-DAG: Div loop:{{B\d+}}
     76 
     77   /// CHECK-START: int Main.divByA(int, int) licm (after)
     78   /// CHECK-DAG: Div loop:{{B\d+}}
     79 
     80   public static int divByA(int a, int b) {
     81     int result = 0;
     82     while (b < 5) {
     83       // a might be null, so we can't hoist the operation.
     84       result += staticField / a;
     85       b++;
     86     }
     87     return result;
     88   }
     89 
     90   /// CHECK-START: int Main.arrayLength(int[]) licm (before)
     91   /// CHECK-DAG: <<NullCheck:l\d+>> NullCheck loop:{{B\d+}}
     92   /// CHECK-DAG:                    ArrayLength [<<NullCheck>>] loop:{{B\d+}}
     93 
     94   /// CHECK-START: int Main.arrayLength(int[]) licm (after)
     95   /// CHECK-NOT:                    NullCheck loop:{{B\d+}}
     96   /// CHECK-NOT:                    ArrayLength loop:{{B\d+}}
     97 
     98   /// CHECK-START: int Main.arrayLength(int[]) licm (after)
     99   /// CHECK-DAG: <<NullCheck:l\d+>> NullCheck loop:none
    100   /// CHECK-DAG:                    ArrayLength [<<NullCheck>>] loop:none
    101 
    102   public static int arrayLength(int[] array) {
    103     int result = 0;
    104     for (int i = 0; i < array.length; ++i) {
    105       result += array[i];
    106     }
    107     return result;
    108   }
    109 
    110   /// CHECK-START: int Main.divAndIntrinsic(int[]) licm (before)
    111   /// CHECK-DAG: Div loop:{{B\d+}}
    112 
    113   /// CHECK-START: int Main.divAndIntrinsic(int[]) licm (after)
    114   /// CHECK-NOT: Div loop:{{B\d+}}
    115 
    116   /// CHECK-START: int Main.divAndIntrinsic(int[]) licm (after)
    117   /// CHECK-DAG: Div loop:none
    118 
    119   public static int divAndIntrinsic(int[] array) {
    120     int result = 0;
    121     for (int i = 0; i < array.length; i++) {
    122       // An intrinsic call, unlike a general method call, cannot modify the field value.
    123       // As a result, the invariant division on the field can be moved out of the loop.
    124       result += (staticField / 42) + Math.abs(array[i]);
    125     }
    126     return result;
    127   }
    128 
    129   /// CHECK-START: int Main.invariantBoundIntrinsic(int) licm (before)
    130   /// CHECK-DAG: InvokeStaticOrDirect loop:{{B\d+}}
    131 
    132   /// CHECK-START: int Main.invariantBoundIntrinsic(int) licm (after)
    133   /// CHECK-NOT: InvokeStaticOrDirect loop:{{B\d+}}
    134 
    135   /// CHECK-START: int Main.invariantBoundIntrinsic(int) licm (after)
    136   /// CHECK-DAG: InvokeStaticOrDirect loop:none
    137 
    138   public static int invariantBoundIntrinsic(int x) {
    139     int result = 0;
    140     // The intrinsic call to abs used as loop bound is invariant.
    141     // As a result, the call itself can be moved out of the loop header.
    142     for (int i = 0; i < Math.abs(x); i++) {
    143       result += i;
    144     }
    145     return result;
    146   }
    147 
    148   /// CHECK-START: int Main.invariantBodyIntrinsic(int, int) licm (before)
    149   /// CHECK-DAG: InvokeStaticOrDirect loop:{{B\d+}}
    150 
    151   /// CHECK-START: int Main.invariantBodyIntrinsic(int, int) licm (after)
    152   /// CHECK-NOT: InvokeStaticOrDirect loop:{{B\d+}}
    153 
    154   /// CHECK-START: int Main.invariantBodyIntrinsic(int, int) licm (after)
    155   /// CHECK-DAG: InvokeStaticOrDirect loop:none
    156 
    157   public static int invariantBodyIntrinsic(int x, int y) {
    158     int result = 0;
    159     for (int i = 0; i < 10; i++) {
    160       // The intrinsic call to max used inside the loop is invariant.
    161       // As a result, the call itself can be moved out of the loop body.
    162       result += Math.max(x, y);
    163     }
    164     return result;
    165   }
    166 
    167   public static int staticField = 42;
    168 
    169   public static void assertEquals(int expected, int actual) {
    170     if (expected != actual) {
    171       throw new Error("Expected " + expected + ", got " + actual);
    172     }
    173   }
    174 
    175   public static void main(String[] args) {
    176     assertEquals(10, div());
    177     assertEquals(100, innerDiv());
    178     assertEquals(18900, innerMul());
    179     assertEquals(105, divByA(2, 0));
    180     assertEquals(12, arrayLength(new int[] { 4, 8 }));
    181     assertEquals(21, divAndIntrinsic(new int[] { 4, -2, 8, -3 }));
    182     assertEquals(45, invariantBoundIntrinsic(-10));
    183     assertEquals(30, invariantBodyIntrinsic(2, 3));
    184   }
    185 }
    186