8324121: SIGFPE in PhaseIdealLoop::extract_long_range_checks
Reviewed-by: kvn, chagedorn
This commit is contained in:
parent
0c1b254be9
commit
cb2a671359
@ -792,13 +792,14 @@ bool PhaseIdealLoop::create_loop_nest(IdealLoopTree* loop, Node_List &old_new) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
jlong stride_con = head->stride_con();
|
jlong stride_con_long = head->stride_con();
|
||||||
assert(stride_con != 0, "missed some peephole opt");
|
assert(stride_con_long != 0, "missed some peephole opt");
|
||||||
// We can't iterate for more than max int at a time.
|
// We can't iterate for more than max int at a time.
|
||||||
if (stride_con != (jint)stride_con) {
|
if (stride_con_long != (jint)stride_con_long || stride_con_long == min_jint) {
|
||||||
assert(bt == T_LONG, "only for long loops");
|
assert(bt == T_LONG, "only for long loops");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
jint stride_con = checked_cast<jint>(stride_con_long);
|
||||||
// The number of iterations for the integer count loop: guarantee no
|
// The number of iterations for the integer count loop: guarantee no
|
||||||
// overflow: max_jint - stride_con max. -1 so there's no need for a
|
// overflow: max_jint - stride_con max. -1 so there's no need for a
|
||||||
// loop limit check if the exit test is <= or >=.
|
// loop limit check if the exit test is <= or >=.
|
||||||
@ -966,7 +967,7 @@ bool PhaseIdealLoop::create_loop_nest(IdealLoopTree* loop, Node_List &old_new) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clone the iv data nodes as an integer iv
|
// Clone the iv data nodes as an integer iv
|
||||||
Node* int_stride = _igvn.intcon(checked_cast<int>(stride_con));
|
Node* int_stride = _igvn.intcon(stride_con);
|
||||||
set_ctrl(int_stride, C->root());
|
set_ctrl(int_stride, C->root());
|
||||||
Node* inner_phi = new PhiNode(x->in(0), TypeInt::INT);
|
Node* inner_phi = new PhiNode(x->in(0), TypeInt::INT);
|
||||||
Node* inner_incr = new AddINode(inner_phi, int_stride);
|
Node* inner_incr = new AddINode(inner_phi, int_stride);
|
||||||
@ -1061,7 +1062,7 @@ bool PhaseIdealLoop::create_loop_nest(IdealLoopTree* loop, Node_List &old_new) {
|
|||||||
register_new_node(outer_phi, outer_head);
|
register_new_node(outer_phi, outer_head);
|
||||||
}
|
}
|
||||||
|
|
||||||
transform_long_range_checks(checked_cast<int>(stride_con), range_checks, outer_phi, inner_iters_actual_int,
|
transform_long_range_checks(stride_con, range_checks, outer_phi, inner_iters_actual_int,
|
||||||
inner_phi, iv_add, inner_head);
|
inner_phi, iv_add, inner_head);
|
||||||
// Peel one iteration of the loop and use the safepoint at the end
|
// Peel one iteration of the loop and use the safepoint at the end
|
||||||
// of the peeled iteration to insert Parse Predicates. If no well
|
// of the peeled iteration to insert Parse Predicates. If no well
|
||||||
@ -1098,7 +1099,7 @@ bool PhaseIdealLoop::create_loop_nest(IdealLoopTree* loop, Node_List &old_new) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PhaseIdealLoop::extract_long_range_checks(const IdealLoopTree* loop, jlong stride_con, int iters_limit, PhiNode* phi,
|
int PhaseIdealLoop::extract_long_range_checks(const IdealLoopTree* loop, jint stride_con, int iters_limit, PhiNode* phi,
|
||||||
Node_List& range_checks) {
|
Node_List& range_checks) {
|
||||||
const jlong min_iters = 2;
|
const jlong min_iters = 2;
|
||||||
jlong reduced_iters_limit = iters_limit;
|
jlong reduced_iters_limit = iters_limit;
|
||||||
@ -1114,7 +1115,8 @@ int PhaseIdealLoop::extract_long_range_checks(const IdealLoopTree* loop, jlong s
|
|||||||
jlong scale = 0;
|
jlong scale = 0;
|
||||||
if (loop->is_range_check_if(if_proj, this, T_LONG, phi, range, offset, scale) &&
|
if (loop->is_range_check_if(if_proj, this, T_LONG, phi, range, offset, scale) &&
|
||||||
loop->is_invariant(range) && loop->is_invariant(offset) &&
|
loop->is_invariant(range) && loop->is_invariant(offset) &&
|
||||||
original_iters_limit / ABS(scale * stride_con) >= min_iters) {
|
original_iters_limit / ABS(scale) >= min_iters * ABS(stride_con)) {
|
||||||
|
assert(scale == (jint)scale, "scale should be an int");
|
||||||
reduced_iters_limit = MIN2(reduced_iters_limit, original_iters_limit/ABS(scale));
|
reduced_iters_limit = MIN2(reduced_iters_limit, original_iters_limit/ABS(scale));
|
||||||
range_checks.push(c);
|
range_checks.push(c);
|
||||||
}
|
}
|
||||||
|
@ -1710,8 +1710,8 @@ public:
|
|||||||
LoopNode* create_inner_head(IdealLoopTree* loop, BaseCountedLoopNode* head, IfNode* exit_test);
|
LoopNode* create_inner_head(IdealLoopTree* loop, BaseCountedLoopNode* head, IfNode* exit_test);
|
||||||
|
|
||||||
|
|
||||||
int extract_long_range_checks(const IdealLoopTree* loop, jlong stride_con, int iters_limit, PhiNode* phi,
|
int extract_long_range_checks(const IdealLoopTree* loop, jint stride_con, int iters_limit, PhiNode* phi,
|
||||||
Node_List &range_checks);
|
Node_List &range_checks);
|
||||||
|
|
||||||
void transform_long_range_checks(int stride_con, const Node_List &range_checks, Node* outer_phi,
|
void transform_long_range_checks(int stride_con, const Node_List &range_checks, Node* outer_phi,
|
||||||
Node* inner_iters_actual_int, Node* inner_phi,
|
Node* inner_iters_actual_int, Node* inner_phi,
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024, 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 8324121
|
||||||
|
* @summary SIGFPE in PhaseIdealLoop::extract_long_range_checks
|
||||||
|
* @run main/othervm -Xcomp -XX:CompileCommand=compileonly,TestLargeScaleInLongRCOverflow::test* -XX:-TieredCompilation TestLargeScaleInLongRCOverflow
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class TestLargeScaleInLongRCOverflow {
|
||||||
|
|
||||||
|
public static void main(String args[]) {
|
||||||
|
Objects.checkIndex(0, 1);
|
||||||
|
try {
|
||||||
|
test1();
|
||||||
|
} catch (java.lang.IndexOutOfBoundsException e) { }
|
||||||
|
try {
|
||||||
|
test2();
|
||||||
|
} catch (java.lang.IndexOutOfBoundsException e) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
// SIGFPE in PhaseIdealLoop::extract_long_range_checks
|
||||||
|
public static void test1() {
|
||||||
|
for (long i = 1; i < 100; i += 2) {
|
||||||
|
Objects.checkIndex(Long.MIN_VALUE * i, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// "assert(static_cast<T1>(result) == thing) failed: must be" in PhaseIdealLoop::transform_long_range_checks
|
||||||
|
public static void test2() {
|
||||||
|
for (long i = 1; i < 100; i += 2) {
|
||||||
|
Objects.checkIndex((Long.MIN_VALUE + 2) * i, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user