Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/compiler/loopopts/TestLoopPeeling.java
41149 views
1
/*
2
* Copyright (c) 2017, 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 8078262 8177095
27
* @summary Tests correct dominator information after loop peeling.
28
*
29
* @run main/othervm -Xcomp
30
* -XX:CompileCommand=compileonly,compiler.loopopts.TestLoopPeeling::test*
31
* compiler.loopopts.TestLoopPeeling
32
*/
33
34
package compiler.loopopts;
35
36
public class TestLoopPeeling {
37
38
public int[] array = new int[100];
39
40
public static void main(String args[]) {
41
TestLoopPeeling test = new TestLoopPeeling();
42
try {
43
test.testArrayAccess1(0, 1);
44
test.testArrayAccess2(0);
45
test.testArrayAccess3(0, false);
46
test.testArrayAllocation(0, 1);
47
} catch (Exception e) {
48
// Ignore exceptions
49
}
50
}
51
52
public void testArrayAccess1(int index, int inc) {
53
int storeIndex = -1;
54
55
for (; index < 10; index += inc) {
56
// This loop invariant check triggers loop peeling because it can
57
// be moved out of the loop (see 'IdealLoopTree::policy_peeling').
58
if (inc == 42) return;
59
60
// This loop variant usage of LShiftL( ConvI2L( Phi(storeIndex) ) )
61
// prevents the split if optimization that would otherwise clone the
62
// LShiftL and ConvI2L nodes and assign them to their corresponding array
63
// address computation (see 'PhaseIdealLoop::split_if_with_blocks_post').
64
if (storeIndex > 0 && array[storeIndex] == 42) return;
65
66
if (index == 42) {
67
// This store and the corresponding range check are moved out of the
68
// loop and both used after main loop and the peeled iteration exit.
69
// For the peeled iteration, storeIndex is always -1 and the ConvI2L
70
// is replaced by TOP. However, the range check is not folded because
71
// we don't do the split if optimization in PhaseIdealLoop2.
72
// As a result, we have a (dead) control path from the peeled iteration
73
// to the StoreI but the data path is removed.
74
array[storeIndex] = 1;
75
return;
76
}
77
78
storeIndex++;
79
}
80
}
81
82
public int testArrayAccess2(int index) {
83
// Load1 and the corresponding range check are moved out of the loop
84
// and both are used after the main loop and the peeled iteration exit.
85
// For the peeled iteration, storeIndex is always Integer.MIN_VALUE and
86
// for the main loop it is 0. Hence, the merging phi has type int:<=0.
87
// Load1 reads the array at index ConvI2L(CastII(AddI(storeIndex, -1)))
88
// where the CastII is range check dependent and has type int:>=0.
89
// The CastII gets pushed through the AddI and its type is changed to int:>=1
90
// which does not overlap with the input type of storeIndex (int:<=0).
91
// The CastII is replaced by TOP causing a cascade of other eliminations.
92
// Since the control path through the range check CmpU(AddI(storeIndex, -1))
93
// is not eliminated, the graph is in a corrupted state. We fail once we merge
94
// with the result of Load2 because we get data from a non-dominating region.
95
int storeIndex = Integer.MIN_VALUE;
96
for (; index < 10; ++index) {
97
if (index == 42) {
98
return array[storeIndex-1]; // Load1
99
}
100
storeIndex = 0;
101
}
102
return array[42]; // Load2
103
}
104
105
public int testArrayAccess3(int index, boolean b) {
106
// Same as testArrayAccess2 but manifests as crash in register allocator.
107
int storeIndex = Integer.MIN_VALUE;
108
for (; index < 10; ++index) {
109
if (b) {
110
return 0;
111
}
112
if (index == 42) {
113
return array[storeIndex-1]; // Load1
114
}
115
storeIndex = 0;
116
}
117
return array[42]; // Load2
118
}
119
120
public byte[] testArrayAllocation(int index, int inc) {
121
int allocationCount = -1;
122
byte[] result;
123
124
for (; index < 10; index += inc) {
125
// This loop invariant check triggers loop peeling because it can
126
// be moved out of the loop (see 'IdealLoopTree::policy_peeling').
127
if (inc == 42) return null;
128
129
if (index == 42) {
130
// This allocation and the corresponding size check are moved out of the
131
// loop and both used after main loop and the peeled iteration exit.
132
// For the peeled iteration, allocationCount is always -1 and the ConvI2L
133
// is replaced by TOP. However, the size check is not folded because
134
// we don't do the split if optimization in PhaseIdealLoop2.
135
// As a result, we have a (dead) control path from the peeled iteration
136
// to the allocation but the data path is removed.
137
result = new byte[allocationCount];
138
return result;
139
}
140
141
allocationCount++;
142
}
143
return null;
144
}
145
}
146
147
148