提交 cb1cb002 编写于 作者: N never

6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I

Reviewed-by: kvn
上级 21200b6a
/* /*
* 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 ...@@ -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) { ...@@ -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,93 +2229,120 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) { ...@@ -2218,93 +2229,120 @@ 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);
new_iff->set_req(1, new_predicate_bol);
_igvn.hash_delete(iff);
iff->set_req(1, proj->is_IfFalse() ? cond_false : cond_true);
Node* ctrl = new_predicate_proj; // new control // Success - attach condition (new_predicate_bol) to predicate if
ProjNode* dp = proj; // old control invar.map_ctrl(proj, new_predicate_proj); // so that invariance test can be appropriate
assert(get_loop(dp) == loop, "guarenteed at the time of collecting proj");
// Find nodes (depends only on the test) off the surviving projection; // Eliminate the old if in the loop body
// move them outside the loop with the control of proj_clone _igvn.hash_delete(iff);
for (DUIterator_Fast imax, i = dp->fast_outs(imax); i < imax; i++) { iff->set_req(1, proj->is_IfFalse() ? cond_false : cond_true);
Node* cd = dp->fast_out(i); // Control-dependent node
if (cd->depends_only_on_test()) { Node* ctrl = new_predicate_proj; // new control
assert(cd->in(0) == dp, ""); ProjNode* dp = proj; // old control
_igvn.hash_delete(cd); assert(get_loop(dp) == loop, "guaranteed at the time of collecting proj");
cd->set_req(0, ctrl); // ctrl, not NULL // Find nodes (depends only on the test) off the surviving projection;
set_early_ctrl(cd); // move them outside the loop with the control of proj_clone
_igvn._worklist.push(cd); for (DUIterator_Fast imax, i = dp->fast_outs(imax); i < imax; i++) {
IdealLoopTree *new_loop = get_loop(get_ctrl(cd)); Node* cd = dp->fast_out(i); // Control-dependent node
if (new_loop != loop) { if (cd->depends_only_on_test()) {
if (!loop->_child) loop->_body.yank(cd); assert(cd->in(0) == dp, "");
if (!new_loop->_child ) new_loop->_body.push(cd); _igvn.hash_delete(cd);
} cd->set_req(0, ctrl); // ctrl, not NULL
--i; set_early_ctrl(cd);
--imax; _igvn._worklist.push(cd);
IdealLoopTree *new_loop = get_loop(get_ctrl(cd));
if (new_loop != loop) {
if (!loop->_child) loop->_body.yank(cd);
if (!new_loop->_child ) new_loop->_body.push(cd);
} }
--i;
--imax;
} }
hoisted = true;
C->set_major_progress();
} }
hoisted = true;
C->set_major_progress();
} // end while } // end while
#ifndef PRODUCT #ifndef PRODUCT
// report that the loop predication has been actually performed // report that the loop predication has been actually performed
// for this loop // for this loop
if (TraceLoopPredicate && hoisted) { if (TraceLoopPredicate && hoisted) {
tty->print("Loop Predication Performed:"); tty->print("Loop Predication Performed:");
loop->dump_head(); loop->dump_head();
} }
#endif #endif
return hoisted; return hoisted;
......
...@@ -821,7 +821,7 @@ public: ...@@ -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);
......
/*
* 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) { }
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册