Skip to content

Commit f5a582c

Browse files
committed
8257575: C2: "failed: only phis" assert failure in loop strip mining verification
Reviewed-by: thartmann, neliasso
1 parent d05401d commit f5a582c

File tree

2 files changed

+175
-1
lines changed

2 files changed

+175
-1
lines changed

src/hotspot/share/opto/loopnode.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1792,12 +1792,28 @@ void LoopNode::verify_strip_mined(int expect_skeleton) const {
17921792
} else {
17931793
assert(expect_skeleton == 0 || expect_skeleton == -1, "no skeleton node?");
17941794
uint phis = 0;
1795+
uint be_loads = 0;
1796+
Node* be = inner->in(LoopNode::LoopBackControl);
17951797
for (DUIterator_Fast imax, i = inner->fast_outs(imax); i < imax; i++) {
17961798
Node* u = inner->fast_out(i);
17971799
if (u->is_Phi()) {
17981800
phis++;
1801+
for (DUIterator_Fast jmax, j = be->fast_outs(jmax); j < jmax; j++) {
1802+
Node* n = be->fast_out(j);
1803+
if (n->is_Load()) {
1804+
assert(n->in(0) == be, "should be on the backedge");
1805+
do {
1806+
n = n->raw_out(0);
1807+
} while (!n->is_Phi());
1808+
if (n == u) {
1809+
be_loads++;
1810+
break;
1811+
}
1812+
}
1813+
}
17991814
}
18001815
}
1816+
assert(be_loads <= phis, "wrong number phis that depends on a pinned load");
18011817
for (DUIterator_Fast imax, i = outer->fast_outs(imax); i < imax; i++) {
18021818
Node* u = outer->fast_out(i);
18031819
assert(u == outer || u == inner || u->is_Phi(), "nothing between inner and outer loop");
@@ -1809,7 +1825,9 @@ void LoopNode::verify_strip_mined(int expect_skeleton) const {
18091825
stores++;
18101826
}
18111827
}
1812-
assert(outer->outcnt() >= phis + 2 && outer->outcnt() <= phis + 2 + stores + 1, "only phis");
1828+
// Late optimization of loads on backedge can cause Phi of outer loop to be eliminated but Phi of inner loop is
1829+
// not guaranteed to be optimized out.
1830+
assert(outer->outcnt() >= phis + 2 - be_loads && outer->outcnt() <= phis + 2 + stores + 1, "only phis");
18131831
}
18141832
assert(sfpt->outcnt() == 1, "no data node");
18151833
assert(outer_tail->outcnt() == 1 || !has_skeleton, "no data node");
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/*
2+
* Copyright (c) 2020, 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 8257575
27+
* @summary C2: "failed: only phis" assert failure in loop strip mining verfication
28+
*
29+
* @run main/othervm -XX:LoopUnrollLimit=0 -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:CompileCommand=dontinline,TestEliminatedLoadPinnedOnBackedge::notInlined
30+
* -XX:CompileCommand=inline,TestEliminatedLoadPinnedOnBackedge::inlined TestEliminatedLoadPinnedOnBackedge
31+
*
32+
*/
33+
34+
public class TestEliminatedLoadPinnedOnBackedge {
35+
private static Object field2;
36+
37+
final static int iters = 2000;
38+
39+
public static void main(String[] args) {
40+
boolean[] flags = new boolean[iters];
41+
for (int i = 0; i < iters; i++) {
42+
flags[i] = i < iters/2;
43+
}
44+
for (int i = 0; i < 20_000; i++) {
45+
test1(flags);
46+
test2(flags, 1);
47+
test3(flags);
48+
inlined(new Object(), 1);
49+
inlined(new Object(), 4);
50+
inlined2(42);
51+
inlined2(0x42);
52+
}
53+
}
54+
55+
static int field;
56+
57+
private static int test1(boolean[] flags) {
58+
int k = 2;
59+
for (; k < 4; k *= 2) {
60+
}
61+
int[] array = new int[10];
62+
notInlined(array);
63+
// This load commons with the load on the backedge after the
64+
// outer strip mined loop is expanded.
65+
int v = array[0];
66+
array[1] = 42;
67+
// No use for o. Allocation removed at macro expansion time.
68+
Object o = new Object();
69+
inlined(o, k);
70+
int i = 0;
71+
for (; ; ) {
72+
synchronized (array) {
73+
}
74+
if (i >= iters) {
75+
break;
76+
}
77+
v = array[0]; // This load ends up on the backedge
78+
if (flags[i]) {
79+
inlined2(array[1]);
80+
}
81+
i++;
82+
}
83+
return v;
84+
}
85+
86+
private static int test2(boolean[] flags, int d) {
87+
int k = 2;
88+
for (; k < 4; k *= 2) {
89+
}
90+
int[] array = new int[10];
91+
notInlined(array);
92+
int v = array[0];
93+
array[1] = 42;
94+
Object o = new Object();
95+
inlined(o, k);
96+
int i = 0;
97+
for (; ; ) {
98+
synchronized (array) {
99+
}
100+
if (d == 0) {}
101+
if (i >= iters) {
102+
break;
103+
}
104+
v = (array[0] + array[2]) / d;
105+
if (flags[i]) {
106+
inlined2(array[1]);
107+
}
108+
i++;
109+
}
110+
return v;
111+
}
112+
113+
private static int test3(boolean[] flags) {
114+
int k = 2;
115+
for (; k < 4; k *= 2) {
116+
}
117+
int[] array = new int[10];
118+
notInlined(array);
119+
int v1 = array[0];
120+
int v2 = array[2];
121+
array[1] = 42;
122+
Object o = new Object();
123+
inlined(o, k);
124+
int i = 0;
125+
for (; ; ) {
126+
synchronized (array) {
127+
}
128+
if (i >= iters) {
129+
break;
130+
}
131+
v1 = array[0];
132+
v2 = array[2];
133+
if (flags[i]) {
134+
inlined2(array[1]);
135+
}
136+
i++;
137+
}
138+
return v1 + v2;
139+
}
140+
141+
private static void inlined2(int i) {
142+
if (i != 42) {
143+
field = 42;
144+
}
145+
}
146+
147+
private static void inlined(Object o, int i) {
148+
if (i != 4) {
149+
field2 = o;
150+
}
151+
}
152+
153+
private static void notInlined(int[] array) {
154+
java.util.Arrays.fill(array, 1);
155+
}
156+
}

0 commit comments

Comments
 (0)