Skip to content

Commit 2db9ea9

Browse files
committedNov 16, 2023
8317723: C2: CountedLoopEndNodes and Zero Trip Guards are wrongly treated as Runtime Predicate
Reviewed-by: thartmann, epeter
1 parent eaa4417 commit 2db9ea9

File tree

5 files changed

+127
-1
lines changed

5 files changed

+127
-1
lines changed
 

‎src/hotspot/share/opto/cfgnode.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ class IfNode : public MultiBranchNode {
431431
Node* fold_compares(PhaseIterGVN* phase);
432432
static Node* up_one_dom(Node* curr, bool linear_only = false);
433433
Node* dominated_by(Node* prev_dom, PhaseIterGVN* igvn);
434+
bool is_zero_trip_guard() const;
434435

435436
// Takes the type of val and filters it through the test represented
436437
// by if_proj and returns a more refined type if one is produced.

‎src/hotspot/share/opto/ifnode.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -1774,6 +1774,13 @@ Node* IfProjNode::Identity(PhaseGVN* phase) {
17741774
return this;
17751775
}
17761776

1777+
bool IfNode::is_zero_trip_guard() const {
1778+
if (in(1)->is_Bool() && in(1)->in(1)->is_Cmp()) {
1779+
return in(1)->in(1)->in(1)->Opcode() == Op_OpaqueZeroTripGuard;
1780+
}
1781+
return false;
1782+
}
1783+
17771784
#ifndef PRODUCT
17781785
//------------------------------dump_spec--------------------------------------
17791786
void IfNode::dump_spec(outputStream *st) const {

‎src/hotspot/share/opto/predicates.cpp

+15-1
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,26 @@ Deoptimization::DeoptReason RuntimePredicate::uncommon_trap_reason(IfProjNode* i
7777
}
7878

7979
bool RuntimePredicate::is_success_proj(Node* node, Deoptimization::DeoptReason deopt_reason) {
80-
if (node->is_IfProj() && !node->in(0)->is_ParsePredicate()) {
80+
if (may_be_runtime_predicate_if(node)) {
8181
return deopt_reason == uncommon_trap_reason(node->as_IfProj());
8282
} else {
8383
return false;
8484
}
8585
}
8686

87+
// A Runtime Predicate must have an If or a RangeCheck node, while the If should not be a zero trip guard check.
88+
bool RuntimePredicate::may_be_runtime_predicate_if(Node* node) {
89+
if (node->is_IfProj()) {
90+
const IfNode* if_node = node->in(0)->as_If();
91+
const int opcode_if = if_node->Opcode();
92+
if ((opcode_if == Op_If && !if_node->is_zero_trip_guard())
93+
|| opcode_if == Op_RangeCheck) {
94+
return true;
95+
}
96+
}
97+
return false;
98+
}
99+
87100
ParsePredicateIterator::ParsePredicateIterator(const Predicates& predicates) : _current_index(0) {
88101
const PredicateBlock* loop_limit_check_predicate_block = predicates.loop_limit_check_predicate_block();
89102
if (loop_limit_check_predicate_block->has_parse_predicate()) {
@@ -118,6 +131,7 @@ void PredicateBlock::verify_block() {
118131
const int opcode = next->Opcode();
119132
assert(next->is_IfProj() || opcode == Op_If || opcode == Op_RangeCheck,
120133
"Regular Predicates consist of an IfProj and an If or RangeCheck node");
134+
assert(opcode != Op_If || !next->as_If()->is_zero_trip_guard(), "should not be zero trip guard");
121135
next = next->in(0);
122136
}
123137
}

‎src/hotspot/share/opto/predicates.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ class ParsePredicate : public StackObj {
257257
// Utility class for queries on Runtime Predicates.
258258
class RuntimePredicate : public StackObj {
259259
static Deoptimization::DeoptReason uncommon_trap_reason(IfProjNode* if_proj);
260+
static bool may_be_runtime_predicate_if(Node* node);
260261

261262
public:
262263
static bool is_success_proj(Node* node, Deoptimization::DeoptReason deopt_reason);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
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 8317723
28+
* @library /test/lib
29+
* @summary Test that CountedLoopEndNodes and zero trip guard check If nodes are not treated as Runtime Predicates.
30+
* @run main/othervm -XX:-TieredCompilation -Xbatch
31+
* -XX:CompileCommand=compileonly,compiler.predicates.TestWrongRuntimePredicateDetection::test*
32+
* compiler.predicates.TestWrongRuntimePredicateDetection
33+
*/
34+
35+
package compiler.predicates;
36+
37+
public class TestWrongRuntimePredicateDetection {
38+
static int[] iArr = new int[50];
39+
static long instanceCount;
40+
static boolean bFld = true;
41+
static volatile byte byFld;
42+
static long[][] lArrFld;
43+
44+
45+
public static void main(String[] x) {
46+
for (int i = 0; i < 1000; i++) {
47+
testCountedLoopEndAsRuntimePredicate();
48+
}
49+
for (int i = 0; i < 10; i++) {
50+
testZeroTripGuardAsRuntimePredicate();
51+
}
52+
}
53+
54+
static void testCountedLoopEndAsRuntimePredicate() {
55+
int i22 = 7, i26, i28, i29 = 8, i31 = 1;
56+
float f4;
57+
do {
58+
for (int i = 0; i < 10000; i++) {
59+
if (bFld) {
60+
break;
61+
}
62+
instanceCount = byFld;
63+
}
64+
for (i26 = 4; 80 > i26; i26 += 2) ;
65+
} while (++i22 < 315);
66+
i28 = 6;
67+
while ((i28 -= 3) > 0) {
68+
for (f4 = i28; f4 < 53; f4++) {
69+
bFld = false;
70+
}
71+
instanceCount = i26;
72+
do {
73+
switch ((i26 >>> 1) % 2 * 5 + 6) {
74+
case 12:
75+
case 10:
76+
lArrFld[i31][1] = i29;
77+
}
78+
} while (++i31 < 53);
79+
}
80+
}
81+
82+
static void testZeroTripGuardAsRuntimePredicate() {
83+
int m;
84+
int a[] = new int[50];
85+
for (int j = 0; j < a.length; j++) {
86+
a[j] = j;
87+
}
88+
89+
for (int j = 4; j < 42; j++) {
90+
for (int k = 1; k < 5; k++) {
91+
iArr[1] = 34;
92+
switch (j % 4) {
93+
case 0:
94+
iArr = iArr;
95+
case 1:
96+
case 3:
97+
m = 3;
98+
}
99+
}
100+
}
101+
}
102+
103+
}

0 commit comments

Comments
 (0)
Please sign in to comment.