< prev index next >
src/share/vm/opto/loopTransform.cpp
Print this page
@@ -1522,10 +1522,78 @@
assert((cl->trip_count() & 1) == 0, "missed peeling");
do_unroll(loop, old_new, false);
}
}
+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) {
assert(ctrl->is_CFG(), "must be control");
Node* backedge = _head->as_Loop()->in(LoopNode::LoopBackControl);
@@ -2359,12 +2427,14 @@
// Double loop body for unrolling. Adjust the minimum-trip test (will do
// twice as many iterations as before) and the main body limit (only do
// 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.
if (should_align)
Unimplemented();
< prev index next >