• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
div()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 
innerDiv()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 
innerMul()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 
divByA(int a, int b)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 
arrayLength(int[] array)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 
divAndIntrinsic(int[] array)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 
invariantBoundIntrinsic(int x)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 
invariantBodyIntrinsic(int x, int y)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 
assertEquals(int expected, int actual)169   public static void assertEquals(int expected, int actual) {
170     if (expected != actual) {
171       throw new Error("Expected " + expected + ", got " + actual);
172     }
173   }
174 
main(String[] args)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