1 /*
2  * Copyright (c) 2016, 2018, 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  * @test
26  * @bug 8159016 8202949 8203915
27  * @summary Tests correct dominator information after over-unrolling a loop.
28  * @requires vm.gc == "Parallel" | vm.gc == "null"
29  * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
30  *                   -Xcomp -XX:-TieredCompilation -XX:-UseSwitchProfiling
31  *                   -XX:-UseCountedLoopSafepoints -XX:LoopUnrollLimit=250
32  *                   -XX:-UseG1GC -XX:+UseParallelGC compiler.loopopts.TestOverunrolling
33  */
34 
35 package compiler.loopopts;
36 
37 public class TestOverunrolling {
38 
test1(int arg)39     public static Object test1(int arg) {
40         Object arr[] = new Object[3];
41         int lim = (arg & 3);
42         // The pre loop is executed for one iteration, initializing p[0].
43         // The main loop is unrolled twice, initializing p[1], p[2], p[3] and p[4].
44         // The p[3] and p[4] stores are always out of bounds and removed. However,
45         // C2 is unable to remove the "over-unrolled", dead main loop. As a result,
46         // there is a control path from the main loop to the post loop without a
47         // memory path (because the last store was replaced by TOP). We crash
48         // because we use a memory edge from a non-dominating region.
49         for (int i = 0; i < lim; ++i) {
50             arr[i] = new Object();
51         }
52         // Avoid EA
53         return arr;
54     }
55 
56     public static long lFld = 0;
57     public static volatile double dFld = 0;
58 
test2()59     public static void test2() {
60         int iArr[] = new int[10];
61         // The inner for-loop is overunrolled because we fail to determine
62         // the constant lower and upper bound (6,8]. After unrolling multiple times,
63         // the range check dependent CastII/ConvI2L emitted for the iArr access become
64         // TOP because index 'j' is out of bounds. As a result, the memory graph is
65         // corrupted with memory consuming nodes still being reachable because the dead
66         // loop is not (yet) removed (Opaque1 nodes are still guarding the bounds).
67         for (int i = 6; i < 10; i++) {
68             for (int j = 8; j > i; j--) {
69                 int k = 1;
70                 do {
71                     iArr[j] = 0;
72                     switch (k) {
73                     case 1:
74                         lFld = 0;
75                         break;
76                     case 10:
77                         dFld = 0;
78                         break;
79                     }
80                 } while (++k < 1);
81             }
82         }
83     }
84 
85     // Similar to test2 but we cannot statically determine the upper bound of
86     // the inner for loop and can therefore not prevent over-unrolling.
test3(int[] array)87     public static void test3(int[] array) {
88         int[] iArr = new int[8];
89         for (int i = 0; i < array.length; i++) {
90             for (int j = 5; j < i; j++) {
91                 int k = 1;
92                 do {
93                     iArr[j] = 0;
94                     switch (k) {
95                     case 1:
96                         lFld = 0;
97                         break;
98                     case 10:
99                         dFld = 0;
100                         break;
101                     }
102                 } while (++k < 1);
103             }
104         }
105     }
106 
107     // Similar to test3 but with negative stride and constant outer loop limit
test4(int[] array, boolean store)108     public static void test4(int[] array, boolean store) {
109         int[] iArr = new int[8];
110         for (int i = -8; i < 8; i++) {
111             for (int j = 5; j > i; j--) {
112                 int k = 1;
113                 do {
114                     if (store) {
115                         iArr[j] = 0;
116                     }
117                     switch (k) {
118                     case 1:
119                         lFld = 0;
120                         break;
121                     case 10:
122                         dFld = 0;
123                         break;
124                     }
125                 } while (++k < 1);
126             }
127         }
128     }
129 
130     // The inner for-loop is over-unrolled and vectorized resulting in
131     // a crash in the matcher because the memory input to a vector is top.
test5(int[] array)132     public static int test5(int[] array) {
133         int result = 0;
134         int[] iArr = new int[8];
135         for (int i = 0; i < array.length; i++) {
136             for (int j = 5; j < i; j++) {
137                 iArr[j] += array[j];
138                 result += array[j];
139             }
140         }
141         return result;
142     }
143 
main(String args[])144     public static void main(String args[]) {
145         for (int i = 0; i < 42; ++i) {
146             test1(i);
147         }
148         test2();
149         int[] array = new int[8];
150         test3(array);
151         test4(array, false);
152         test5(array);
153     }
154 }
155 
156