1 /*
2  * Copyright (c) 2017, Red Hat, Inc. 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 8191887
27  * @summary loop cloning misses support for Opaque4 node
28  * @modules java.base/jdk.internal.misc:+open
29  *
30  * @run main/othervm -XX:-BackgroundCompilation TestLoopUnswitching
31  *
32  */
33 
34 import jdk.internal.misc.Unsafe;
35 import java.lang.reflect.Field;
36 import java.util.Arrays;
37 
38 public class TestLoopUnswitching {
39 
40     static final jdk.internal.misc.Unsafe UNSAFE = Unsafe.getUnsafe();
41     static final long F_OFFSET;
42 
43     static class A {
44         int f;
A(int f)45         A(int f) {
46             this.f = f;
47         }
48     }
49 
50     static {
51         try {
52             Field fField = A.class.getDeclaredField("f");
53             F_OFFSET = UNSAFE.objectFieldOffset(fField);
54         } catch (Exception e) {
55             throw new RuntimeException(e);
56         }
57     }
58 
test1(A[] arr, boolean flag1, boolean flag2)59     static int test1(A[] arr, boolean flag1, boolean flag2) {
60         int res = 0;
61         for (int i = 0; i < 10; i++) {
62             A a = arr[i];
63             if (flag1) { // triggers unswitching
64                 res += UNSAFE.getInt(a, F_OFFSET);
65             }
66             if (flag2) {
67                 // Opaque4 node here is in the loop but If is out of the loop
68                 res += UNSAFE.getInt(a, F_OFFSET);
69                 break;
70             }
71             res += UNSAFE.getInt(a, F_OFFSET);
72         }
73         return res;
74     }
75 
test2(A[] arr, boolean flag1, boolean flag2)76     static int test2(A[] arr, boolean flag1, boolean flag2) {
77         int res = 0;
78         for (int i = 0; i < 10; i++) {
79             A a = arr[i];
80             if (flag1) { // triggers unswitching
81                 res += UNSAFE.getInt(a, F_OFFSET);
82             }
83             if (flag2) {
84                 // Opaque4 node here is out of the loop but Bool is in the the loop
85                 res += UNSAFE.getInt(a, F_OFFSET);
86                 break;
87             }
88             res += a.f;
89         }
90         return res;
91     }
92 
main(String[] args)93     static public void main(String[] args) {
94         A[] arr = new A[1000];
95         Arrays.fill(arr, new A(0x42));
96         for (int i = 0; i < 20000; i++) {
97             test1(arr, (i%2) == 0, (i%2) == 0);
98             test2(arr, (i%2) == 0, (i%2) == 0);
99         }
100     }
101 
102 }
103