1 /*
2  * Copyright (c) 2020, 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 8240227
27  * @summary Test different cases of overunrolling the main loop of unswitched loops (pre/main/post) which are then not entered.
28  * @run main/othervm -XX:CompileCommand=compileonly,compiler.loopopts.TestUnswitchOverunrolling::test*
29  *                   -Xcomp -Xbatch -XX:-TieredCompilation compiler.loopopts.TestUnswitchOverunrolling
30  * @run main/othervm -XX:CompileCommand=compileonly,compiler.loopopts.TestUnswitchOverunrolling::*
31  *                   -Xcomp -Xbatch -XX:-TieredCompilation compiler.loopopts.TestUnswitchOverunrolling
32  */
33 
34 package compiler.loopopts;
35 
36 public class TestUnswitchOverunrolling {
37 
38     public static int v = 1;
39     public static int w = 2;
40     public static int x = 3;
41     public static int y = 4;
42     public static int z = 5;
43 
44     // The inner for-loop is unswitched and pre-main-post loops are created for both unswitched loop versions.
45     // Afterwards, both main loops are over-unrolled and vectorized resulting in a crash in the matcher because
46     // the memory input to a vector is top.
test(int[] array)47     public static int test(int[] array) {
48         int result = 0;
49         int[] iArr = new int[8];
50         for (int i = 0; i < array.length; i++) {
51             for (int j = 5; j < i; j++) {
52                 if (x == 42) {
53                     y = 34;
54                 }
55                 iArr[j] += array[j];
56                 result += array[j];
57             }
58         }
59         return result;
60     }
61 
62     // Test with additional null check predicates for objects
test2(int[] array, A a, A a2)63     public static int test2(int[] array, A a, A a2) {
64         int result = 0;
65         int[] iArr = new int[8];
66         for (int i = 0; i < array.length; i++) {
67             for (int j = 5; j < i; j++) {
68                 y = a2.iFld;
69                 if (x == 42) {
70                     y = 34;
71                 }
72                 z = a.iFld;
73                 iArr[j] += array[j];
74                 result += array[j];
75             }
76         }
77         return result;
78     }
79 
80     // Test with two conditions (unswitch twice) and additional null check predicates for objects
testUnswitchTwice(int[] array, A a, A a2, A a3)81     public static int testUnswitchTwice(int[] array, A a, A a2, A a3) {
82         int result = 0;
83         int[] iArr = new int[8];
84         for (int i = 0; i < array.length; i++) {
85             for (int j = 5; j < i; j++) {
86                 y = a2.iFld;
87                 if (x == 42) {
88                     y = 34;
89                 }
90                 z = a.iFld;
91                 if (w == 22) {
92                     y = 55;
93                 }
94                 v = a3.iFld;
95                 iArr[j] += array[j];
96                 result += array[j];
97             }
98         }
99         return result;
100     }
101 
102     // Test with three conditions (unswitch three times) and additional null check predicates for objects
testUnswitchThreeTimes(int[] array, A a, A a2, A a3)103     public static int testUnswitchThreeTimes(int[] array, A a, A a2, A a3) {
104         int result = 0;
105         int[] iArr = new int[8];
106         for (int i = 0; i < array.length; i++) {
107             for (int j = 5; j < i; j++) {
108                 y += a2.iFld;
109                 if (x == 42) {
110                     y = 34;
111                 }
112                 if (w == 22) {
113                     y = 55;
114                 }
115                 v = a3.iFld;
116                 if (z == 75) {
117                     y = 66;
118                 }
119                 y += a.iFld + a2.iFld + a3.iFld;
120                 iArr[j] += array[j];
121                 result += array[j];
122             }
123         }
124         return result;
125     }
126 
main(String args[])127     public static void main(String args[]) {
128         int[] array = new int[8];
129         for (int i = 0; i < array.length; i++) {
130             array[i] = i + 1;
131         }
132 
133         check(test(array), 1, 2, 3, 4, 5);
134         check(test2(array, new A(), new A()), 1, 2, 3, 6, 6);
135         check(testUnswitchTwice(array, new A(), new A(), new A()), 6, 2, 3, 6, 6);
136         check(testUnswitchThreeTimes(array, new A(), new A(), new A()), 6, 2, 3, 78, 6);
137 
138         for (int i = 0; i < array.length; i++) {
139             if (array[i] != i + 1) {
140                 throw new RuntimeException("array values should not change");
141             }
142         }
143     }
144 
check(int result, int expV, int expW, int expX, int expY, int expZ)145     public static void check(int result, int expV, int expW, int expX, int expY, int expZ) {
146         if (result != 19 || expV != v || expW != w || expX != x || expY != y || expZ != z) {
147             throw new RuntimeException("wrong execution");
148         }
149     }
150 }
151 
152 class A {
153     int iFld = 6;
154 }
155 
156