6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
Reviewed-by: kvn
This commit is contained in:
parent
72a7a6ffcf
commit
dac78c30b9
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -2088,29 +2088,41 @@ bool IdealLoopTree::is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, Invari
|
|||||||
BoolNode* PhaseIdealLoop::rc_predicate(Node* ctrl,
|
BoolNode* PhaseIdealLoop::rc_predicate(Node* ctrl,
|
||||||
int scale, Node* offset,
|
int scale, Node* offset,
|
||||||
Node* init, Node* limit, Node* stride,
|
Node* init, Node* limit, Node* stride,
|
||||||
Node* range) {
|
Node* range, bool upper) {
|
||||||
|
DEBUG_ONLY(ttyLocker ttyl);
|
||||||
|
if (TraceLoopPredicate) tty->print("rc_predicate ");
|
||||||
|
|
||||||
Node* max_idx_expr = init;
|
Node* max_idx_expr = init;
|
||||||
int stride_con = stride->get_int();
|
int stride_con = stride->get_int();
|
||||||
if ((stride_con > 0) == (scale > 0)) {
|
if ((stride_con > 0) == (scale > 0) == upper) {
|
||||||
max_idx_expr = new (C, 3) SubINode(limit, stride);
|
max_idx_expr = new (C, 3) SubINode(limit, stride);
|
||||||
register_new_node(max_idx_expr, ctrl);
|
register_new_node(max_idx_expr, ctrl);
|
||||||
|
if (TraceLoopPredicate) tty->print("(limit - stride) ");
|
||||||
|
} else {
|
||||||
|
if (TraceLoopPredicate) tty->print("init ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scale != 1) {
|
if (scale != 1) {
|
||||||
ConNode* con_scale = _igvn.intcon(scale);
|
ConNode* con_scale = _igvn.intcon(scale);
|
||||||
max_idx_expr = new (C, 3) MulINode(max_idx_expr, con_scale);
|
max_idx_expr = new (C, 3) MulINode(max_idx_expr, con_scale);
|
||||||
register_new_node(max_idx_expr, ctrl);
|
register_new_node(max_idx_expr, ctrl);
|
||||||
|
if (TraceLoopPredicate) tty->print("* %d ", scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset && (!offset->is_Con() || offset->get_int() != 0)){
|
if (offset && (!offset->is_Con() || offset->get_int() != 0)){
|
||||||
max_idx_expr = new (C, 3) AddINode(max_idx_expr, offset);
|
max_idx_expr = new (C, 3) AddINode(max_idx_expr, offset);
|
||||||
register_new_node(max_idx_expr, ctrl);
|
register_new_node(max_idx_expr, ctrl);
|
||||||
|
if (TraceLoopPredicate)
|
||||||
|
if (offset->is_Con()) tty->print("+ %d ", offset->get_int());
|
||||||
|
else tty->print("+ offset ");
|
||||||
}
|
}
|
||||||
|
|
||||||
CmpUNode* cmp = new (C, 3) CmpUNode(max_idx_expr, range);
|
CmpUNode* cmp = new (C, 3) CmpUNode(max_idx_expr, range);
|
||||||
register_new_node(cmp, ctrl);
|
register_new_node(cmp, ctrl);
|
||||||
BoolNode* bol = new (C, 2) BoolNode(cmp, BoolTest::lt);
|
BoolNode* bol = new (C, 2) BoolNode(cmp, BoolTest::lt);
|
||||||
register_new_node(bol, ctrl);
|
register_new_node(bol, ctrl);
|
||||||
|
|
||||||
|
if (TraceLoopPredicate) tty->print_cr("<u range");
|
||||||
return bol;
|
return bol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2187,7 +2199,6 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) {
|
|||||||
while (if_proj_list.size() > 0) {
|
while (if_proj_list.size() > 0) {
|
||||||
// Following are changed to nonnull when a predicate can be hoisted
|
// Following are changed to nonnull when a predicate can be hoisted
|
||||||
ProjNode* new_predicate_proj = NULL;
|
ProjNode* new_predicate_proj = NULL;
|
||||||
BoolNode* new_predicate_bol = NULL;
|
|
||||||
|
|
||||||
ProjNode* proj = if_proj_list.pop()->as_Proj();
|
ProjNode* proj = if_proj_list.pop()->as_Proj();
|
||||||
IfNode* iff = proj->in(0)->as_If();
|
IfNode* iff = proj->in(0)->as_If();
|
||||||
@ -2218,61 +2229,89 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) {
|
|||||||
// Invariant test
|
// Invariant test
|
||||||
new_predicate_proj = create_new_if_for_predicate(predicate_proj);
|
new_predicate_proj = create_new_if_for_predicate(predicate_proj);
|
||||||
Node* ctrl = new_predicate_proj->in(0)->as_If()->in(0);
|
Node* ctrl = new_predicate_proj->in(0)->as_If()->in(0);
|
||||||
new_predicate_bol = invar.clone(bol, ctrl)->as_Bool();
|
BoolNode* new_predicate_bol = invar.clone(bol, ctrl)->as_Bool();
|
||||||
if (TraceLoopPredicate) tty->print("invariant");
|
|
||||||
|
// Negate test if necessary
|
||||||
|
bool negated = false;
|
||||||
|
if (proj->_con != predicate_proj->_con) {
|
||||||
|
new_predicate_bol = new (C, 2) BoolNode(new_predicate_bol->in(1), new_predicate_bol->_test.negate());
|
||||||
|
register_new_node(new_predicate_bol, ctrl);
|
||||||
|
negated = true;
|
||||||
|
}
|
||||||
|
IfNode* new_predicate_iff = new_predicate_proj->in(0)->as_If();
|
||||||
|
_igvn.hash_delete(new_predicate_iff);
|
||||||
|
new_predicate_iff->set_req(1, new_predicate_bol);
|
||||||
|
if (TraceLoopPredicate) tty->print_cr("invariant if%s: %d", negated ? " negated" : "", new_predicate_iff->_idx);
|
||||||
|
|
||||||
} else if (cl != NULL && loop->is_range_check_if(iff, this, invar)) {
|
} else if (cl != NULL && loop->is_range_check_if(iff, this, invar)) {
|
||||||
// Range check (only for counted loops)
|
assert(proj->_con == predicate_proj->_con, "must match");
|
||||||
new_predicate_proj = create_new_if_for_predicate(predicate_proj);
|
|
||||||
Node *ctrl = new_predicate_proj->in(0)->as_If()->in(0);
|
// Range check for counted loops
|
||||||
const Node* cmp = bol->in(1)->as_Cmp();
|
const Node* cmp = bol->in(1)->as_Cmp();
|
||||||
Node* idx = cmp->in(1);
|
Node* idx = cmp->in(1);
|
||||||
assert(!invar.is_invariant(idx), "index is variant");
|
assert(!invar.is_invariant(idx), "index is variant");
|
||||||
assert(cmp->in(2)->Opcode() == Op_LoadRange, "must be");
|
assert(cmp->in(2)->Opcode() == Op_LoadRange, "must be");
|
||||||
LoadRangeNode* ld_rng = (LoadRangeNode*)cmp->in(2); // LoadRangeNode
|
Node* ld_rng = cmp->in(2); // LoadRangeNode
|
||||||
assert(invar.is_invariant(ld_rng), "load range must be invariant");
|
assert(invar.is_invariant(ld_rng), "load range must be invariant");
|
||||||
ld_rng = (LoadRangeNode*)invar.clone(ld_rng, ctrl);
|
|
||||||
int scale = 1;
|
int scale = 1;
|
||||||
Node* offset = zero;
|
Node* offset = zero;
|
||||||
bool ok = is_scaled_iv_plus_offset(idx, cl->phi(), &scale, &offset);
|
bool ok = is_scaled_iv_plus_offset(idx, cl->phi(), &scale, &offset);
|
||||||
assert(ok, "must be index expression");
|
assert(ok, "must be index expression");
|
||||||
|
|
||||||
|
Node* init = cl->init_trip();
|
||||||
|
Node* limit = cl->limit();
|
||||||
|
Node* stride = cl->stride();
|
||||||
|
|
||||||
|
// Build if's for the upper and lower bound tests. The
|
||||||
|
// lower_bound test will dominate the upper bound test and all
|
||||||
|
// cloned or created nodes will use the lower bound test as
|
||||||
|
// their declared control.
|
||||||
|
ProjNode* lower_bound_proj = create_new_if_for_predicate(predicate_proj);
|
||||||
|
ProjNode* upper_bound_proj = create_new_if_for_predicate(predicate_proj);
|
||||||
|
assert(upper_bound_proj->in(0)->as_If()->in(0) == lower_bound_proj, "should dominate");
|
||||||
|
Node *ctrl = lower_bound_proj->in(0)->as_If()->in(0);
|
||||||
|
|
||||||
|
// Perform cloning to keep Invariance state correct since the
|
||||||
|
// late schedule will place invariant things in the loop.
|
||||||
|
ld_rng = invar.clone(ld_rng, ctrl);
|
||||||
if (offset && offset != zero) {
|
if (offset && offset != zero) {
|
||||||
assert(invar.is_invariant(offset), "offset must be loop invariant");
|
assert(invar.is_invariant(offset), "offset must be loop invariant");
|
||||||
offset = invar.clone(offset, ctrl);
|
offset = invar.clone(offset, ctrl);
|
||||||
}
|
}
|
||||||
Node* init = cl->init_trip();
|
|
||||||
Node* limit = cl->limit();
|
|
||||||
Node* stride = cl->stride();
|
|
||||||
new_predicate_bol = rc_predicate(ctrl, scale, offset, init, limit, stride, ld_rng);
|
|
||||||
if (TraceLoopPredicate) tty->print("range check");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new_predicate_proj == NULL) {
|
// Test the lower bound
|
||||||
|
Node* lower_bound_bol = rc_predicate(ctrl, scale, offset, init, limit, stride, ld_rng, false);
|
||||||
|
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: %d", lower_bound_iff->_idx);
|
||||||
|
|
||||||
|
// Test the upper bound
|
||||||
|
Node* upper_bound_bol = rc_predicate(ctrl, scale, offset, init, limit, stride, ld_rng, true);
|
||||||
|
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: %d", lower_bound_iff->_idx);
|
||||||
|
|
||||||
|
// Fall through into rest of the clean up code which will move
|
||||||
|
// any dependent nodes onto the upper bound test.
|
||||||
|
new_predicate_proj = upper_bound_proj;
|
||||||
|
} else {
|
||||||
// The other proj of the "iff" is a uncommon trap projection, and we can assume
|
// The other proj of the "iff" is a uncommon trap projection, and we can assume
|
||||||
// the other proj will not be executed ("executed" means uct raised).
|
// the other proj will not be executed ("executed" means uct raised).
|
||||||
continue;
|
continue;
|
||||||
} else {
|
|
||||||
// Success - attach condition (new_predicate_bol) to predicate if
|
|
||||||
invar.map_ctrl(proj, new_predicate_proj); // so that invariance test can be appropriate
|
|
||||||
IfNode* new_iff = new_predicate_proj->in(0)->as_If();
|
|
||||||
|
|
||||||
// Negate test if necessary
|
|
||||||
if (proj->_con != predicate_proj->_con) {
|
|
||||||
new_predicate_bol = new (C, 2) BoolNode(new_predicate_bol->in(1), new_predicate_bol->_test.negate());
|
|
||||||
register_new_node(new_predicate_bol, new_iff->in(0));
|
|
||||||
if (TraceLoopPredicate) tty->print_cr(" if negated: %d", iff->_idx);
|
|
||||||
} else {
|
|
||||||
if (TraceLoopPredicate) tty->print_cr(" if: %d", iff->_idx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_igvn.hash_delete(new_iff);
|
// Success - attach condition (new_predicate_bol) to predicate if
|
||||||
new_iff->set_req(1, new_predicate_bol);
|
invar.map_ctrl(proj, new_predicate_proj); // so that invariance test can be appropriate
|
||||||
|
|
||||||
|
// Eliminate the old if in the loop body
|
||||||
_igvn.hash_delete(iff);
|
_igvn.hash_delete(iff);
|
||||||
iff->set_req(1, proj->is_IfFalse() ? cond_false : cond_true);
|
iff->set_req(1, proj->is_IfFalse() ? cond_false : cond_true);
|
||||||
|
|
||||||
Node* ctrl = new_predicate_proj; // new control
|
Node* ctrl = new_predicate_proj; // new control
|
||||||
ProjNode* dp = proj; // old control
|
ProjNode* dp = proj; // old control
|
||||||
assert(get_loop(dp) == loop, "guarenteed at the time of collecting proj");
|
assert(get_loop(dp) == loop, "guaranteed at the time of collecting proj");
|
||||||
// Find nodes (depends only on the test) off the surviving projection;
|
// Find nodes (depends only on the test) off the surviving projection;
|
||||||
// move them outside the loop with the control of proj_clone
|
// move them outside the loop with the control of proj_clone
|
||||||
for (DUIterator_Fast imax, i = dp->fast_outs(imax); i < imax; i++) {
|
for (DUIterator_Fast imax, i = dp->fast_outs(imax); i < imax; i++) {
|
||||||
@ -2295,7 +2334,6 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) {
|
|||||||
|
|
||||||
hoisted = true;
|
hoisted = true;
|
||||||
C->set_major_progress();
|
C->set_major_progress();
|
||||||
}
|
|
||||||
} // end while
|
} // end while
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
@ -821,7 +821,7 @@ public:
|
|||||||
BoolNode* rc_predicate(Node* ctrl,
|
BoolNode* rc_predicate(Node* ctrl,
|
||||||
int scale, Node* offset,
|
int scale, Node* offset,
|
||||||
Node* init, Node* limit, Node* stride,
|
Node* init, Node* limit, Node* stride,
|
||||||
Node* range);
|
Node* range, bool upper);
|
||||||
|
|
||||||
// Implementation of the loop predication to promote checks outside the loop
|
// Implementation of the loop predication to promote checks outside the loop
|
||||||
bool loop_predication_impl(IdealLoopTree *loop);
|
bool loop_predication_impl(IdealLoopTree *loop);
|
||||||
|
76
hotspot/test/compiler/6930043/Test6930043.java
Normal file
76
hotspot/test/compiler/6930043/Test6930043.java
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @bug 6930043
|
||||||
|
* @summary C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
|
||||||
|
*
|
||||||
|
* @run main Test6930043
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
public class Test6930043 {
|
||||||
|
int[] a;
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
public int loop_back(int i, int i_0_) {
|
||||||
|
int i_1_ = 0;
|
||||||
|
int[] is = a;
|
||||||
|
if (is == null) return 0;
|
||||||
|
for (int i_2_ = i; i_2_ >= i_0_; i_2_--)
|
||||||
|
i_1_ += is[idx = i_2_];
|
||||||
|
return i_1_;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int loop_forw(int start, int end) {
|
||||||
|
int result = 0;
|
||||||
|
int[] is = a;
|
||||||
|
if (is == null) return 0;
|
||||||
|
for (int index = start; index < end; index++)
|
||||||
|
result += is[index];
|
||||||
|
// result += is[idx = index];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] strings) {
|
||||||
|
Test6930043 var_Test6930043 = new Test6930043();
|
||||||
|
var_Test6930043.a = new int[1000000];
|
||||||
|
var_Test6930043.loop_forw(10, 999990);
|
||||||
|
var_Test6930043.loop_forw(10, 999990);
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
try {
|
||||||
|
if (var_Test6930043.loop_forw(-1, 999990) != 0) throw new InternalError();
|
||||||
|
} catch (ArrayIndexOutOfBoundsException e) { }
|
||||||
|
}
|
||||||
|
var_Test6930043.loop_back(999990, 10);
|
||||||
|
var_Test6930043.loop_back(999990, 10);
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
try {
|
||||||
|
if (var_Test6930043.loop_back(999990, -1) != 0) throw new InternalError();
|
||||||
|
} catch (ArrayIndexOutOfBoundsException e) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user