hotspot/test/compiler/loopopts/TestMoveStoresOutOfLoops.java
changeset 32372 b82e88dcb26c
child 33078 9452eb89c16d
equal deleted inserted replaced
32371:8815f2d1447f 32372:b82e88dcb26c
       
     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 }