Skip to content

Commit 8352e38

Browse files
committed
8273277: C2: Move conditional negation into rc_predicate
Backport-of: 710f496456d642c3e98d230270598f0b2dc75aba
1 parent 9700ded commit 8352e38

File tree

5 files changed

+84
-25
lines changed

5 files changed

+84
-25
lines changed

src/hotspot/share/opto/loopPredicate.cpp

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,7 @@ bool IdealLoopTree::is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, Invari
698698
BoolNode* PhaseIdealLoop::rc_predicate(IdealLoopTree *loop, Node* ctrl,
699699
int scale, Node* offset,
700700
Node* init, Node* limit, jint stride,
701-
Node* range, bool upper, bool &overflow) {
701+
Node* range, bool upper, bool &overflow, bool negate) {
702702
jint con_limit = (limit != NULL && limit->is_Con()) ? limit->get_int() : 0;
703703
jint con_init = init->is_Con() ? init->get_int() : 0;
704704
jint con_offset = offset->is_Con() ? offset->get_int() : 0;
@@ -824,7 +824,7 @@ BoolNode* PhaseIdealLoop::rc_predicate(IdealLoopTree *loop, Node* ctrl,
824824
cmp = new CmpUNode(max_idx_expr, range);
825825
}
826826
register_new_node(cmp, ctrl);
827-
BoolNode* bol = new BoolNode(cmp, BoolTest::lt);
827+
BoolNode* bol = new BoolNode(cmp, negate ? BoolTest::ge : BoolTest::lt);
828828
register_new_node(bol, ctrl);
829829

830830
if (TraceLoopPredicate) {
@@ -1191,36 +1191,26 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree *loop, ProjNode*
11911191
}
11921192
// If predicate expressions may overflow in the integer range, longs are used.
11931193
bool overflow = false;
1194+
bool negate = (proj->_con != predicate_proj->_con);
11941195

11951196
// Test the lower bound
1196-
BoolNode* lower_bound_bol = rc_predicate(loop, ctrl, scale, offset, init, limit, stride, rng, false, overflow);
1197-
// Negate test if necessary
1198-
bool negated = false;
1199-
if (proj->_con != predicate_proj->_con) {
1200-
lower_bound_bol = new BoolNode(lower_bound_bol->in(1), lower_bound_bol->_test.negate());
1201-
register_new_node(lower_bound_bol, ctrl);
1202-
negated = true;
1203-
}
1197+
BoolNode* lower_bound_bol = rc_predicate(loop, ctrl, scale, offset, init, limit, stride, rng, false, overflow, negate);
1198+
12041199
ProjNode* lower_bound_proj = create_new_if_for_predicate(predicate_proj, NULL, reason, overflow ? Op_If : iff->Opcode());
12051200
IfNode* lower_bound_iff = lower_bound_proj->in(0)->as_If();
12061201
_igvn.hash_delete(lower_bound_iff);
12071202
lower_bound_iff->set_req(1, lower_bound_bol);
1208-
if (TraceLoopPredicate) tty->print_cr("lower bound check if: %s %d ", negated ? " negated" : "", lower_bound_iff->_idx);
1203+
if (TraceLoopPredicate) tty->print_cr("lower bound check if: %s %d ", negate ? " negated" : "", lower_bound_iff->_idx);
12091204

12101205
// Test the upper bound
1211-
BoolNode* upper_bound_bol = rc_predicate(loop, lower_bound_proj, scale, offset, init, limit, stride, rng, true, overflow);
1212-
negated = false;
1213-
if (proj->_con != predicate_proj->_con) {
1214-
upper_bound_bol = new BoolNode(upper_bound_bol->in(1), upper_bound_bol->_test.negate());
1215-
register_new_node(upper_bound_bol, ctrl);
1216-
negated = true;
1217-
}
1206+
BoolNode* upper_bound_bol = rc_predicate(loop, lower_bound_proj, scale, offset, init, limit, stride, rng, true, overflow, negate);
1207+
12181208
ProjNode* upper_bound_proj = create_new_if_for_predicate(predicate_proj, NULL, reason, overflow ? Op_If : iff->Opcode());
12191209
assert(upper_bound_proj->in(0)->as_If()->in(0) == lower_bound_proj, "should dominate");
12201210
IfNode* upper_bound_iff = upper_bound_proj->in(0)->as_If();
12211211
_igvn.hash_delete(upper_bound_iff);
12221212
upper_bound_iff->set_req(1, upper_bound_bol);
1223-
if (TraceLoopPredicate) tty->print_cr("upper bound check if: %s %d ", negated ? " negated" : "", lower_bound_iff->_idx);
1213+
if (TraceLoopPredicate) tty->print_cr("upper bound check if: %s %d ", negate ? " negated" : "", lower_bound_iff->_idx);
12241214

12251215
// Fall through into rest of the clean up code which will move
12261216
// any dependent nodes onto the upper bound test.
@@ -1266,10 +1256,10 @@ ProjNode* PhaseIdealLoop::insert_initial_skeleton_predicate(IfNode* iff, IdealLo
12661256
Node* rng, bool &overflow,
12671257
Deoptimization::DeoptReason reason) {
12681258
// First predicate for the initial value on first loop iteration
1269-
assert(proj->_con && predicate_proj->_con, "not a range check?");
12701259
Node* opaque_init = new OpaqueLoopInitNode(C, init);
12711260
register_new_node(opaque_init, upper_bound_proj);
1272-
BoolNode* bol = rc_predicate(loop, upper_bound_proj, scale, offset, opaque_init, limit, stride, rng, (stride > 0) != (scale > 0), overflow);
1261+
bool negate = (proj->_con != predicate_proj->_con);
1262+
BoolNode* bol = rc_predicate(loop, upper_bound_proj, scale, offset, opaque_init, limit, stride, rng, (stride > 0) != (scale > 0), overflow, negate);
12731263
Node* opaque_bol = new Opaque4Node(C, bol, _igvn.intcon(1)); // This will go away once loop opts are over
12741264
register_new_node(opaque_bol, upper_bound_proj);
12751265
ProjNode* new_proj = create_new_if_for_predicate(predicate_proj, NULL, reason, overflow ? Op_If : iff->Opcode());
@@ -1286,7 +1276,7 @@ ProjNode* PhaseIdealLoop::insert_initial_skeleton_predicate(IfNode* iff, IdealLo
12861276
register_new_node(max_value, new_proj);
12871277
max_value = new AddINode(opaque_init, max_value);
12881278
register_new_node(max_value, new_proj);
1289-
bol = rc_predicate(loop, new_proj, scale, offset, max_value, limit, stride, rng, (stride > 0) != (scale > 0), overflow);
1279+
bol = rc_predicate(loop, new_proj, scale, offset, max_value, limit, stride, rng, (stride > 0) != (scale > 0), overflow, negate);
12901280
opaque_bol = new Opaque4Node(C, bol, _igvn.intcon(1));
12911281
register_new_node(opaque_bol, new_proj);
12921282
new_proj = create_new_if_for_predicate(predicate_proj, NULL, reason, overflow ? Op_If : iff->Opcode());

src/hotspot/share/opto/loopTransform.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2419,7 +2419,7 @@ Node* PhaseIdealLoop::add_range_check_predicate(IdealLoopTree* loop, CountedLoop
24192419
Node* predicate_proj, int scale_con, Node* offset,
24202420
Node* limit, jint stride_con, Node* value) {
24212421
bool overflow = false;
2422-
BoolNode* bol = rc_predicate(loop, predicate_proj, scale_con, offset, value, NULL, stride_con, limit, (stride_con > 0) != (scale_con > 0), overflow);
2422+
BoolNode* bol = rc_predicate(loop, predicate_proj, scale_con, offset, value, NULL, stride_con, limit, (stride_con > 0) != (scale_con > 0), overflow, false);
24232423
Node* opaque_bol = new Opaque4Node(C, bol, _igvn.intcon(1));
24242424
register_new_node(opaque_bol, predicate_proj);
24252425
IfNode* new_iff = NULL;

src/hotspot/share/opto/loopnode.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1105,7 +1105,8 @@ class PhaseIdealLoop : public PhaseTransform {
11051105
BoolNode* rc_predicate(IdealLoopTree *loop, Node* ctrl,
11061106
int scale, Node* offset,
11071107
Node* init, Node* limit, jint stride,
1108-
Node* range, bool upper, bool &overflow);
1108+
Node* range, bool upper, bool &overflow,
1109+
bool negate);
11091110

11101111
// Implementation of the loop predication to promote checks outside the loop
11111112
bool loop_predication_impl(IdealLoopTree *loop);
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
3+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation.
9+
*
10+
* This code is distributed in the hope that it will be useful, but WITHOUT
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
* version 2 for more details (a copy is included in the LICENSE file that
14+
* accompanied this code).
15+
*
16+
* You should have received a copy of the GNU General Public License version
17+
* 2 along with this work; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19+
*
20+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21+
* or visit www.oracle.com if you need additional information or have any
22+
* questions.
23+
*/
24+
25+
/**
26+
* @test
27+
* @bug 8273277
28+
* @summary Skeleton predicates sometimes need to be negated
29+
* @run main compiler.loopopts.TestSkeletonPredicateNegation
30+
*
31+
*/
32+
33+
package compiler.loopopts;
34+
35+
public class TestSkeletonPredicateNegation {
36+
public static int in0 = 2;
37+
38+
public static void main(String[] args) {
39+
try {
40+
TestSkeletonPredicateNegation instance = new TestSkeletonPredicateNegation();
41+
for (int i = 0; i < 10000; ++i) {
42+
instance.mainTest(args);
43+
}
44+
} catch (Exception ex) {
45+
System.out.println(ex.getClass().getCanonicalName());
46+
} catch (OutOfMemoryError e) {
47+
System.out.println("OOM Error");
48+
}
49+
}
50+
51+
public void mainTest (String[] args){
52+
long loa11[] = new long[1987];
53+
54+
for (long lo14 : loa11) {
55+
TestSkeletonPredicateNegation.in0 = -128;
56+
for (int i18 = 0; i18 < 52; i18++) {
57+
try {
58+
loa11[TestSkeletonPredicateNegation.in0] %= 2275269548L;
59+
Math.ceil(1374905370.2785515599);
60+
} catch (Exception a_e) {
61+
TestSkeletonPredicateNegation.in0--;
62+
}
63+
}
64+
}
65+
}
66+
}

test/hotspot/jtreg/vmTestbase/jit/t/t105/t105.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,17 @@
2323

2424
/*
2525
* @test
26+
* @bug 8273277
2627
*
2728
* @summary converted from VM Testbase jit/t/t105.
2829
* VM Testbase keywords: [jit, quick]
2930
*
3031
* @library /vmTestbase
3132
* /test/lib
3233
* @run main/othervm -XX:-OmitStackTraceInFastThrow jit.t.t105.t105
34+
* @run main/othervm -XX:-OmitStackTraceInFastThrow -Xbatch -XX:Tier0BackedgeNotifyFreqLog=0 -XX:Tier2BackedgeNotifyFreqLog=0 -XX:Tier3BackedgeNotifyFreqLog=0 -XX:Tier2BackEdgeThreshold=1 -XX:Tier3BackEdgeThreshold=1 -XX:Tier4BackEdgeThreshold=1 jit.t.t105.t105
3335
*
34-
* This test must be run with ProfileTraps disabled to avoid preallocated
36+
* This test must be run with OmitStackTraceInFastThrow disabled to avoid preallocated
3537
* exceptions. They don't have the detailed message that this test relies on.
3638
*/
3739

0 commit comments

Comments
 (0)