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 }