Skip to content

Commit

Permalink
8273277: C2: Move conditional negation into rc_predicate
Browse files Browse the repository at this point in the history
Backport-of: 710f496456d642c3e98d230270598f0b2dc75aba
  • Loading branch information
GoeLin committed Jan 26, 2022
1 parent 9700ded commit 8352e38
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 25 deletions.
34 changes: 12 additions & 22 deletions src/hotspot/share/opto/loopPredicate.cpp
Expand Up @@ -698,7 +698,7 @@ bool IdealLoopTree::is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, Invari
BoolNode* PhaseIdealLoop::rc_predicate(IdealLoopTree *loop, Node* ctrl,
int scale, Node* offset,
Node* init, Node* limit, jint stride,
Node* range, bool upper, bool &overflow) {
Node* range, bool upper, bool &overflow, bool negate) {
jint con_limit = (limit != NULL && limit->is_Con()) ? limit->get_int() : 0;
jint con_init = init->is_Con() ? init->get_int() : 0;
jint con_offset = offset->is_Con() ? offset->get_int() : 0;
Expand Down Expand Up @@ -824,7 +824,7 @@ BoolNode* PhaseIdealLoop::rc_predicate(IdealLoopTree *loop, Node* ctrl,
cmp = new CmpUNode(max_idx_expr, range);
}
register_new_node(cmp, ctrl);
BoolNode* bol = new BoolNode(cmp, BoolTest::lt);
BoolNode* bol = new BoolNode(cmp, negate ? BoolTest::ge : BoolTest::lt);
register_new_node(bol, ctrl);

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

// Test the lower bound
BoolNode* lower_bound_bol = rc_predicate(loop, ctrl, scale, offset, init, limit, stride, rng, false, overflow);
// Negate test if necessary
bool negated = false;
if (proj->_con != predicate_proj->_con) {
lower_bound_bol = new BoolNode(lower_bound_bol->in(1), lower_bound_bol->_test.negate());
register_new_node(lower_bound_bol, ctrl);
negated = true;
}
BoolNode* lower_bound_bol = rc_predicate(loop, ctrl, scale, offset, init, limit, stride, rng, false, overflow, negate);

ProjNode* lower_bound_proj = create_new_if_for_predicate(predicate_proj, NULL, reason, overflow ? Op_If : iff->Opcode());
IfNode* lower_bound_iff = lower_bound_proj->in(0)->as_If();
_igvn.hash_delete(lower_bound_iff);
lower_bound_iff->set_req(1, lower_bound_bol);
if (TraceLoopPredicate) tty->print_cr("lower bound check if: %s %d ", negated ? " negated" : "", lower_bound_iff->_idx);
if (TraceLoopPredicate) tty->print_cr("lower bound check if: %s %d ", negate ? " negated" : "", lower_bound_iff->_idx);

// Test the upper bound
BoolNode* upper_bound_bol = rc_predicate(loop, lower_bound_proj, scale, offset, init, limit, stride, rng, true, overflow);
negated = false;
if (proj->_con != predicate_proj->_con) {
upper_bound_bol = new BoolNode(upper_bound_bol->in(1), upper_bound_bol->_test.negate());
register_new_node(upper_bound_bol, ctrl);
negated = true;
}
BoolNode* upper_bound_bol = rc_predicate(loop, lower_bound_proj, scale, offset, init, limit, stride, rng, true, overflow, negate);

ProjNode* upper_bound_proj = create_new_if_for_predicate(predicate_proj, NULL, reason, overflow ? Op_If : iff->Opcode());
assert(upper_bound_proj->in(0)->as_If()->in(0) == lower_bound_proj, "should dominate");
IfNode* upper_bound_iff = upper_bound_proj->in(0)->as_If();
_igvn.hash_delete(upper_bound_iff);
upper_bound_iff->set_req(1, upper_bound_bol);
if (TraceLoopPredicate) tty->print_cr("upper bound check if: %s %d ", negated ? " negated" : "", lower_bound_iff->_idx);
if (TraceLoopPredicate) tty->print_cr("upper bound check if: %s %d ", negate ? " negated" : "", lower_bound_iff->_idx);

// Fall through into rest of the clean up code which will move
// any dependent nodes onto the upper bound test.
Expand Down Expand Up @@ -1266,10 +1256,10 @@ ProjNode* PhaseIdealLoop::insert_initial_skeleton_predicate(IfNode* iff, IdealLo
Node* rng, bool &overflow,
Deoptimization::DeoptReason reason) {
// First predicate for the initial value on first loop iteration
assert(proj->_con && predicate_proj->_con, "not a range check?");
Node* opaque_init = new OpaqueLoopInitNode(C, init);
register_new_node(opaque_init, upper_bound_proj);
BoolNode* bol = rc_predicate(loop, upper_bound_proj, scale, offset, opaque_init, limit, stride, rng, (stride > 0) != (scale > 0), overflow);
bool negate = (proj->_con != predicate_proj->_con);
BoolNode* bol = rc_predicate(loop, upper_bound_proj, scale, offset, opaque_init, limit, stride, rng, (stride > 0) != (scale > 0), overflow, negate);
Node* opaque_bol = new Opaque4Node(C, bol, _igvn.intcon(1)); // This will go away once loop opts are over
register_new_node(opaque_bol, upper_bound_proj);
ProjNode* new_proj = create_new_if_for_predicate(predicate_proj, NULL, reason, overflow ? Op_If : iff->Opcode());
Expand All @@ -1286,7 +1276,7 @@ ProjNode* PhaseIdealLoop::insert_initial_skeleton_predicate(IfNode* iff, IdealLo
register_new_node(max_value, new_proj);
max_value = new AddINode(opaque_init, max_value);
register_new_node(max_value, new_proj);
bol = rc_predicate(loop, new_proj, scale, offset, max_value, limit, stride, rng, (stride > 0) != (scale > 0), overflow);
bol = rc_predicate(loop, new_proj, scale, offset, max_value, limit, stride, rng, (stride > 0) != (scale > 0), overflow, negate);
opaque_bol = new Opaque4Node(C, bol, _igvn.intcon(1));
register_new_node(opaque_bol, new_proj);
new_proj = create_new_if_for_predicate(predicate_proj, NULL, reason, overflow ? Op_If : iff->Opcode());
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/opto/loopTransform.cpp
Expand Up @@ -2419,7 +2419,7 @@ Node* PhaseIdealLoop::add_range_check_predicate(IdealLoopTree* loop, CountedLoop
Node* predicate_proj, int scale_con, Node* offset,
Node* limit, jint stride_con, Node* value) {
bool overflow = false;
BoolNode* bol = rc_predicate(loop, predicate_proj, scale_con, offset, value, NULL, stride_con, limit, (stride_con > 0) != (scale_con > 0), overflow);
BoolNode* bol = rc_predicate(loop, predicate_proj, scale_con, offset, value, NULL, stride_con, limit, (stride_con > 0) != (scale_con > 0), overflow, false);
Node* opaque_bol = new Opaque4Node(C, bol, _igvn.intcon(1));
register_new_node(opaque_bol, predicate_proj);
IfNode* new_iff = NULL;
Expand Down
3 changes: 2 additions & 1 deletion src/hotspot/share/opto/loopnode.hpp
Expand Up @@ -1105,7 +1105,8 @@ class PhaseIdealLoop : public PhaseTransform {
BoolNode* rc_predicate(IdealLoopTree *loop, Node* ctrl,
int scale, Node* offset,
Node* init, Node* limit, jint stride,
Node* range, bool upper, bool &overflow);
Node* range, bool upper, bool &overflow,
bool negate);

// Implementation of the loop predication to promote checks outside the loop
bool loop_predication_impl(IdealLoopTree *loop);
Expand Down
@@ -0,0 +1,66 @@
/*
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

/**
* @test
* @bug 8273277
* @summary Skeleton predicates sometimes need to be negated
* @run main compiler.loopopts.TestSkeletonPredicateNegation
*
*/

package compiler.loopopts;

public class TestSkeletonPredicateNegation {
public static int in0 = 2;

public static void main(String[] args) {
try {
TestSkeletonPredicateNegation instance = new TestSkeletonPredicateNegation();
for (int i = 0; i < 10000; ++i) {
instance.mainTest(args);
}
} catch (Exception ex) {
System.out.println(ex.getClass().getCanonicalName());
} catch (OutOfMemoryError e) {
System.out.println("OOM Error");
}
}

public void mainTest (String[] args){
long loa11[] = new long[1987];

for (long lo14 : loa11) {
TestSkeletonPredicateNegation.in0 = -128;
for (int i18 = 0; i18 < 52; i18++) {
try {
loa11[TestSkeletonPredicateNegation.in0] %= 2275269548L;
Math.ceil(1374905370.2785515599);
} catch (Exception a_e) {
TestSkeletonPredicateNegation.in0--;
}
}
}
}
}
4 changes: 3 additions & 1 deletion test/hotspot/jtreg/vmTestbase/jit/t/t105/t105.java
Expand Up @@ -23,15 +23,17 @@

/*
* @test
* @bug 8273277
*
* @summary converted from VM Testbase jit/t/t105.
* VM Testbase keywords: [jit, quick]
*
* @library /vmTestbase
* /test/lib
* @run main/othervm -XX:-OmitStackTraceInFastThrow jit.t.t105.t105
* @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
*
* This test must be run with ProfileTraps disabled to avoid preallocated
* This test must be run with OmitStackTraceInFastThrow disabled to avoid preallocated
* exceptions. They don't have the detailed message that this test relies on.
*/

Expand Down

1 comment on commit 8352e38

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.