|
1 /* |
|
2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. |
|
8 * |
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 * version 2 for more details (a copy is included in the LICENSE file that |
|
13 * accompanied this code). |
|
14 * |
|
15 * You should have received a copy of the GNU General Public License version |
|
16 * 2 along with this work; if not, write to the Free Software Foundation, |
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 * |
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
20 * or visit www.oracle.com if you need additional information or have any |
|
21 * questions. |
|
22 * |
|
23 */ |
|
24 |
|
25 /** |
|
26 * @test |
|
27 * @bug 8080289 |
|
28 * @summary Sink stores out of loops if possible |
|
29 * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:+PrintCompilation -XX:CompileCommand=dontinline,TestMoveStoresOutOfLoops::test* TestMoveStoresOutOfLoops |
|
30 * |
|
31 */ |
|
32 |
|
33 import java.lang.reflect.*; |
|
34 import java.util.*; |
|
35 import java.util.function.*; |
|
36 |
|
37 public class TestMoveStoresOutOfLoops { |
|
38 |
|
39 private static long[] array = new long[10]; |
|
40 private static long[] array2 = new long[10]; |
|
41 private static boolean[] array3 = new boolean[1000]; |
|
42 private static byte[] byte_array = new byte[10]; |
|
43 |
|
44 // Array store should be moved out of the loop, value stored |
|
45 // should be 999, the loop should be eliminated |
|
46 static void test_after_1(int idx) { |
|
47 for (int i = 0; i < 1000; i++) { |
|
48 array[idx] = i; |
|
49 } |
|
50 } |
|
51 |
|
52 // Array store can't be moved out of loop because of following |
|
53 // non loop invariant array access |
|
54 static void test_after_2(int idx) { |
|
55 for (int i = 0; i < 1000; i++) { |
|
56 array[idx] = i; |
|
57 array2[i%10] = i; |
|
58 } |
|
59 } |
|
60 |
|
61 // Array store can't be moved out of loop because of following |
|
62 // use |
|
63 static void test_after_3(int idx) { |
|
64 for (int i = 0; i < 1000; i++) { |
|
65 array[idx] = i; |
|
66 if (array[0] == -1) { |
|
67 break; |
|
68 } |
|
69 } |
|
70 } |
|
71 |
|
72 // Array store can't be moved out of loop because of preceding |
|
73 // use |
|
74 static void test_after_4(int idx) { |
|
75 for (int i = 0; i < 1000; i++) { |
|
76 if (array[0] == -2) { |
|
77 break; |
|
78 } |
|
79 array[idx] = i; |
|
80 } |
|
81 } |
|
82 |
|
83 // All array stores should be moved out of the loop, one after |
|
84 // the other |
|
85 static void test_after_5(int idx) { |
|
86 for (int i = 0; i < 1000; i++) { |
|
87 array[idx] = i; |
|
88 array[idx+1] = i; |
|
89 array[idx+2] = i; |
|
90 array[idx+3] = i; |
|
91 array[idx+4] = i; |
|
92 array[idx+5] = i; |
|
93 } |
|
94 } |
|
95 |
|
96 // Array store can be moved after the loop but needs to be |
|
97 // cloned on both exit paths |
|
98 static void test_after_6(int idx) { |
|
99 for (int i = 0; i < 1000; i++) { |
|
100 array[idx] = i; |
|
101 if (array3[i]) { |
|
102 return; |
|
103 } |
|
104 } |
|
105 } |
|
106 |
|
107 // Optimize out redundant stores |
|
108 static void test_stores_1(int ignored) { |
|
109 array[0] = 0; |
|
110 array[1] = 1; |
|
111 array[2] = 2; |
|
112 array[0] = 0; |
|
113 array[1] = 1; |
|
114 array[2] = 2; |
|
115 } |
|
116 |
|
117 static void test_stores_2(int idx) { |
|
118 array[idx+0] = 0; |
|
119 array[idx+1] = 1; |
|
120 array[idx+2] = 2; |
|
121 array[idx+0] = 0; |
|
122 array[idx+1] = 1; |
|
123 array[idx+2] = 2; |
|
124 } |
|
125 |
|
126 static void test_stores_3(int idx) { |
|
127 byte_array[idx+0] = 0; |
|
128 byte_array[idx+1] = 1; |
|
129 byte_array[idx+2] = 2; |
|
130 byte_array[idx+0] = 0; |
|
131 byte_array[idx+1] = 1; |
|
132 byte_array[idx+2] = 2; |
|
133 } |
|
134 |
|
135 // Array store can be moved out of the loop before the loop header |
|
136 static void test_before_1(int idx) { |
|
137 for (int i = 0; i < 1000; i++) { |
|
138 array[idx] = 999; |
|
139 } |
|
140 } |
|
141 |
|
142 // Array store can't be moved out of the loop before the loop |
|
143 // header because there's more than one store on this slice |
|
144 static void test_before_2(int idx) { |
|
145 for (int i = 0; i < 1000; i++) { |
|
146 array[idx] = 999; |
|
147 array[i%2] = 0; |
|
148 } |
|
149 } |
|
150 |
|
151 // Array store can't be moved out of the loop before the loop |
|
152 // header because of use before store |
|
153 static int test_before_3(int idx) { |
|
154 int res = 0; |
|
155 for (int i = 0; i < 1000; i++) { |
|
156 res += array[i%10]; |
|
157 array[idx] = 999; |
|
158 } |
|
159 return res; |
|
160 } |
|
161 |
|
162 // Array store can't be moved out of the loop before the loop |
|
163 // header because of possible early exit |
|
164 static void test_before_4(int idx) { |
|
165 for (int i = 0; i < 1000; i++) { |
|
166 if (idx / (i+1) > 0) { |
|
167 return; |
|
168 } |
|
169 array[idx] = 999; |
|
170 } |
|
171 } |
|
172 |
|
173 // Array store can't be moved out of the loop before the loop |
|
174 // header because it doesn't postdominate the loop head |
|
175 static void test_before_5(int idx) { |
|
176 for (int i = 0; i < 1000; i++) { |
|
177 if (i % 2 == 0) { |
|
178 array[idx] = 999; |
|
179 } |
|
180 } |
|
181 } |
|
182 |
|
183 // Array store can be moved out of the loop before the loop header |
|
184 static int test_before_6(int idx) { |
|
185 int res = 0; |
|
186 for (int i = 0; i < 1000; i++) { |
|
187 if (i%2 == 1) { |
|
188 res *= 2; |
|
189 } else { |
|
190 res++; |
|
191 } |
|
192 array[idx] = 999; |
|
193 } |
|
194 return res; |
|
195 } |
|
196 |
|
197 final HashMap<String,Method> tests = new HashMap<>(); |
|
198 { |
|
199 for (Method m : this.getClass().getDeclaredMethods()) { |
|
200 if (m.getName().matches("test_(before|after|stores)_[0-9]+")) { |
|
201 assert(Modifier.isStatic(m.getModifiers())) : m; |
|
202 tests.put(m.getName(), m); |
|
203 } |
|
204 } |
|
205 } |
|
206 |
|
207 boolean success = true; |
|
208 void doTest(String name, Runnable init, Function<String, Boolean> check) throws Exception { |
|
209 Method m = tests.get(name); |
|
210 for (int i = 0; i < 20000; i++) { |
|
211 init.run(); |
|
212 m.invoke(null, 0); |
|
213 success = success && check.apply(name); |
|
214 if (!success) { |
|
215 break; |
|
216 } |
|
217 } |
|
218 } |
|
219 |
|
220 static void array_init() { |
|
221 array[0] = -1; |
|
222 } |
|
223 |
|
224 static boolean array_check(String name) { |
|
225 boolean success = true; |
|
226 if (array[0] != 999) { |
|
227 success = false; |
|
228 System.out.println(name + " failed: array[0] = " + array[0]); |
|
229 } |
|
230 return success; |
|
231 } |
|
232 |
|
233 static void array_init2() { |
|
234 for (int i = 0; i < 6; i++) { |
|
235 array[i] = -1; |
|
236 } |
|
237 } |
|
238 |
|
239 static boolean array_check2(String name) { |
|
240 boolean success = true; |
|
241 for (int i = 0; i < 6; i++) { |
|
242 if (array[i] != 999) { |
|
243 success = false; |
|
244 System.out.println(name + " failed: array[" + i + "] = " + array[i]); |
|
245 } |
|
246 } |
|
247 return success; |
|
248 } |
|
249 |
|
250 static void array_init3() { |
|
251 for (int i = 0; i < 3; i++) { |
|
252 array[i] = -1; |
|
253 } |
|
254 } |
|
255 |
|
256 static boolean array_check3(String name) { |
|
257 boolean success = true; |
|
258 for (int i = 0; i < 3; i++) { |
|
259 if (array[i] != i) { |
|
260 success = false; |
|
261 System.out.println(name + " failed: array[" + i + "] = " + array[i]); |
|
262 } |
|
263 } |
|
264 return success; |
|
265 } |
|
266 |
|
267 static void array_init4() { |
|
268 for (int i = 0; i < 3; i++) { |
|
269 byte_array[i] = -1; |
|
270 } |
|
271 } |
|
272 |
|
273 static boolean array_check4(String name) { |
|
274 boolean success = true; |
|
275 for (int i = 0; i < 3; i++) { |
|
276 if (byte_array[i] != i) { |
|
277 success = false; |
|
278 System.out.println(name + " failed: byte_array[" + i + "] = " + byte_array[i]); |
|
279 } |
|
280 } |
|
281 return success; |
|
282 } |
|
283 |
|
284 static public void main(String[] args) throws Exception { |
|
285 TestMoveStoresOutOfLoops test = new TestMoveStoresOutOfLoops(); |
|
286 test.doTest("test_after_1", TestMoveStoresOutOfLoops::array_init, TestMoveStoresOutOfLoops::array_check); |
|
287 test.doTest("test_after_2", TestMoveStoresOutOfLoops::array_init, TestMoveStoresOutOfLoops::array_check); |
|
288 test.doTest("test_after_3", TestMoveStoresOutOfLoops::array_init, TestMoveStoresOutOfLoops::array_check); |
|
289 test.doTest("test_after_4", TestMoveStoresOutOfLoops::array_init, TestMoveStoresOutOfLoops::array_check); |
|
290 test.doTest("test_after_5", TestMoveStoresOutOfLoops::array_init2, TestMoveStoresOutOfLoops::array_check2); |
|
291 test.doTest("test_after_6", TestMoveStoresOutOfLoops::array_init, TestMoveStoresOutOfLoops::array_check); |
|
292 array3[999] = true; |
|
293 test.doTest("test_after_6", TestMoveStoresOutOfLoops::array_init, TestMoveStoresOutOfLoops::array_check); |
|
294 |
|
295 test.doTest("test_stores_1", TestMoveStoresOutOfLoops::array_init3, TestMoveStoresOutOfLoops::array_check3); |
|
296 test.doTest("test_stores_2", TestMoveStoresOutOfLoops::array_init3, TestMoveStoresOutOfLoops::array_check3); |
|
297 test.doTest("test_stores_3", TestMoveStoresOutOfLoops::array_init4, TestMoveStoresOutOfLoops::array_check4); |
|
298 |
|
299 test.doTest("test_before_1", TestMoveStoresOutOfLoops::array_init, TestMoveStoresOutOfLoops::array_check); |
|
300 test.doTest("test_before_2", TestMoveStoresOutOfLoops::array_init, TestMoveStoresOutOfLoops::array_check); |
|
301 test.doTest("test_before_3", TestMoveStoresOutOfLoops::array_init, TestMoveStoresOutOfLoops::array_check); |
|
302 test.doTest("test_before_4", TestMoveStoresOutOfLoops::array_init, TestMoveStoresOutOfLoops::array_check); |
|
303 test.doTest("test_before_5", TestMoveStoresOutOfLoops::array_init, TestMoveStoresOutOfLoops::array_check); |
|
304 test.doTest("test_before_6", TestMoveStoresOutOfLoops::array_init, TestMoveStoresOutOfLoops::array_check); |
|
305 |
|
306 if (!test.success) { |
|
307 throw new RuntimeException("Some tests failed"); |
|
308 } |
|
309 } |
|
310 } |