diff --git a/src/hotspot/share/opto/loopPredicate.cpp b/src/hotspot/share/opto/loopPredicate.cpp index a81939876a3..178948ae2a2 100644 --- a/src/hotspot/share/opto/loopPredicate.cpp +++ b/src/hotspot/share/opto/loopPredicate.cpp @@ -816,7 +816,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; @@ -942,7 +942,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) { @@ -1309,36 +1309,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. @@ -1384,10 +1374,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 C->add_skeleton_predicate_opaq(opaque_bol); register_new_node(opaque_bol, upper_bound_proj); @@ -1405,7 +1395,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)); C->add_skeleton_predicate_opaq(opaque_bol); register_new_node(opaque_bol, new_proj); diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 2b5d747c19a..35398b68a30 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -2555,7 +2555,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; diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index 15a55408314..bd4200aa17a 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -1303,7 +1303,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); diff --git a/test/hotspot/jtreg/compiler/loopopts/TestSkeletonPredicateNegation.java b/test/hotspot/jtreg/compiler/loopopts/TestSkeletonPredicateNegation.java new file mode 100644 index 00000000000..cbb82a07ea0 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestSkeletonPredicateNegation.java @@ -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--; + } + } + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/jit/t/t105/t105.java b/test/hotspot/jtreg/vmTestbase/jit/t/t105/t105.java index 6cdb615852f..7b24ed2fec9 100644 --- a/test/hotspot/jtreg/vmTestbase/jit/t/t105/t105.java +++ b/test/hotspot/jtreg/vmTestbase/jit/t/t105/t105.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8273277 * * @summary converted from VM Testbase jit/t/t105. * VM Testbase keywords: [jit, quick] @@ -30,8 +31,9 @@ * @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. */