src/share/vm/opto/loopnode.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
hotspot Cdiff src/share/vm/opto/loopnode.cpp
src/share/vm/opto/loopnode.cpp
Print this page
rev 10221 : 8149745: C2 should optimize long accumulations in a counted loop
summary: Look for parallel iv for long adds
Reviewed-by:
*** 1741,1792 ****
//---------------------------replace_parallel_iv-------------------------------
// Replace parallel induction variable (parallel to trip counter)
void PhaseIdealLoop::replace_parallel_iv(IdealLoopTree *loop) {
assert(loop->_head->is_CountedLoop(), "");
CountedLoopNode *cl = loop->_head->as_CountedLoop();
! if (!cl->is_valid_counted_loop())
return; // skip malformed counted loop
Node *incr = cl->incr();
! if (incr == NULL)
return; // Dead loop?
Node *init = cl->init_trip();
Node *phi = cl->phi();
int stride_con = cl->stride_con();
// Visit all children, looking for Phis
for (DUIterator i = cl->outs(); cl->has_out(i); i++) {
Node *out = cl->out(i);
// Look for other phis (secondary IVs). Skip dead ones
! if (!out->is_Phi() || out == phi || !has_node(out))
continue;
PhiNode* phi2 = out->as_Phi();
! Node *incr2 = phi2->in( LoopNode::LoopBackControl );
// Look for induction variables of the form: X += constant
if (phi2->region() != loop->_head ||
incr2->req() != 3 ||
incr2->in(1) != phi2 ||
incr2 == incr ||
! incr2->Opcode() != Op_AddI ||
! !incr2->in(2)->is_Con())
continue;
// Check for parallel induction variable (parallel to trip counter)
// via an affine function. In particular, count-down loops with
// count-up array indices are common. We only RCE references off
// the trip-counter, so we need to convert all these to trip-counter
// expressions.
! Node *init2 = phi2->in( LoopNode::EntryControl );
! int stride_con2 = incr2->in(2)->get_int();
// The general case here gets a little tricky. We want to find the
// GCD of all possible parallel IV's and make a new IV using this
// GCD for the loop. Then all possible IVs are simple multiples of
// the GCD. In practice, this will cover very few extra loops.
// Instead we require 'stride_con2' to be a multiple of 'stride_con',
// where +/-1 is the common case, but other integer multiples are
// also easy to handle.
! int ratio_con = stride_con2/stride_con;
if ((ratio_con * stride_con) == stride_con2) { // Check for exact
#ifndef PRODUCT
if (TraceLoopOpts) {
tty->print("Parallel IV: %d ", phi2->_idx);
--- 1741,1798 ----
//---------------------------replace_parallel_iv-------------------------------
// Replace parallel induction variable (parallel to trip counter)
void PhaseIdealLoop::replace_parallel_iv(IdealLoopTree *loop) {
assert(loop->_head->is_CountedLoop(), "");
CountedLoopNode *cl = loop->_head->as_CountedLoop();
! if (!cl->is_valid_counted_loop()) {
return; // skip malformed counted loop
+ }
Node *incr = cl->incr();
! if (incr == NULL) {
return; // Dead loop?
+ }
Node *init = cl->init_trip();
Node *phi = cl->phi();
int stride_con = cl->stride_con();
// Visit all children, looking for Phis
for (DUIterator i = cl->outs(); cl->has_out(i); i++) {
Node *out = cl->out(i);
// Look for other phis (secondary IVs). Skip dead ones
! if (!out->is_Phi() || out == phi || !has_node(out)) {
continue;
+ }
PhiNode* phi2 = out->as_Phi();
! Node *incr2 = phi2->in(LoopNode::LoopBackControl);
// Look for induction variables of the form: X += constant
if (phi2->region() != loop->_head ||
incr2->req() != 3 ||
incr2->in(1) != phi2 ||
incr2 == incr ||
! (incr2->Opcode() != Op_AddI && incr2->Opcode() != Op_AddL) ||
! !incr2->in(2)->is_Con()) {
continue;
+ }
+ BasicType bt = incr2->Opcode() == Op_AddI ? T_INT : T_LONG;
// Check for parallel induction variable (parallel to trip counter)
// via an affine function. In particular, count-down loops with
// count-up array indices are common. We only RCE references off
// the trip-counter, so we need to convert all these to trip-counter
// expressions.
! Node *init2 = phi2->in(LoopNode::EntryControl);
! Node* stride2 = incr2->in(2);
! jlong stride_con2 = (bt == T_INT) ? stride2->get_int() : stride2->get_long();
// The general case here gets a little tricky. We want to find the
// GCD of all possible parallel IV's and make a new IV using this
// GCD for the loop. Then all possible IVs are simple multiples of
// the GCD. In practice, this will cover very few extra loops.
// Instead we require 'stride_con2' to be a multiple of 'stride_con',
// where +/-1 is the common case, but other integer multiples are
// also easy to handle.
! jlong ratio_con = stride_con2/stride_con;
if ((ratio_con * stride_con) == stride_con2) { // Check for exact
#ifndef PRODUCT
if (TraceLoopOpts) {
tty->print("Parallel IV: %d ", phi2->_idx);
*** 1795,1819 ****
#endif
// Convert to using the trip counter. The parallel induction
// variable differs from the trip counter by a loop-invariant
// amount, the difference between their respective initial values.
// It is scaled by the 'ratio_con'.
! Node* ratio = _igvn.intcon(ratio_con);
set_ctrl(ratio, C->root());
! Node* ratio_init = new MulINode(init, ratio);
! _igvn.register_new_node_with_optimizer(ratio_init, init);
set_early_ctrl(ratio_init);
! Node* diff = new SubINode(init2, ratio_init);
_igvn.register_new_node_with_optimizer(diff, init2);
set_early_ctrl(diff);
! Node* ratio_idx = new MulINode(phi, ratio);
! _igvn.register_new_node_with_optimizer(ratio_idx, phi);
set_ctrl(ratio_idx, cl);
! Node* add = new AddINode(ratio_idx, diff);
_igvn.register_new_node_with_optimizer(add);
set_ctrl(add, cl);
! _igvn.replace_node( phi2, add );
// Sometimes an induction variable is unused
if (add->outcnt() == 0) {
_igvn.remove_dead_node(add);
}
--i; // deleted this phi; rescan starting with next position
--- 1801,1837 ----
#endif
// Convert to using the trip counter. The parallel induction
// variable differs from the trip counter by a loop-invariant
// amount, the difference between their respective initial values.
// It is scaled by the 'ratio_con'.
! Node* ratio = (bt == T_INT) ? (Node*)_igvn.intcon((int)ratio_con) : (Node*)_igvn.longcon(ratio_con);
set_ctrl(ratio, C->root());
! Node* conv_init = init;
! if (bt == T_LONG) {
! conv_init = new ConvI2LNode(init);
! _igvn.register_new_node_with_optimizer(conv_init, init);
! set_early_ctrl(conv_init);
! }
! Node* ratio_init = MulNode::make(bt, conv_init, ratio);
! _igvn.register_new_node_with_optimizer(ratio_init, conv_init);
set_early_ctrl(ratio_init);
! Node* diff = SubNode::make(bt, init2, ratio_init);
_igvn.register_new_node_with_optimizer(diff, init2);
set_early_ctrl(diff);
! Node* conv_phi = phi;
! if (bt == T_LONG) {
! conv_phi = new ConvI2LNode(phi);
! _igvn.register_new_node_with_optimizer(conv_phi, phi);
! set_ctrl(conv_phi, cl);
! }
! Node* ratio_idx = MulINode::make(bt, conv_phi, ratio);
! _igvn.register_new_node_with_optimizer(ratio_idx, conv_phi);
set_ctrl(ratio_idx, cl);
! Node* add = AddNode::make(bt, ratio_idx, diff);
_igvn.register_new_node_with_optimizer(add);
set_ctrl(add, cl);
! _igvn.replace_node(phi2, add);
// Sometimes an induction variable is unused
if (add->outcnt() == 0) {
_igvn.remove_dead_node(add);
}
--i; // deleted this phi; rescan starting with next position
src/share/vm/opto/loopnode.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File