--- old/src/share/vm/opto/loopTransform.cpp 2015-03-19 12:50:34.188349100 -0700 +++ new/src/share/vm/opto/loopTransform.cpp 2015-03-19 12:50:33.988349100 -0700 @@ -1524,6 +1524,74 @@ } } +void PhaseIdealLoop::mark_reductions(IdealLoopTree *loop) { + if (SuperWordReductions == false) return; + + for (uint i = 0; i < loop->_body.size(); i++) { + Node *n = loop->_body[i]; + if (n != NULL && n->is_Phi()) { + PhiNode *phi = n->as_Phi(); + // for definitions which are loop inclusive and not tripcounts + if (phi != NULL && phi->is_tripcount() == false) { + uint len = n->len(); + Node *defNode = n->in(len - 1); + + if (defNode != NULL) { + Node *n_ctrl = get_ctrl(defNode); + if (n_ctrl != NULL && loop->is_member(get_loop(n_ctrl))) { + uint flags = defNode->flags(); + + // This is a loop carried depedence, set if needed + if ((flags & Node::Flag_is_loop_carried_dep) != Node::Flag_is_loop_carried_dep) + defNode->add_flag(Node::Flag_is_loop_carried_dep); + + // now test it to see if it fits the standard pattern for a reduction operator + switch (defNode->Opcode()) { + // the communitative operators + case Op_AddI: + case Op_AddL: + case Op_AddF: + case Op_AddD: + case Op_MulI: + case Op_MulL: + case Op_MulF: + case Op_MulD: + if ((flags & Node::Flag_has_reduction) != Node::Flag_has_reduction) + { + // To be a reduction, the arithmetic node must source the phi and provide a def to it + int end = defNode->req(); + for (int j = 1; j < end; j++) { + Node* in = defNode->in(j); + if (in == n){ + defNode->add_flag(Node::Flag_has_reduction); + break; + } + } + } + break; + + // the non communitative operators + case Op_DivI: + case Op_DivL: + case Op_DivF: + case Op_DivD: + case Op_SubI: + case Op_SubL: + case Op_SubF: + case Op_SubD: + // TODO: these need ordering constraints + break; + + default: + break; + } + } + } + } + } + } +} + //------------------------------dominates_backedge--------------------------------- // Returns true if ctrl is executed on every complete iteration bool IdealLoopTree::dominates_backedge(Node* ctrl) { @@ -2361,8 +2429,10 @@ // an even number of trips). If we are peeling, we might enable some RCE // and we'd rather unroll the post-RCE'd loop SO... do not unroll if // peeling. - if (should_unroll && !should_peel) - phase->do_unroll(this,old_new, true); + if (should_unroll && !should_peel) { + phase->mark_reductions(this); + phase->do_unroll(this, old_new, true); + } // Adjust the pre-loop limits to align the main body // iterations.