Skip to content

Commit 7dbdad5

Browse files
committed
8308892: Bad graph detected in build_loop_late after JDK-8305635
Reviewed-by: rcastanedalo, roland, thartmann
1 parent dc8bc6c commit 7dbdad5

File tree

2 files changed

+97
-2
lines changed

2 files changed

+97
-2
lines changed

src/hotspot/share/opto/loopPredicate.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1835,6 +1835,9 @@ ParsePredicateNode* ParsePredicates::get_parse_predicate_or_null(Node* parse_pre
18351835
}
18361836

18371837
// Initialize the Parse Predicate projection field that matches the kind of the parent of `parse_predicate_proj`.
1838+
// Only initialize if Parse Predicate projection itself or any of the Parse Predicate projections coming further up
1839+
// in the graph are not already initialized (this would be a sign of repeated Parse Predicates which are not cleaned up,
1840+
// yet).
18381841
bool ParsePredicates::assign_predicate_proj(ParsePredicateSuccessProj* parse_predicate_proj) {
18391842
ParsePredicateNode* parse_predicate = get_parse_predicate_or_null(parse_predicate_proj);
18401843
assert(parse_predicate != nullptr, "must exist");
@@ -1847,13 +1850,16 @@ bool ParsePredicates::assign_predicate_proj(ParsePredicateSuccessProj* parse_pre
18471850
_loop_predicate_proj = parse_predicate_proj;
18481851
break;
18491852
case Deoptimization::DeoptReason::Reason_profile_predicate:
1850-
if (_profiled_loop_predicate_proj != nullptr) {
1853+
if (_profiled_loop_predicate_proj != nullptr ||
1854+
_loop_predicate_proj != nullptr) {
18511855
return false;
18521856
}
18531857
_profiled_loop_predicate_proj = parse_predicate_proj;
18541858
break;
18551859
case Deoptimization::DeoptReason::Reason_loop_limit_check:
1856-
if (_loop_limit_check_predicate_proj != nullptr) {
1860+
if (_loop_limit_check_predicate_proj != nullptr ||
1861+
_loop_predicate_proj != nullptr ||
1862+
_profiled_loop_predicate_proj != nullptr) {
18571863
return false;
18581864
}
18591865
_loop_limit_check_predicate_proj = parse_predicate_proj;
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* Copyright (c) 2023, 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+
/*
26+
* @test
27+
* @bug 8308892
28+
* @summary Test that Parse Predicates immediately following other Parse Predicates
29+
are cleaned up properly.
30+
* @run main/othervm -Xbatch compiler.predicates.TestWrongPredicateOrder
31+
*/
32+
33+
package compiler.predicates;
34+
35+
public class TestWrongPredicateOrder {
36+
static boolean flag;
37+
static int iFld = 0;
38+
static int iFld2 = 34;
39+
static int iArr[] = new int[1005];
40+
static int iArr2[] = new int[2];
41+
42+
43+
public static void main(String[] strArr) {
44+
// We will keep hitting the Profiled Loop Predicate for RC1 (Integer.MAX_VALUE - 1 - 3 > 1005) such that we will
45+
// not emit the Profile Loop Parse Predicate anymore. After that, we will also keep hitting the Loop Limit Check
46+
// Predicate (Interger.MAX_VALUE - 1 > Integer.MAX_VALUE - 2) such that we will also not emit the Loop Limit Check
47+
// Parse Predicate anymore. As a result, we'll only emit the Loop Parse Predicate in the next re-compilation.
48+
// In the next re-compilation, we'll hoist IC1 as Loop Predicate and IC2 as Profiled Loop Predicate.
49+
// They have a data dependency between them but this is normally okay because Profiled Loop Predicates are below
50+
// Loop Predicates in the graph. But due to the flipped order of Parse Predicates in this bug, we create the
51+
// Hoisted Predicates in the wrong order and we end up with a bad graph and assert.
52+
for (int i = 0; i < 10000; i++) {
53+
flag = !flag;
54+
test();
55+
}
56+
}
57+
58+
public static void test() {
59+
// Ensure to emit Loop Limit Check Predicate which is hit too often
60+
// -> no Loop Limit Check Parse Predicate is added in re-compilation anymore
61+
int limit = flag ? Integer.MAX_VALUE - 1 : 1000;
62+
63+
int i = 0;
64+
// Loop Limit Check Predicate: limit <= Integer.MAX_VALUE - stride + 1 = Integer.MAX_VALUE - 2
65+
while (i < limit) {
66+
i += 3;
67+
// Invariant check hoisted as Loop Predicate
68+
iArr2[iFld] = 1; // (IC1)
69+
70+
if (flag) {
71+
// Early exit -> enables Profiled Loop Predicate creation below
72+
return;
73+
}
74+
75+
// Invariant check hoisted as Profiled Loop Predicate
76+
// Data dependency on Loop Predicate for "iArr2[0] = 1"
77+
iArr2[1] = 5; // (IC2)
78+
79+
// Profiled Loop Predicate for range check hit too much -> no Profiled Loop Parse Predicate is added in
80+
// re-compilation anymore
81+
iArr[i] = 34; // (RC1)
82+
83+
if (iFld2 == 5555) {
84+
i++; // UCT -> ensures to emit Parse Predicates twice with an If in between that is folded after parsing
85+
}
86+
}
87+
}
88+
}
89+

0 commit comments

Comments
 (0)